How to store multi connected waypoints - javascript

I am trying to create a basic 2D road system on a grid. Currently I have a list of staight lines but they are not connected to each other.
The part I am stuck on is how I construct the data and store my data so I know which waypoint points to which ever waypoint (more than one way point can connect to any other way point).
So currently if you image i have this as my data:
var point = [];
point[0] = {'x':2,'y':6};
point[1] = {'x':2,'y':8};
point[2] = {'x':6,'y':9};
point[3] = {'x':7,'y':2};
Now suppose point 0 connects to points 2 and 3. And point 1 connects to point 3.
What would be the best way to store the information that these points are linked, also allowing me then to look up and obtain properties of the object relating to a connected waypoint (which would mainly be useful for pathfinding in the future).
For example I may need to find a waypoint at a given x or y position. Or i may want to obtain relevant waypoint data that are connected to for example point 1, such as their x and y position and what ever waypoints may connect to them too.

The road network can be represented by an adjacency list. Basically, each point will be given a list (which could be implemented by an array) containing the indices which can be reached from it. In your example, this can be expressed as follows.
var point = [];
point[0] = {'x':2,'y':6, 'neighbors':[2,3]};
point[1] = {'x':2,'y':8, 'neighbors':[3]};
point[2] = {'x':6,'y':9, 'neighbors':[0]};
point[3] = {'x':7,'y':2, 'neighbors':[0,1]};

Related

Check if list of latitude, longitude are withing range

I'm having a problem
I would like to ask what the most efficient way is to check if latitude and longitude coordinates are inside a range (for example 100 meters) from a list of latitudes and longitude points.
For example I have this list of coordinates:
[[48.34483,51.16.24517],[48.484,16.2585],[48.361,51.87739419],[6.38477205,51.87745015],[48.3645,51.16.73167],[6.38391099,51.87755068],[48.3575,16.725],[6.38380232,51.87720004],[6.38376297,51.87708017],[6.38375183,51.87704018],[6.38373055,51.8769829]]
I would like somehow that all points that are in a specific range (100m for example),
to be somehow grouped.
Is there any way how I can indicate that for example from the above list:
[48.484,16.2585],[48.361,51.87739419] and [48.3575,16.725]
are in a radius of 100m ( distance between these points is less then 100m) and they should be groped
Sounds like a great question for a GIS professional; you could perhaps post on gis.stackexchange.com. Are you using a mapping technology where you already have access to an API? The functionality that you're looking for are referred to as geometric operations. I'd start by looking into geometry functions available in an API which calculate the distance between points. You could find the geometric center of all of the points, then request the geometry API to create a buffer around that point. Next, query if each point falls within that buffer.
Found a post which might help with finding the center of the points here:
How do I find the center of a number of geographic points?
Also found a post on stackexchange which sounds very similar to yours, only the post is in reference to ArcGIS and the Point Distance (Analysis) tool:
https://gis.stackexchange.com/q/91571/81346
Ideally you'd use a geospatial db for this, to avoid performance issues when dealing with increasing numbers of points. MySQL, Postgres etc all support geospatial functions.
But as you've tagged your question with javascript, I'll post a JS solution. There's an npm package called haversine - with it, you should be able to loop through each point and return the other points that are within 100m. Something like:
// bring in haversine from npm
var haversine = require("haversine");
// define the full list of points
var data = [
[48.34483,51.1624517],
[48.484,16.2585],
[48.361,51.87739419],
[6.38477205,51.87745015],
[48.3645,51.1673167],
[6.38391099,51.87755068],
[48.3575,16.725],
[6.38380232,51.87720004],
[6.38376297,51.87708017],
[6.38375183,51.87704018],
[6.38373055,51.8769829]
];
var points = data.map(point => new Object({latitude: point[0], longitude: point[1]}));
// var to store results in
var results = [];
// loop through the points
points.forEach((pair) => {
var nearby = points;
// filter the full list to those within 100m of pair
nearby.filter(point => haversine(pair, point, {unit: 'mile'}) <= 100);
results.push({
'point': pair,
'nearby': nearby
});
});
console.log(results);
Note: I corrected some of the points in your list, which had double decimals so weren't valid

High Performance Coordinate System - Three.js

