Given a poly-line path in 2D (like a GPS trace) I am interested in finding all points where the path gets close to existing landmarks. See the diagram below. This could be considered a problem Strava is solving when it reports running time between landmarks.
The landmarks have a small radius and I am only interested in them when the path crosses through that radius - finding the red dot where the paths is closest to the landmark.
There are many more landmarks than points on the paths.
Given a line segment and a landmark it is not difficult to compute the minimum distance using the vector dot product. The problem is to efficiently find the line segments that pass through landmarks.
I am not looking for code but the general algorithms and data structures to make this efficient - I lack the background in geometry where this problem is located.
The following properties could be exploited:
Using the bounding box of the path, the landmarks to be considered could be cut down. Landmarks could be stored in a quad-tree or 2d-tree for this.
The points of the paths form a sequence. One could walk along the paths only considering the next landmark that could come within reach.
Landmarks are static, paths change.
The bird's eye view of multiple proximity data structures including quad- and 2d-trees is that you have a tree where
Each leaf has a site (here, a landmark point);
Each interior node has some data that gives a lower bound on the nearest site in its sub-tree.
The lower bound doesn't have to be the minimum; we could just use 0 everywhere (and thereby recover the brute force algorithm). This is the same idea as admissible heuristics in the A* algorithm.
Then to find all sites within some distance r of a query point, we traverse the tree but skip sub-trees where the lower bound is greater than r.
Thing is, this works for query line segments too (and many other geometric primitives besides). All we need is code to compute
The distance from a query primitive to a site,
A lower bound on the distance from a query primitive to sites in a sub-tree.
You already have the first. With quad- or 2d-trees, for the second, you could use a line-segment-to-box distance, or you could implement something simpler (e.g., maximum separation in either the horizontal or vertical dimension).
Related
I'm working on my bachelor thesis (on Computer Science) and right now I'm having a problem about finding shortest path between two points on 3D triangular mesh that is manifold. I already read about MMP, but which computes distance function $d(x)$ between given point and vertex $x$ on mesh.
I got to know that the problem I'm solving is named Geodesics but What I really couldn't find is some good algorithm which uses A* for finding shortest path between two given points on two given vertices.
I 'invented' also algorithm which uses A* by using Euclidian Distance Heuristics and correction after finding new Point on any Edge..
I also have edges saved in half-edge structure.
So my main idea is this:
We will find closest edge by A* algorithm and find on this edge point with minimalizing function $f(x) + g(x)$ where $f$ is our current distance and $g$ is heuristics(euclidean distance)
Everytime we find new edge, we will unfold current mesh and find closest path to our starting point
So now my questions:
Do you know some research paper which talks about this problem ??
Why nobody wrote about algorithm that uses A* ??
What are your opinions about algorithm I proposed ?
Here are some papers and tools related to finding geodesics (or approximations) on a surface mesh:
A Survey of Algorithms for Geodesic Paths and Distances
You Can Find Geodesic Paths in Triangle Meshes by Just Flipping Edges (code)
The Vector Heat Method
(code)
You can find more papers in the survey paper.
I implemented the algorithm you mentionned (MMP) a long time ago and it's quite difficult to get it right and quite time consuming since the number of splits along an edge grows quite fast.
I am no expert in the matter so read with prejudice. Also sorry this is more of a comment than answer...
First You should clarify some things:
the mesh is convex or concave?
are the path always on surface or can fly between faces on the outside (if concave) but never inside?
are the start/end points on edges of faces or can be inside?
Assuming concave, points on edges and only surface paths...
I think the graph A* approach is unusable as there is infinite possible paths between point and any edge of the same face so how you test all of them?
If you really want A* then you can do something similar to raster A*
so resample all your edges to more points
so either n points or use some density like 10 points per average edge length or some detail size.
use graph A* on resampled points (do not handle them as edges anymore)
However this will produce only close to shortest path so in order to improve the accuracy you should recursively resample the edges near used point with higher and higher density until the distance between resampled points get smaller than accuracy.
Another option would be using something similar to CCD (cyclic coordinate descent) so:
create plane that goes through your 2 points and center of your mesh
create path that goes through all intersection of plane and faces between the 2 points (use the shorter on from the 2 options)
iterativelly move intersections back and forward and use greedy approach to get the result
However this might get stuck in local minima... You could use search/fitting approaches instead but those will get very slow with increasing number of faces
I got the feeling you might also do this using RANSAC ...
From my point of view I think the first A* approach is the most promising, you just need linked list of points per each edge and one cost counter per each its point from this you can simply encode even the recursive improvement of accuracy. It can be done even in-place so no reallocation needed in the recursion ... And also the algo is not complicated so you should have no problems implementing it, and the result is guaranteed which is not the case with other approaches I mention... Another pros is that it can be used even if start/endpoint does not belong to edge...
Given a polygonal subdivison S and a set of points P, find the closest line segment in S for each point (in 2-d space).
In my setting, I have hundreds of thousands of segments and a couple thousand points.
Checking each line for each point would take too long. Is there an efficient algorithm for this?
I was considering multiple options, but can't figure out which is best.
Build a trapezoidal map and query the face each point is in. Then go over the edges of the face (in the subdivision) to find the nearest line.
Build a range tree or segment tree. Query a box around the point and find the closest line segment in it. There has to be a segment in the box for this to find anything.
Build a line segment voronoi diagram. Each face describes the nearest segment, but I wouldn't know how to do a point query, since the edges can be parabolic arcs.
What is a good high-level approach for this problem?
Nearest Neighbor in Postgis
The approach of Postgis is to use R-trees with a custom search algorithm. While going down the tree like in a regular query, they keep track of the minimum and maximum distance to objects in the bounding regions they encounter in the tree. Each encountered branch of the tree is added to an Active Branch List (ABL), which are pruned using the distance metrics.
They pick a branch's bounding region in the ABL and apply the algorithm recursively. At a leaf (an object like a line segment), it updates the variable nearest. When returning from the recursion, they apply the nearest variable for more pruning of the ABL, repeating until the ABL is empty.
The theoretical worst case is linear per query, but it has much better results in practice.
I'm currently struggling in finding an algorithm if a path is possible or not.
I have a field of points, the positions of these points are fully random. I have also a starting point, and a destination point. On my starting point I can jump to any point around the starting point in a limited radius, and continue the same from there, but only with a limited amount of jumps. Performance in this case is important! Existant algorithms like Dijkstra won't help me here.
Any idea?
You could construct an undirected graph with the points as vertices. Each of the edges connects two points which are no further apart than the jump distance limit. Once this graph is constructed, you can find the shortest path with traditional algorithms.
To construct the graph, you could assign the points to a grid of 2D matrix cells. The cell hight and width is the jump radius limit. Candidate points for an edge for a given point have to belong to its matrix cell or directly adjacent cells. This reduces the construction time.
A further speedup could be to restrict a first version of the graph to those grid cells which are located near the direct line-of-sight between start and end point. Only if the search is not sucessfull, you could broaden the search area and try again.
If start and end point are further apart than radius limit times jump limit, no feasible path exists.
Just in case someone want have a solution:
Since the amount of jumps are limited I've created a radial grid, where the maximum radius is the amount of circles multiplied by their own radius.
After that I simply use an A-star path finder. (I used one existant by http://www.rapidfirestudio.com)
Imagine I am implementing Dijkstra's algorithm at a park. There are points and connections between those points; these specify valid paths the user can walk on (e.g. sidewalks).
Now imagine that the user is on the grass (i.e. not on a path) and wants to navigate to another location. The problem is not in Dijkstra's algorithm (which works fine), the problem is determining at which vertex to begin.
Here is a picture of the problem: (ignore the dotted lines for now)
Black lines show the edges in Dijkstra's algorithm; likewise, purple circles show the vertices. Sidewalks are in gray. The grass is, you guessed it, green. The user is located at the red star, and wants to get to the orange X.
If I naively look for the nearest vertex and use that as my starting point, the user is often directed to a suboptimal path, that involves walking further away from their destination at the start (i.e. the red solid path).
The blue solid path is the optimal path that my algorithm would ideally come up with.
Notes:
Assume no paths cross over other paths.
When navigating to a starting point, the user should never cross over a path (e.g. sidewalk).
In the image above, the first line segment coming out of the star is created dynamically, simply to assist the user. The star is not a vertex in the graph (since the user can be anywhere inside the grass region). The line segment from the star to a vertex is simply being displayed so that the user knows how to get to the first valid vertex in the graph.
How can I implement this efficiently and correctly?
Idea #1: Find the enclosing polygon
If I find the smallest polygon which surrounds my starting point, I can now create new paths for Dijkstra's algorithm from the starting point (which will be added as a new vertex temporarily) to each of the vertices that make up the polygon. In the example above, the polygon has 6 sides, so this would mean creating 6 new paths to each of its vertices (i.e. the blue dotted lines). I would then be able to run Dijkstra's algorithm and it would easily determine that the blue solid line is the optimal path.
The problem with this method is in determining which vertices comprise the smallest polygon that surrounds my point. I cannot create new paths to each vertex in the graph, otherwise I will end up with the red dotted lines as well, which completely defeats the purpose of using Dijkstra's algorithm (I should not be allowed to cross over a sidewalk). Therefore, I must take care to only create paths to the vertices of the enclosing polygon. Is there an algorithm for this?
There is another complication with this solution: imagine the user now starts at the purple lightning bolt. It has no enclosing polygon, yet the algorithm should still work by connecting it to the 3 points at the top right. Again, once it is connected to those, running Dijkstra's is easy.
Update: the reason we want to connect to one of these 3 points and not walk around everything to reach the orange X directly is because we want to minimize the walking done on unpaved paths. (Note: This is only a constraint if you start outside a polygon. We don't care how long you walk on the grass if it is within a polygon).
If this is the correct solution, then please post its algorithm as an answer.
Otherwise, please post a better solution.
You can start off by running Dijkstra from the target to find its distance to all vertices.
Now let's consider the case where you start "inside" the graph on the grass. We want to find all vertices that we can reach via a straight line without crossing any edge. For that we can throw together all the line segments representing the edges and the line segments connecting the start point to every vertex and use a sweep-line algorithm to find whether the start-vertex lines intersect any edge.
Alternatively you can use any offline algorithm for planar point location, those also work with a sweep line. I believe this is in the spirit of the more abstract algorithm proposed in the question in that it reports the polygon that surrounds the point.
Then we just need to find the vertex whose connection line to the start does not intersect any edge and the sum d(vertex, target) + d(vertex, start) is minimum.
The procedure when the vertex is outside the graph is somewhat underspecified, but I guess the exact same idea would work. Just keep in mind that there is the possibility to walk all around the graph to the target if it is on the border, like in your example.
This could probably be implemented in O((n+m) log m) per query. If you run an all-pairs shortest path algorithm as a preprocessing step and use an online point location algorithm, you can get logarithmic query time at the cost of the space necessary to store the information to speed up shortest path queries (quadratic if you just store all distance pairs).
I believe simple planar point location works just like the sweep line approaches, only with persistent BSTs to store all the sweepline states.
I'm not sure why you are a bothering with trying to find a starting vertex when you already have one. The point you (the user) are standing at is another vertex in of itself. So the real question now is to find the distance from your starting point to any other point in the enclosing polygon graph. And once you have that, you can simply run Dijkstra's or another shortest path algorithm method like A*, BFS, etc, to find the shortest path to your goal point.
On that note, I think you are better off implementing A* for this problem because a park involves things like trees, playgrounds, ponds (sometimes), etc. So you will need to use a shortest path algorithm that takes these into consideration, and A* is one algorithm that uses these factors to determine a path of shortest length.
Finding distance from start to graph:
The problem of finding the distance from your new vertex to other vertices can be done by only looking for points with the closest x or y coordinate to your start point. So this algorithm has to find points that form a sort of closure around the start point, i.e. a polygon of minimum area which contains the point. So as #Niklas B suggested, a planar point algorithm (with some modifications) might be able to accomplish this. I was looking at the sweep-line algorithm, but that only works for line segments so that will not work (still worth a shot, with modifications might be able to give the correct answer).
You can also decide to implement this algorithm in stages, so first, find the points with the closest y coordinate to the current point (Both negative and positive y, so have to use absolute value), then among those points, you find the ones with the closest x coordinate to the current point and that should give you the set of points that form the polygon. Then these are the points you use to find the distance from your start to the graph.
In a cubic box I have a large collection points in R^3. I'd like to find the k nearest neighbors for each point. Normally I'd think to use something like a k-d tree, but in this case I have periodic boundary conditions. As I understand it, a k-d tree works by partitioning the space by cutting it into hyper planes of one less dimension, i.e. in 3D we would split the space by drawing 2D planes. For any given point, it is either on the plane, above it, or below it. However, when you split the space with periodic boundary conditions a point could be considered to be on either side!
What's the most efficient method of finding and maintaining a list of nearest neighbors with periodic boundary conditions in R^3?
Approximations are not sufficient, and the points will only be moved one at a time (think Monte Carlo not N-body simulation).
Even in the Euclidean case, a point and its nearest neighbor may be on opposite sides of a hyperplane. The core of nearest-neighbor search in a k-d tree is a primitive that determines the distance between a point and a box; the only modification necessary for your case is to take the possibility of wraparound into account.
Alternatively, you could implement cover trees, which work on any metric.
(I'm posting this answer even though I'm not fully sure it works. Intuitively it seems right, but there might be an edge case I haven't considered)
If you're working with periodic boundary conditions, then you can think of space as being cut into a series of blocks of some fixed size that are all then superimposed on top of one another. Suppose that we're in R2. Then one option would be to replicate that block nine times and arrange them into a 3x3 grid of duplicates of the block. Given this, if we find the nearest neighbor of any single node in the central square, then either
The nearest neighbor is inside the central square, in which case the neighbor is a nearest neighbor, or
The nearest neighbor is in a square other than the central square. In that case, if we find the point in the central square that the neighbor corresponds to, that point should be the nearest neighbor of the original test point under the periodic boundary condition.
In other words, we just replicate the elements enough times so that the Euclidean distance between points lets us find the corresponding distance in the modulo space.
In n dimensions, you would need to make 3n copies of all the points, which sounds like a lot, but for R3 is only a 27x increase over the original data size. This is certainly a huge increase, but if it's within acceptable limits you should be able to use this trick to harness a standard kd-tree (or other spacial tree).
Hope this helps! (And hope this is correct!)