The shortest path between two points on a cuboid on its surface - algorithm

I can't find a universal solution to "The Spider and the Fly Problem" (the shortest path between two points on a cuboid on its surface). Everybody solves a one specific case but what when two points can be anywhere?
My idea was to create an algorithm that considers various nets of a cuboid, calculates shortest paths on 2D and then returns the minimum but I have no idea for the algorithm to generate these grids (I guess hardcoding all combinations is not the best way).

Simplistic approach (only works where the points are on the same or adjacent faces)
Flatten the cube structure to 2d as follows...
Start with a face containing one of the two points. If this also contains the other point, you can stop there and the solution is trivial.
There are only 4 neighbouring faces. If any of them contain the other point, you can place that face adjoining the first, and plot the straight line.
Otherwise, then the points are on opposing faces. You need to try placing the final face adjoining each of the 4 neighbouring faces, and choose the shortest of the 4 alternatives. This will not always give the best solution, but it's not far off, and is cheap.
Generic approach
Jim Propp's surface distance conjecture is that For a centrally symmetric convex compact body, the greatest surface distance between two points is achieved only for pairs which are opposites through the centre. My conjecture based on that would be that the shortest distance is approximately where the plane made by the two points and the centre of the body meets the surface. So you simply need to find where that plane intersects the faces using 3d geometry, and use the faces that are crossed by the shorter of the two alternatives when looking at possible routes. If the plane runs along an edge of the cube (e.g. if the points are on opposite faces and are both between the centre of the face and the corner of the face, and those corners are linked by an edge) then routes through both faces should be considered, although I speculate they will be equivalent lengths.
This solution is more generic, and also satisfies scenarios where the points are on the same face, connected faces and opposite faces.
The only problem with this approach arises where the line between the two points passes through the centre of the body, which by definition means that the two points are exactly opposite each other, because that means the 3 points are in a straight line, so there isn't a plane...

I think this is a good question, for which the answer is not at all obvious. In the smooth realm, it is an extraordinarily difficult problem. Geodesics (shortest paths) on a sphere (which is a smooth analog of a cube) are easy to find. Geodesics on a biaxial ellipsoid (an ellipsoid of revolution; one cross section is a circle) are much harder to find. Finding geodesics on a triaxial ellipsoid (a smooth analog of a general cuboid) was a challenging unsolved problem in the first half of the 19th century. See the Wikipedia page.
On the other hand, geodesics on cuboid are made from straight line segments so are much simpler. But some of the difficulty of the problem remains.
You may be able to find some literature on the subject if you search for the term "net". A polyhedron cut along some edges so that it can be flattened is often called a "net". I was able to quickly find a site that claims (without proof) that there are just 11 different nets for a cub(oid). But I agree with you that hard coding all the variations is not the best way.
It's not even obvious to me that the approach using nets will work for all polyhedra. I think I see an argument that will work for cuboids, but for general polyhedra, even convex polyhedra, it is not known whether they must have even one net. See the Wikipedia page. I think a satisfying solution to the problem on cuboids should work more generally on polyhedra, and the net idea seems to be insufficiently general, in my view.
What I'm thinking might work is a dynamic programming solution, where you look at the different edges your path can pass through between the initial and final points. There is a hierarchy of edges (those on the starting face; those containing a vertex on the starting face; those on the faces adjacent to the starting face; etc.). For each point on each of those edges you can find the minimum distance to the start point, culminating in the minimum distance from the end point to the start point.
Another way to think about this is to use something akin to the reflection principle, except instead of reflections, we use rotations in space which rotate the polyhedron about one of its edges so that the other face adjacent to the edge becomes coplanar with the starting face. Then we don't have to worry about whether we have a good net or not. You just pick a sequence of edges so that the final point is eventually rotated onto the plane of the initial face. The sequence of edges is finite because any loop is not part of a minimal path. I'll think about how I might be able to communicate this idea better.

