Highlighting areas in leaflet using markers? - javascript

I'm trying to highlight an area surrounded by node markers. Currently, I'm doing this by creating polygons. Each node in the database is assigned a polygon ID and those with the same IDs are pushed into the array to act as the vertices of the same polygon.
However, as the data is retrieved from the database in the order they were entered into the table, polygon self-intersection happens like in the picture below:
Self-intersection in polygon
I've tried to sort the vertices by starting from the first and looking for the nearest node, then from that node I look for the nearest again and so on. It worked for some, but some cases still have self-intersection like this:
Self-intersection after sorting using nearest node
Is there any leaflet plugin that will allow me to highlight an area surrounded by nodes? Below is my code for sorting the vertices. All vertices of the same polygon ID are first pushed into the array "arr" before being sorted.
var i;
var j;
var flag = 0;
var sortedarray = [];
var finalarray = [];
for (j = 0; j < initiallength - 1; j++) {
if (flag == 0) {
finalarray.push(arr[0]);
arr.splice(0, 1);
flag++;
}
sortedarray = [];
for (i = 0; i < arr.length; i++) {
var x = L.GeometryUtil.distance(map, finalarray[j], arr[i]);
sortedarray.push(x);
}
var smallest = Math.min.apply(Math, sortedarray);
var x = sortedarray.indexOf(smallest);
finalarray.push(arr[x]);
arr.splice(x, 1);
}
var polygon = L.polygon(finalarray).setStyle(myStyle).addTo(map);

Related

How do I create bounds of a 2darray tilemap in Javascript?

I am creating a 2D ASCII game. Currently I have the world (leveldata) stored in a 2D array. Example:
"test2": [
["╔","═","═","═","═","═","═","═","═","═","╗","´","´","´","´","`","´","´","´","´","´"],
["║","▓","▓","▓","▓","▓","▓","▓","▓","▓","║","´","`","`","´","`","´","´","`","´","´"],
["║","▓","▓","▓","▓","▓","▓","▓","▓","▓","║","´","´","´","´","`","´","´","´","´","´"],
["║","▓","▓","▓","▓","▓","▓","▓","▓","▓","║","´","`","´","´","´","´","´","`","´","´"],
["╚","═","═","▓","▓","▓","▓","═","═","═","╝","´","´","´","´","´","`","´","´","´","´"],
["´","´","´","´","´","`","´","´","´","´","`","´","´","`","´","´","`","´","´","´","´"],
["´","´","`","´","´","´","´","´","´","╔","╗","´","´","´","´","´","´","´","`","´","´"],
["´","´","´","´","´","´","´","´","`","║","║","´","`","´","´","`","´","´","`","`","´"],
["´","´","´","´","´","´","´","`","´","║","║","´","´","´","´","`","´","`","`","´","´"],
["´","´","`","´","´","´","´","´","´","║","║","´","´","`","´","´","`","`","´","´","´"],
["´","´","´","´","´","´","`","´","`","║","║","`","´","´","´","´","`","´","´","`","´"]
]
I take this data, replace the tile where the player is and then paste it to the screen, like so:
I want to take this array that I paste to the screen, and crop it around the player with variable
bounds. Essentially remove any tiles that are a certain distance from a box around the player, so that the camera "follows" the player.
The problem is, tiles aren't removing the way I want them to and I am stuck on what I am supposed to do. Here is all I have so far, it takes in map data, bounds, and player position, and dumps out a custom array. I am trying just the upper bounds so far...
// Cropping the game screen using a camera.
function crop(width=5, height=5, x=1, y=1, map=[]) {
let topBound = y-height;
let bottomBound = y + height;
let rowsRemoved = [];
// Loop through and remove rows that are above or below the max.
for (let row = 0; row < map.length; row++) {
if (row < topBound) {
rowsRemoved.push(row);
}
}
for (let i = 0; i < rowsRemoved.length; i++) {
console.log(rowsRemoved[i]);
map.splice(rowsRemoved[i], 1);
}
console.log(rowsRemoved)
// Loop through and remove columns that are above or below the max.
// for (let row = 0; row < map.length; row++) {
// for (let column = 0; column < map[row].length; column++) {
// if (column < x-width || column > x+width) {
// map[row].splice(map[row].indexOf(map[row][column]), 1);
// }
// }
// }
console.log("----")
return map;
}
It turned out it was to slice the array instead of splice it, and take a totally different approach.
// Cropping the game screen using a camera.
function crop(width=5, height=5, x=1, y=1, map=[]) {
// Get the bounds and make sure they stay within the map's bounds.
let topBound = y - height;
if (topBound < 0) {
topBound = 0;
}
let bottomBound = y + height + 1;
let leftBound = x - width;
if (leftBound < 0) {
leftBound = 0;
}
let rightBound = x + width + 1;
let rowsRemoved = [];
// Remove rows that are above or below the max.
map = map.slice(topBound, bottomBound);
console.log(map)
// Remove columns that are above or below the max.
for (let row = 0; row < map.length; row++) {
map[row] = map[row].slice(leftBound, rightBound);
}
console.log("----");
return map;
}