Conceptual Question
I am building a flight simulator in Three.js. I intend to rip CSV data for Latitude, Longitude, and Elevation from Google Earth and transfer it into arcGIS to create a Digital Elevation Model (DEM). I then want to create the terrain based on the DEM. I already have a splat map texture shader I wrote and things are looking good.
However, I will need to add models and more specifically text and landing zones for the towns. This will require accurate XYZ coordinates.
I figure this is an interesting problem. I have seen one question before on stackoverflow similar to this but it was not quite to the same depth I'm looking for.
1) How to create coordinate system that maps actual XYZ, Latitude, Longitude, Elevation data to a PlaneBufferGeometry?
My assumption is that if I take a hypothetical 100,000 x 100,000 map sample then I will need to create a Plane that has matching vert count and then maps 1:1.
new THREE.PlaneBufferGeometry( 100000, 100000, 100000, 100000 );
Then the trickier part of mapping lat long coordinates to this. Perhaps just a multiplier like * 100 or so per lat, long degrees?
2) How to create the most efficient data structure for this. It will contain a lot of data.
I am thinking the most efficient data structure would be an array with Z integers.
let vertArray = new Array(10000000000);
for (i = 0; i < 9999999999; i++) {
vertArray[i] = planeBufferGeometry.vertices[i].z;
}
Each 100,000 in the array would represent a Y coordinate, while each i value in said sections would be an X coordinate. The value of the Z coordinate would be stored in the array itself.
So hypothetically if I wanted to get X: 3, Y: 4, Z: ? it would be...
const xCoord = 3,
yCoord = 4,
index = (yCoord * 100000) + xCoord,
zCoord = vertArray[index];
This is the smallest overhead approach I can think of... defining Array length ahead of time, keeping the array one dimensional, filling with only integers. Any better ideas? Perhaps creating an array would be unneeded and I could create an equation that pulls vert data directly from the rendered mesh?
3) Are there ways to decrease the impact of large data stored in browser memory?
I have yet to implement this but the idea of a 10 Million Length array in the browser is quite a lot in my mind. I would prefer being able to load the entire thing rather than doing some sort of AJAX call when the helicopter gets near the edge of a sub-plane. Think "zones" in MMORPG's.

Compute Voronoï diagram on a large dataset of very close points

