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
Related
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);
I have this project in paperjs:
var url = "http://www.clker.com/cliparts/q/I/s/P/E/3/yellow-umbrella-md.png";
raster = new Raster(url);
raster.rotate(10);
raster.scale(0.4);
var url2 = "https://images.vexels.com/media/users/3/145373/isolated/preview/98721f602aa3fadb040e0a161ab3f966-waterdrop-vislumbrante-vis-o-ilustra--o-by-vexels.png";
secondRaster = new Raster(url);
secondRaster.scale(0.9);
var count = 150;
var symbol = new Symbol(raster);
var secondSymbol = new Symbol(secondRaster);
for (var i = 0; i < count; i++) {
// The center position is a random point in the view:
var center = Point.random() * view.size;
var placedSymbol = symbol.place(center);
placedSymbol.scale(i / count);
}
function onFrame(event) {
// Run through the active layer's children list and change
// the position of the placed symbols:
for (var i = 0; i < count; i++) {
var item = project.activeLayer.children[i];
// Move the item 1/20th of its width to the right. This way
// larger circles move faster than smaller circles:
item.position.y += item.bounds.width / 80;
// If the item has left the view on the right, move it back
// to the left:
if (item.bounds.bottom > view.size.width) {
item.position.y = -item.bounds.width;
}
}
}
The first raster has a symbol works good, but the second can't make it work... I read about to add more than one symbol to project.activeLayer.children but don't work. Even if I do a group of an array with both symbols also don't show up.
I read in a post that symbols can't be added as a group. Being that be true, it should be ok to be added even though isolated...
Anybody had done something similar?
Thank you
There are some mistakes in your code:
The most important one, that make you think that the second raster doesn't work, is that you are creating the second raster with the variable url instead of url2. So both rasters use the same image as source...
You need to place the second symbol like you do with the first one otherwise it will never get rendered.
When iterating through active layer children, make sure to iterate over all children by using project.activeLayer.children.length (as you are placing count * 2 symbols).
When checking for bottom reaching items, use height instead of width.
Here is a sketch demonstrating the solution.
var COUNT = 10;
var raster = new Raster('http://www.clker.com/cliparts/q/I/s/P/E/3/yellow-umbrella-md.png');
raster.rotate(10);
raster.scale(0.4);
var secondRaster = new Raster('https://images.vexels.com/media/users/3/145373/isolated/preview/98721f602aa3fadb040e0a161ab3f966-waterdrop-vislumbrante-vis-o-ilustra--o-by-vexels.png');
secondRaster.scale(0.15);
var symbol = new Symbol(raster);
var secondSymbol = new Symbol(secondRaster);
for (var i = 1; i <= COUNT; i++) {
// first symbol
symbol.place(Point.random() * view.size).scale(i / COUNT);
// second symbol
secondSymbol.place(Point.random() * view.size).scale(i / COUNT);
}
function onFrame(event) {
for (var i = 0; i < project.activeLayer.children.length; i++) {
var item = project.activeLayer.children[i];
item.position.y += item.bounds.height / 80;
if (item.bounds.bottom > view.size.height) {
item.position.y = -item.bounds.height;
}
}
}
I'm trying to create a simulation of 150 mouses moving inside a 20x20 grid in p5.js (A processing like libary). First I'm spawning 150 mouses random places and everything goes fine. But after I have spawned the mouses I am trying to make them move to one of their neighbors. Instead of moving to one of the neighbors and make the current square empty it stays on the one that it already was one + it moves to the next one so instead of having 150 mouses i suddenly have 300... I have tried changing the code for hours but I can't find the proplem... Here is my code:
var w = 40;
var grid = [];
var mouses = 10;
var mouseAmount = [];
var Mouse;
var current;
function setup() {
createCanvas(800, 800);
cols = floor(width/w)
rows = floor(height/w)
// frameRate(60);
for (var j = 0; j < rows; j++) {
for ( var i = 0; i < cols; i++) {
var cell = new Cells(i,j);
grid.push(cell);
}
}
amount = new Amount;
}
function draw() {
background(51);
for ( var i = 0; i < grid.length; i++) {
grid[i].show();
}
amount.run();
}
function index(i, j) {
if (i < 0 || j < 0 || i > cols-1 || j > rows-1 ) {
return -1;
}
return i + j * cols;
}
function Cells(i, j) {
this.i = i;
this.j = j;
this.active = false;
this.moveCell = function() {
var neighbors = [];
var top = grid[index(i, j -1)];
var right = grid[index(i+1, j)];
var bottom = grid[index(i, j+1)];
var left = grid[index(i-1, j)];
if (top) {
neighbors.push(top)
}
if (right) {
neighbors.push(right)
}
if (bottom) {
neighbors.push(bottom)
}
if (left) {
neighbors.push(left)
}
if(neighbors.length > 0) {
var r = floor(random(0, neighbors.length));
return neighbors[r];
} else {
return undefined;
}
}
this.show = function() {
var x = this.i*w;
var y = this.j*w;
stroke(255);
noFill();
rect(x,y,w,w);
if(this.active == true) {
fill(155, 0, 255, 100)
rect(x, y, w, w)
}
}
}
function Amount() {
this.run = function() {
var r = floor(random(grid.length))
for (var i = 0; i < mouses; i++) {
var mouse = grid[r];
mouseAmount.push(mouse)
}
if (mouseAmount.length < 1499) {
for (var i = 0; i < mouseAmount.length; i++) {
mouseAmount[i].active = true;
}
}
if (mouseAmount.length > 1499) {
Next();
}
}
}
function Next(i,j) {
for (var i = 0; i < mouseAmount.length; i++) {
current = mouseAmount[i];
var nextCell = current.moveCell();
if (nextCell) {
nextCell.active = true;
current.active = false;
current = nextCell;
}
}
}
Thank you in advance :)
I don't really understand exactly what your code is supposed to do, but a few things stand out to me about your code:
Problem One: I don't understand how you're iterating through your grid array. You seem to be iterating over mouseAmount, which seems to hold random cells from the grid for some reason? That doesn't make a lot of sense to me. Why don't you just iterate over the grid array directly?
Problem Two: You then move the cells randomly to a neighbor, but you don't take into account whether the neighbor is already active or not. I'm not sure what you want to happen, but this seems a bit strange.
Problem Three: Usually with simulations like this, you have to copy the next generation into a new data structure instead of modifying the data structure as you step through it.
The biggest problem is that you haven't really explained what you want your code to do, or what this code does instead, or how those two things are different. But if I were you, I'd make the following changes:
Step One: Iterate over your grid array in a more reasonable way. Just iterate over every index and take the appropriate action for every cell. If I were you I would just use a 2D array and use a nested for loop to iterate over it.
Step Two: Make sure your logic for moving to a neighbor is correct. Do you want cells to move to already active cells?
Step Three: Make a copy of the grid before you modify it. Think about it this way: as you iterate over the grid, let's say you move a cell down one row. Then you continue iterating, you'll reach the newly active cell again. In other words, you'll touch the same active cell twice in one generation, which is definitely going to mess you up.
A word of advice: get this working for a single active cell first. It's really hard to tell what's going on since you have so many things going on at one time. Take a step back and make sure it works for one active cell before moving up to having a whole grid.
I am attempting to animate several markers on a map with a for loop, but instead of animating them as intended, the code below is adding the consecutive coordinates simultaneously (full code here):
for (j in jsonObj[i]) {
for (k in jsonObj[i][j]) {
if (jsonObj.hasOwnProperty(i)) {
subindex = Object.keys(jsonObj[i][j][k]);
sublenght = subindex.length;
for (cnt = 0; cnt < sublenght; cnt += 1) {
lat = [],
lon = [],
lat[cnt] = (jsonObj.flightPositions[j].positions[cnt].lat)
lon[cnt] = (jsonObj.flightPositions[j].positions[cnt].lon)
var marker = new L.Marker.movingMarker([[lat[cnt], lon[cnt]]], [2500], {autostart: true}).addTo(map);
};
}
}
}
I tried using closures, always getting the same result. My most recent attempt can be seen here. I guess there is something wrong with it, but what I am most afraid is that my whole approach may be wrong. I was hoping that anyone could throw me a hint. Any help appreciated!
According to Leaflet.MovingMarker plugin usage, you should create only 1 marker (per moving marker you need), and pass it directly an array of positions.
L.movingMarker(<LatLng[]> latlngs, <Number[]> durations [,<Object> options]);
In your code you create 1 marker per position, with only the current position.
I will not build on your JSFiddle as it looks far more complicated than probably necessary (do not know why you ever try some IIFE's), so building on the code you posted, you would have something like:
for (j in jsonObj[i]) { // i === "flightPositions"
for (k in jsonObj[i][j]) { // j === array index, k === "positions"
if (jsonObj.hasOwnProperty(i)) { // should have been checked before
subindex = Object.keys(jsonObj[i][j][k]); // indices of array
sublenght = subindex.length; // could have just done jsonObj[i][j][k].length
var coordinates = [];
for (cnt = 0; cnt < sublenght; cnt += 1) { // iterates in positions array
coordinates.push([
jsonObj.flightPositions[j].positions[cnt].lat,
jsonObj.flightPositions[j].positions[cnt].lon
]);
};
// outside the positions array for loop.
var marker = L.Marker.movingMarker(coordinates, 2500, {
autostart: true
}).addTo(map);
}
}
}
just wondering if anyone would be able to tell me how to solve an issue that I've been running into? The user puts in coordinates (ex: 85.231,40.213) into a text area, which populate and array, splits them, and then attempts to create a marker where the user specified.
var stringArray = document.getElementById("geos").value.split('\n');
var x = [];
var y = [];
var cords = [];
var array = stringArray.split(','); //splits up array by ","
var j = 0;
for (var i = 0; i < array.length; i++) //assigns broken up array into x and y values
{
x[j] = array[i];
i++;
y[j] = array[i];
j++;
}
var textarea = document.getElementById("test");
//textarea.value = stringArray.join("\n");
//textarea.value = y;
for (var i = 0; i < stringArray.length; i++) //assigns x and y variables to coordinates
{
cords[i] = new google.maps.LatLng(x[i],y[i]);
}
textarea.value = cords.join("\n");
for ( var i = 0; i < cords.length; i++ ) //code that plots all the points in the array
{
var marker = new google.maps.Marker({ //create a new marker
position: cords[i],
map: map,
})
map.addOverlay( marker );
}
When I add ".toString()" in between "stringArray" and "split(",")" I'm able to output the items to another text area, however it seems that the information does not want to display. Any insights?
Thanks
map: map,
that last comma will cause a syntax error, remove it.
What you probably need to do is make sure that your latlng coordinates are correctly converted from strings to numbers. e.g. this might help, changing this line:
cords[i] = new google.maps.LatLng(x[i],y[i]);
to this:
cords[i] = new google.maps.LatLng(parseFloat(x[i]), parseFloat(y[i]));