How can sort an array by comparing to n-1

I am facing this problem in javascript : I have lot of random map coordinates(latitude,longitude) stored in an array like
var coordinates = [
[64,22],[55,33],[28,35],[...,...]
]
I also have a method that calculates distance between two of those points
like
var getDistance =function(point1,point2)
{
return L.dist(point1,point2);//leaflet method
}
then here is my problem :
how to sort my array to have the distance sorted by closest from first coordinate then closest to second, then closest to third, then closest to fourth... ? anyone have a solution for this... im lost :(
edit 1 :
I tried to resolve the problem with a nested for loop ... but the results seems to be wrong.
var cloestIndex = 1;
var closestDistance = 99999999;
for (var i = 0; i < coords.length; i++) {
for (var j = i + 1; j < coords.length; j++) {
if ((Map().distance(coords[i], coords[j]) < closestDistance) &&
(Map().distance(coords[i], coords[j]) != 0){
closestDistance = (Map().distance(coords[i], coords[j]));
closestIndex = j;
}
}
console.log("CD", closestDistance + "(" + closestIndex + ")");
finalArray.push(coords[closestIndex]);
coords.splice(closestIndex, 0);
cloestDistance = 9999999;
}
how to sort my array to have the distance sorted by cloest from first coordinate then cloest to second, then cloest to third, then cloest to fourth... ?
That's not called a "sort" because "closest distance to previous" is not an ordering. Sorting them by distance to a single point would be.
So to do what you want, you really should literally follow your description and first put the first coordinate in the result array, then find the closest-to-that in the rest and add it, then find the closest-to-that and so on until no more coordinates are left.

Correctly iterating over first n elements of an array in javascript

I have a trouble executing the following snippet. It is callback code for a larger python Bokeh plotting. Since my experience with javascript is limited I was drawing from this question on how to loop over an array in javascript.
This is the modified objects2 = ColumnDataSource(data=dict(x=[],y1=[],y2=[],y3=[], y4=[]))
var inds = cb_obj.get('selected')['1d'].indices; // Obtains column numbers
var d1 = m1.get('data'); // Obtains matrix with numbered columns that correspond to inds
var d2 = s2.get('data'); // Plotted data columns that get modified according to inds
var ys = ['y1','y2','y3','y4']; // Array of names of columns in d2/s2
var j, y, select= ys.slice(0,inds.length+1), // Limit number of columns to number of inds
//This piece is from the linked question - a loop through select (e.g only 'y1' and 'y2')
var len = select.length;
for(j=0; j<len; ++j) {
if (j in select) {
y = selected[j];
// For each selected name of a column
d2[y] = []; // Erase current value
// Fill the column from d1 (12 is just the length of the column)
for (var i = 0; i < 12; i++) {
d2[y].push(d1[inds[j]][i]),
}
}
}
s2.trigger('change');
The second loop was working just fine for a predefined number of y1,y2, when only two indices were passed to it. But my goal is to make the selection size dynamic i.e for a varying number of indices like [1,5,65,76] or [1,8] which is passed down from outside to inds, the code is to fill up appropriate number of ys so either y1,y2,y3,y4 or just y1,y2 with data from d1/m1.
From what I can tell the code "should" be doing just that , but I am obviously not seeing something.
For comparison here is the previous version of code that worked, but was limited to exactly two indices.
var inds = cb_obj.get('selected')['1d'].indices;
var d1 = m1.get('data');
var d2 = s2.get('data');
d2['y'] = []
d2['y2'] = []
for (i = 0; i < 12; i++) {
d2['y1'].push(d1[inds['0']][i]),
d2['y2'].push(d1[inds['1']][i])
}
s2.trigger('change');
Here is the whole thing (Python) with sample data for better visualization.
I figured it out. There was an extra comma at the end of this line
d2[y].push(d1[inds[j]][i])

algorithm for generating grid of points

I've got array of coordinates in following schema (x,y):
array = [[1,2],[1,5],[1,1],[2,2],[2,5],[2,1]]
I would like to do some process to achieve effect:
array1 = [[[1,2],[1,5],[1,1]],[[2,2],[2,5],[2,1]]]; array2 = [[[2,2],[2,5],[2,1]]]
and
array1a = [[[1,2],[2,2]]]; array2a = [[[1,5],[2,5]]]; array3a=[[[1,1],[2,1]]]
in other words I would like to get coordinates of all parallel and perpendicular lines.
I've came up with two double loops (one by x, and another by y) but maybe there is another faster(better) way
--
pseudo code:
for (var i = 0; i < length; i++) {
for (var j = 0; j < length2; j++) {
var x = points[i][j][0];
var y = points[i][j][1];
};
};
for (var i = 0; i < length2; i++) {
for (var j = 0; j < length; j++) {
var x = points[i][j][0] ;
var y = points[i][j][1] ;
};
};
EDIT
OK, here's the situation:
I've got this kind of rectangle, I've got coordinates of points (red mark) as array:
array = [[1,2],[1,5],[1,1],[2,2],[2,5],[2,1]]
and I want to make antoher array which will be like this:
array1 = [[[1,2],[1,5],[1,1]],[[2,2],[2,5],[2,1]]]
in above array there are coordinates of points thats one of green line containts. Those lines are parallel or perpendicular lines to sides of rectangle.
If you sort the points by X coordinate and then group them together by X coordinate, each group is a set of points on a vertical line.
Similarly, if you sort the points by Y coordinate and then group them together by Y coordinate, each group is a set of points on a horizontal line.
If this sounds simplistic, I apologize. But your initial description and the added diagram with your further explanation leads me to believe that it's what you're asking for.

Finding if a point is in a polygon

I have this code here that is attempting to work out if a point latLng passes through a polygon Maps.area.
Maps.ui.contains = function(latLng){
//poly.getBounds gets the 'box' around the polygon
if(!Maps.ui.getBounds().contains(latLng))
return false;
//So we dont need to check t/f, we either set it or we dont
var inPolygon = false;
var count = 0;
Maps.area.getPaths().forEach(function(el0, index0){
var last = el0.getLength() - 1;
el0.forEach(function(el1, index1){
count += Maps.ui.ray_intersect_segment(latLng, el1, el0.getAt(last));
last = index1;
});
});
if(Maps.area.getPaths().getLength()%2 == 0)
return count%2==0;
else
return count%2!=0;
}
var eps = 0.0001;
var inf = 1e600;
Maps.ui.ray_intersect_segment = function(point, i1, i2){
var p = point;
var segment = (i1.lng() > i2.lng())?[i2, i1]:[i1, i2];
p = (p.lng() == segment[0].lng() || p.lng() == segment[1].lng())?new google.maps.LatLng(p.lng() + eps):p;
if(p.lng() < segment[0].lng() || p.lng() > segment[1].lng() || p.lat() > [segment[0].lat(), segment[1].lng()].max())
return 0;
if(p.lat() < [segment[0].lat(), segment[1].lat()].min())
return 1;
var a = (segment[0].lat() != segment[1].lat())?(segment[1].lng() - segment[0].lng())/(segment[1].lat() - segment[0].lat()):inf;
var b = (segment[0].lat() != p.lat()) ? (p.lng() - segment[0].lng())/(p.lat() - segment[0].lat()):inf;
return (b > a)?1:0;
}
Maps.ui.getBounds = function() {
//Lets make a box
var bounds = new google.maps.LatLngBounds();
//Get all the points lines of the polly
var paths = Maps.area.getPaths();
for (var p = 0; p < paths.getLength(); p++)
//To store each path
var path = paths.getAt(p);
//Now lets expand the box
for (var i = 0; i < path.getLength(); i++)
//Add each point of the line to the 'box' making it bigger each time
bounds.extend(path.getAt(i));
//Reaturn the bounds, this has a contains method so we can check if the latLng is in it.
return bounds;
}
Array.prototype.max = function() {
return Math.max.apply(null, this)
}
Array.prototype.min = function() {
return Math.min.apply(null, this)
}
But I can't seem to work it out. For a simple triangle or square it works perfectly, but when we get to something like this it doesn't work because we can't figure out whether count should be even or odd
The Google Maps API v3 spherical geometry library has the poly.contains. Takes a LatLng and a Polygon and tells you if the point is in the polygon.
containsLocation(point:LatLng, polygon:Polygon)
This is a pretty standard problem for geographical information systems. There are several "standard" algorithms for solving the problem. The link below notes a few of them and provides an example. Note that the algorithms tend to break down in edge cases, such as when the polygon spans the extreme lat/lon boundaries such as the poles and meridian.
Polygon Algorithms

Categories

Resources