I solved the problem for cubes and cuboids by discretizing the cube edges, generating a big graph and solving graph shortest path problem. You can specify start point (sx, sy, 0), and algorithm will determine all shortest path to target points on top face (z = 1), here for 19 * 19 target points. Cube edges are divided into 100 parts. Graph with these settings has n=1558 vertices and m=464000(!) edges, inner loop of floyd_warshall_path() for updating shortest path distances is executed n³ = 3,781,833,112 times (takes less than 1 minute on Raspberry Pi400). Orange shortest paths flow through 3 cuboid faces, blue ones through 4. Algorithm generates OpenSCAD file as output. Details in this posting, all code in GitHub repo.
P.S:
I made experiments with 1 x 1 x 3 cuboid and was able to find examples where shortest path between two points needs to pass 5 faces. Code is submitted to GitHub repo, and details are in this forum posting.
Orange shortest paths are passing 3 faces, blue are passing 4 faces, and the new yellow shortest paths pass 5 faces! With "mirror" at bottom, allowing to see the bottom face with start point as well. This time cuboid edges are divided into 150 parts (149 inner vertices), and there are 49 * 49 top face target points for single start point on bottom face:

I implemented cuboid shortest paths completely different this time, no graph, and geometric distance calculations in 28 possible foldings of cuboid into plane, details in this new forum thread:
Efficient cuboid surface shortest path problem application
The much increased efficiency with all the sliders allows to change x/y coordinate of bottom face point, number of divisions in X/Y direction and which folding to display, with instantaneous display after any change. This allows to play with a cuboid and "see" how the shortest paths change (on top face as well as on side and bottom faces).
Scale to 50% size, 0.5fps animation shows the 6 foldings containing any shortest path. The animation corresponds to clockwise traversal of OpenSCAD 3D top face shown on the right.
With added top and bottom face view.

but for anyone still interested, this question was solved on stackxechange by "Intelligenti pauca" (with some nice diagrams): here is the original link
https://math.stackexchange.com/questions/3023721/finding-the-shortest-path-between-two-points-on-the-surface-of-a-cube
The "Simplistic approach" from "Richardissimo" was on the right track, you just need to check a few more cases.
Intelligenti pauca:
If the two points belong to adjacent faces, you have to check three
different possible unfoldings to find the shortest path. In diagram
below I represented the first point (red) and the second point (black)
in three possible relative positions: middle position occurs when the
path goes through the common edge, in the other cases the path
traverses one of the faces adjacent to both faces. The other possible
positions are clearly longer than these.
image1
If the two points belong to opposite faces, then 12 different possible
positions have to be checked: see diagram below.
image2
After mapping the points like this you can calculate the distances like normal on a plane an have min(possible distances) as your shortest path-length.

Related

Algorithm to calculate the shortest path between two points on the surface of a 3D mesh