I have a large dataset of geographical points (around 22 000 points, but I could be more in the future) and I need to compute their Voronoï diagram. I first project my points from (lat,lng) to (x,y) (using latLngToLayerPoint() from Leaflet) and then compute the diagram based on a Javascript implementation of Fortune's algorithm . I recover each cells of the diagrams or more precisely va and vb, being respectively :
"A Voronoi.Vertex object with an x and a y property defining the start
point (relative to the Voronoi site on the left) of this Voronoi.Edge
object."
and
"A Voronoi.Vertex object with an x and a y property defining the end
point (relative to Voronoi site on the left) of this Voronoi.Edge
object."
(cf. Documentation)
Finally, I project back these points to display the diagram using leaflet. I know that, in order to compute the diagram each point needs to be unique, so I get rid of duplicates before computing the diagram. But the thing is, I end up with a pretty bad result (non-noded intersections, complex polygons):
Close-up
I have holes in the diagram and I'm not sure why. The points are house Address so some of them, even if they are not equals, are really (really) close. And I wonder if the issue doesn't come from the projection (if (lat1,lng1) and (lat2,lng2) are almost equals, will (x1,y1) and (x2,y2) be equals ?). I strongly suspect that is where the issue come from, but I don't know how to workaround (establish a threshold ?)
Edit : I precise that I delete the duplicates after the projection, so it's not about the precision of the projection but more about what happen if two points are one-pixel apart ?
So I found the solution to my problem, I post it in case of anyone need to compute a Voronoï diagram on a map using Leaflet and Turf and is having troubles implementing the Fortune's algorithm (until turf-voronoi works).
Other sources of how to compute a Voronoï diagram on map can be found (but using d3) (I think d3 also use this Javascript implementation of Fortune's algorithm)
The problem was not caused by the size of the dataset or the proximity of the points, but by how I recovered the cells.
So you first need to project your point from (lat,lng) to (x,y)(using latLngToLayerPoint()), compute the diagram : voronoi.compute(sites,bbox), where the sites are your points looking like this [ {x: 200, y: 200}, {x: 50, y: 250}, {x: 400, y: 100} /* , ... */ ] (note that your sites needs to be unique) and if you want the frame of the screen for your current zoom to be your bbox juste use :
var xl = 0,
xr = $(document).width(),
yt = 0,
yb = $(document).height();
Once you computed the diagram, just recover the cells (be carfull, if you want the right polygons you need the edges to be counterclockwise ordered (or clockwise ordered, but you them to be ordered), thankfully the algorithm provides the half edges of a given Voronoï.Vertex counterclockwise ordered). To recover the vertex of each cell you can use either getStartpoint() or getEndpoint() without forgetting to project them back from (x,y) to (lat,lng) (using layerPointToLatLng())
diagram.cells.forEach(function (c) {
var edges=[];
var size = c.halfedges.length;
for (var i = 0; i < size; i++) {
var pt = c.halfedges[i].getEndpoint();
edges.push(map.layerPointToLatLng(L.point(pt.x,pt.y)));
};
voronoi_cells.push(L.polygon(edges));
});
Finally, you have to use a FeatureCollection to display the diagram :
I highly recomment you don't implement a Voronoi tesselation algorithm by yourself, and use https://github.com/Turfjs/turf-voronoi instead.

Get pairs of point coordinates for Daubechies wavelets generated with scipy.daub in Python

I've been trying to get the coordinates of the points that make up a Daubechies wavelet generated with scipy.daub, in order to send them across a websocket and have them plotted on a Canvas.js dynamic chart.
I managed to send the data over to the browser and have the points plotted on the chart (so there's no issue there), but all I get is sawtooth waveforms. I realised this is due to the fact that for each Y coordinate I receive, I increase the x value by 1.
However, perfect Daubechies wavelets are plotted using matplotlib.pylab and the returned list of points contains the y values, as far as I can tell. Here's how I generate the wavelets (it's meant to become an ECG simulator btw):
def generate_waves(hr, n):
global ecg
interval = 1.0 * 60 / hr
rr = [interval + random.uniform(0.0, 0.1 * interval) for i in range(n)]
fs = 1000.0 # sampling rate
pqrst = scipy.signal.daub(9)
ecg = scipy.concatenate([scipy.signal.resample(pqrst, int(r*fs)) for r in rr])
t = scipy.arange(len(ecg))/fs
pylab.plot(t, ecg)
pylab.show()
So, since the ecg list returns the y values, is there any way I can get hold of the x values so I can pass them through the websocket together and properly plot them on the chart?
Cheers!
I eventually figured it out. The x values are given by t. Pretty stupid of me not to have seen this, I know.
Thanks anyway!

How to handle collisions with tile id javascript

Ive written a small game in JavaScript with the html5 canvas and am at the point of collision detection and getting rather confused.
I build my levels in tiled and then import the saved JSON file into the game.
In my level draw function i have a check to see if there are any layer properties and if the layer properties are collisions. If it does, that layer is returned and the loop carries on. When finished, the layer that was returned with collisions gets put through another loop so that the the tile values can be put into an array.
So in this array i have i have a series of arrays depending on how many rows of tiles there are in the layer, and these rows hold the data for that row for each tile.
What i would like to do is when the player x/y is in one of the tiles which doesn't equal 0, then collide.
How would i do this if all i have is the value that is in that tile space?
Here is a link to the live version of the game so you can see for yourself how the tiles are stored, i have put in some console.logs so you might want to use firebug or equivalent to look at that. To log in use
Username - guest
password - guest
TO clarify my question is: How do i create collisions between my player x/y and a tile value??
Thanks very much
UPDATE
Ok so i think im nearly there, my problem at the moment is how do i read the objects x and y out of the array and then check the collision, at the moment the collision detection on works with the last tile in the array (the bottom right of the screen), here is the code i implemented to go through the array:
this.check_coll = function(array,posX, posY){
var collided = false,
block_x,
block_y,
block_cx,
block_cy,
combined_hw = 32,
combined_hh = 32,
player_cx = posX+(32/2),
player_cy = posY+(32/2);
array.forEach(function(value,i){
//get obj x
block_x = value[1];
//get obj y
block_y = value[2];
block_cx = block_x+(32/2);
block_cy = block_y+(32/2);
collided = Math.abs(player_cx - block_cx)< combined_hw
&& Math.abs(player_cy - block_cy)< combined_hh;
});
return collided;
}
Any ideas guys??

Categories