I am looking for an algorithm to calculate the following:
I have:
A 3D triangle mesh. The triangles do not necessarily lie in one plane. The angle between the norm vectors of two neighbouring triangles is less then 90 degrees.
Two points. The two points lie either on an edge of the triangle mesh or inside a triangle of the mesh.
I need to calculate the polyline which represents the shortest path between the two points on the mesh.
What is the simplest and/or most effective strategy to do this?
As it stands, your problem is not well defined; there can be many solutions depending on the direction used to "project" the line segment onto the mesh.
Once you have chosen the direction of projection, flatten the mesh onto a plane perpendicular to the direction of projection. At this point, your mesh is a collection of 2d edges (line segments); just determine the intersection (if any) of each edge with your target line segment.
Edit:
The updated question is now well defined. Since my answer to the original question (above) has been marked as accepted, presumably that means the information given in the comments below are actually what was really being "accepted" for the update question. I'll summarize:
A google search of "shortest distance on 3d mesh" turns up some relevant information, like Shortest Path Approximation on Triangulated Meshes
Also, see: https://stackoverflow.com/a/10389377/294949 -- danh
Since your start/end points potentially lie anywhere on the mesh (not restricted to vertices) I guess you are searching for the geodesic shortest path (not Dikstra shortest path following edges). A nice algorithm is implemented in geometry-central: http://geometry-central.net/surface/algorithms/flip_geodesics/
The algorithm is described in the paper "You Can Find Geodesic Paths in Triangle Meshes by Just Flipping Edges".
A standard approach to this task of finding the shortest path polyline (or geodesic) on the surface of triangular mesh between two given points consists of two steps:
Find a path approximation between two points
Iteratively adjust it to make it locally shortest everywhere.
The first step (path approximation) can be computed, for example, using
Dijkstra algorithm, which considers only paths along mesh edges (no crossing of mesh triangles),
Or some variations of Dijkstra algorithm, better suited for near planar surfaces like A*-search,
Or it can be Fast marching method, which can find also the paths crossing the triangles, however not guaranteed to produce a geodesic line.
The next step is iterative adjustment of the approximate path till it becomes truly locally shortest. Some recent articles are really promising here, like Just Flipping Edges. But it requires to construct a path network from the original mesh before operating, so it can be really expensive if your task is just to find one shortest path on the mesh.
A more classical way is to consider every piece of current path approximation between it enters two consecutive vertices, and unfold the strip of crossed triangles on plane. Then find the shortest path in the planar strip, which is a task that can be solved exactly in a linear time, for example by Shortest Paths in Polygons method by Wolfgang Mulzer. The crossing of this line with the edges will give the shortest path on the mesh in between two vertices.
Then for every vertex on the path approximation, two walks around this vertex are evaluated using same unfolding in hope a path around will be shorter then the path exactly via the vertex. The last steps are repeated till convergence.
Below is an example of geodesic path on a mesh with 2 million triangles:
Left - from the application MeshInspector: the time of iterative adjustment is highlighted in green and it is only a small fraction of total time.
Right - the picture from Just Flipping Edges article, where total time is not given, but it is presumably even higher due to the necessity to construct path network from the mesh.

Optimizing Geodesic Distances on a Triangular Mesh

I have a convex triangulated mesh. I am able to numerically calculate geodesics between points on the surface; however, I am having trouble tackling the following problem:
Imagine a net being placed over the mesh. The outside boundary of the net coincides with the boundary of the mesh, but the nodes of the net corresponding to the interior of the net are allowed to move freely. I'm interested in finding the configuration that would have the least stress (I know the distances for the at rest state of the net).
Doing this on a smooth surface is simple enough as I could solve for the stresses in terms of the positions of the nodes of the net; however, I don't see a way of calculating the stresses in terms of the position of the net nodes because I don't know that a formula exists for geodesics on a convex triangulated surface.
I'm hoping there is an alternative method to solving this such as a fixed point argument.
Hint:
If I am right, as long as a node remains inside a face, the equations are linear (just as if the node was on a plane). Assuming some node/face correspondence, you can solve for the equilibrium, as if the nodes did belong to the respective planes of support, unconstrained by the face boundaries.
Then for the nodes which are found to lie outside the face, you can project them on the surface and obtain a better face assignment. Hopefully this process might converge to a stable solution.
The picture shows a solution after a first tentative node/face assignment, then a second one after projection/reassignment.
On second thoughts, the problem is even harder as the computation involves geodesic distances between the nodes, which depend on the faces that are traversed. So the domain in which linearity holds when moving a single node is even smaller than a face, it is also limited by "wedges" emanating from the lined nodes and containing no other vertex.
Then you may have to compute the domains where the geodesic distances to a linked neighbor is a linear function of the coordinates and project onto this partition of the surface. Looks like an endeavor.

How can I pick a set of vertices to subtract from a polygon such that the distortion is minimum?

I'm working with a really slow renderer, and I need to approximate polygons so that they look almost the same when confined to a screen area containing very few pixels. That is, I'd need an algorithm to go through a polygon and subtract/move a bunch of vertices until the end polygon has a good combination of shape preservation and economy of vertice usage.
I don't know if there's a formal name for these kind of problems, but if anyone knows what it is it would help me get started with my research.
My untested plan is to remove the vertices that change the polygon area the least, and protect the vertices that touch the bounding box from removal, until the difference in area from the original polygon to the proposed approximate one exceeds a tolerance I specify.
This would all be done only once, not in real time.
Any other ideas?
Thanks!
You're thinking about the problem in a slightly off way. If your goal is to reduce the number of vertices with a minimum of distortion, you should be defining your distortion in terms of those same vertices, which define the shape. There's a very simple solution here, which I believe would solve your problem:
Calculate distance between adjacent vertices
Choose a tolerance between vertices, below which the vertices are resolved into a single vertex
Replace all pairs of vertices with distances lower than your cutoff with a single vertex halfway between the two.
Repeat until no vertices are removed.
Since your area is ultimately decided by the vertex placement, this method preserves shape and minimizes shape distortion. The one drawback is that distance between vertices might be slightly less intuitive than polygon area, but the two are proportional. If you really wish, you could run through the change in area that would result from vertex removal, but that's a lot more work for questionable benefit imo.
As mentioned by Angus, if you want a direct solution for the change in area, it's not actually super difficult. Was originally going to leave this as an exercise to the reader, but it's totally possible to solve this exactly, though you need to include vertices on either side.
Assume you're looking at a window of vertices [A, B, C, D] that are connected in that order. In this example we're determining the "cost" of combining B and C.
Calculate the angle offset from collinearity from A toward C. Basically you just want to see how far from collinear the two points are. This is |sin(|arctan(B - A)| - |arctan(C - A)|)| Where pipes are absolute value, and differences are the sensical notion of difference.
Calculate the total distance over which the angle change will effectively be applied, this is just the euclidean distance from A to B times the euclidean distance from B to C.
Multiply the terms from 2 and 3 to get your first term
To get your second term, repeat steps 2 - 4 replacing A with D, B with C, and C with B (just going in the opposite direction)
Calculate the geometric mean of the two terms obtained.
The number that results in step 6 presents the full-picture minus a couple constants.
I tried my own plan first: Protect the vertices touching the bounding box, then remove the rest in the order that changes the resultant area the least, until you can't find a vertice to remove that keeps the new polygon area within X% of the original one. This is the result with X = 5%:
When the user zooms out really far these shapes fit the bill well enough for me. I haven't tried any of the other suggestions. The savings are quite astonishing, sometimes from 80-100 vertices down to 4 or 5.

Find the point furthest away from n other points

I am trying to create an algorithm for 'fleeing' and would like to first find points which are 'safe'. That is to say, points where they are relatively distant from other points.
This is 2D (not that it matters much) and occurs within a fixed sized circle.
I'm guessing the sum of the squared distances would produce a good starting equation, whereby the highest score is the furthest away.
As for picking the points, I do not think it would be possible to solve for X,Y but approximation is sufficient.
I did some reading and determined that in order to cover the area of a circle, you would need 7 half-sized circles (with centers forming a hex, and a seventh at the center)
I could iterate through these, all of which are within the circle to begin with. As I choose the best scoring sphere, I could continue to divide them into 7 spheres. Of course, excluding any points which fall outside the original circle.
I could then iterate to a desired precision or a desired level.
To expand on the approach, the assumption is that it takes time to arrive at a location and while the location may be safe, the trip in between may not. How should I incorporate the distance in the equation so that I arrive at a good solution.
I suppose I could square the distance to the new point and multiply it by the score, and iterate from there. It would strongly favor a local spot, but I imagine that is a good behavior. It would try to resolve a safe spot close by and then upon re-calculating it could find 'outs' and continue to sneak to safety.
Any thoughts on this, or has this problem been done before? I wasn't able to find this problem specifically when I looked.
EDIT:
I've brought in the C# implementation of Fortune's Algorithm, and also added a few points around my points to create a pseudo circular constraint, as I don't understand the algorithm well enough to adjust it manually.
I realize now that the blue lines create a path between nodes. I can use the length of these and the distance between the surrounding points to compute a path (time to traverse and danger) and weigh that against the safety (the empty circle it is trying to get to) to determine what is the best course of action. By playing with how these interact, I can eliminate most of the work I would have had to do, simply by using the voronoi. Also my spawning algorithm will use this now, to determine the LEC and spawn at that spot.
You can take the convex hull of your set of locations - the vertices of the convex hull will give you the set of "most distant" points. Next, take the centroid of the points you're fleeing from, then determine which vertex of the convex hull is the most distant from the centroid. You may be able to speed this up by, for example, dividing the playing field into quadrants - you only need to test the vertices that are in the furthermost quadrant (e.g., if the centroid is in the positive-x positive-y quadrant, then you only need to check the vertices in the negative-x negative-y quadrant); if the playing field is an irregular shape then this may not be an option.
As an alternative to fleeing to the most distant point, if you have a starting point that you're fleeing from (e.g. the points you're fleeing from are enemies, and the player character is currently at point X which denotes its starting point), then rather than have the player flee to the most distant point you can instead have the player follow the trajectory that most quickly takes them from the centroid of the enemies - draw a ray from the enemies' centroid through the player's location, and that ray gives you the direction that the player should flee.
If the player character is surrounded then both of these algorithms will give nonsense results, but in that case the player character doesn't really have any viable options anyway.

Subdivided icosahedron - how to find the nearest vertex to an arbitrary point

I have an application that creates an approximation to sphere by subdividing an icosahedron. The Cartesian vertex coordinates are converted to spherical coordinates so that all vertices sit on the surface of a unit sphere.
What I need to do next is find the nearest vertex to an arbitrary point on the surface of the sphere. I have come up with two simple algorithms...
Brute force search - will be OK for a small number of vertices, but will be excessive for finer subdivisions.
Sorted / Indexed search - sort the vertices into some form of order by azimuth and inclination and then create a rough index to speed up a brute force search by limiting its scope.
I was wondering if there was a more subtle, and hopefully higher performing algorithm that I can use instead of one of the two above.
Update 1: I have just recalled that for another part of the application the vertices store information about their neighbours. My new algorithm is
Pick an arbitrary start vertex. Find which of its neighbours has a smaller distance to the point to locate. Use this neighbour as the new start vertex. Repeat until none of the vertex's neighbours has a smaller distance to the point. This vertex is the closest to the point.
Scanning through the responses, I think I may be off base, but what you're after is simple. I think.
Since you're dealing with just points that sit on the sphere, you can just drop a line from the vertex to the center of the sphere, drop another line from the arbitrary point to the center and solve for the angle created between them. Smaller is better. The easiest and cheapest way I think would be the dot product. The angle basically falls out of it. Here's a link about it: http://www.kynd.info/library/mathandphysics/dotProduct_01/
For testing them, I would suggest picking a vertex, testing it, then testing its neighbors. It SHOULD always be in the direction of the smallest neighbor (angle should always decrease as you get closer to the vertex you're after)
Anyhow, I hope that's what you're after.
Oh, and I came across this page while looking for your subdivision algorithm. Hard to find; if you could post a link to it I think it would help out a lot more than just myself.
One of possible solutions is to build BSP tree for vertices: http://en.wikipedia.org/wiki/Binary_space_partitioning
If the icosahedron has one vertex at the north pole and the opposite vertex at the south pole then there are 2 groups each of 5 vertices which are in planes parallel to the equator. With a little geometry I figure that these planes are at N/S 57.3056° (decimals, not dd.mmss). This divides your icosahedron into 4 latitude zones;
anything north (south) of 28.6528° is closest to the vertex at the nearer pole;
anything between the equator and north (south) 28.6528° is closer to one of the 5 vertices in that zone.
I'm working this as a navigator would, arcs measured in degrees and denoted north and south; if you prefer a more mathematical convention you can translate this all to your version of spherical coordinates quite easily.
I suspect, though I haven't coded it, that checking the distance to 5 vertices and selecting the nearest will be quicker than more sophisticated approaches based on partitioning the surface of the sphere into the projections of the faces of the icosahedron, or projecting the points on the sphere back onto the icosahedron and working the problem in that coordinate system.
For example, the approach you suggest in your update 1 will require the computation of the distance to 6 vertices (the first, arbitrarily chosen one and its 5 neighbours) at least.
It doesn't matter (if you only want to know which vertex is nearest) whether you calculate distances in Cartesian or spherical coordinates. However, calculation in Cartesian coordinates avoids a lot of calls to trigonometric functions.
If, on the other hand, you haven't arranged your icosahedron with vertices at the poles of your sphere, well, you should have !

Resources