Minimum distance between two 3D Cubes/Cuboids - algorithm

Having two 3D cubes/cuboids, each defined by their different vertices (p1, p2, p3, p4, p5, p6, p7, p8), how can I find the minimum distance between the cubes?
I have been working on a simple Euclidean 3D distance algorithm with the min and max of each cube but it doesn't work for rotated cubes. Is there any overall method for this problem? In this picture there are two examples of the two cubes and possible positions where I want to calculate the minimum distance:

I don't see a shortcut, so I'll answer based on brute-force case exhaustion. This won't be the fastest approach but a very robust one.
You're looking for the shortest connecting line from a point in cube A to a point in cube B. At both ends, this shortest line will surely not end inside the cube, but on a surface, edge or vertex of the cube (assuming the cubes don't overlap). So you get 9 cases:
vertex / vertex
vertex / edge
vertex / surface
edge / vertex
edge / edge
edge / surface
surface / vertex
surface / edge
surface / surface
We can omit the surface / surface case, as it's only possible with surfaces parallel to each other, and in that situation some other case, using an edge or vertex, will give the same distance.
For each of the cases, you can find online a formula for computing the distance of the (infinitely extended) geometric objects, and then you should check for staying inside the finite surfaces or edges.
Finally, you can return the minimum of the valid distances.
Of course, there can be lots of optimizations, excluding cases that cannot produce shortest distances, e.g. surfaces pointing away from the other cube, but that needs careful analysis.

Related

How to Judge the Equality of 2 Triangular Meshes?

Given a triangular mesh A in 3D space. Rotate and translate all its points to generate a new mesh B.
How to determine the equality of A and B, just by their vertices and faces?
Topology of the mesh is not important, I only care about the geometric equality, A and B should be equal even if their triangulation are changed. It is
something like the transform in-variance problem for triangular mesh, only translate and rotation is considered.
To complete #Spektre's answer, if the two meshes are not exactly the same, that is there is at least a pair of nodes or edges which does not perfectly overlap, You can use the Hausdorff distance to quantify the "difference" between the two meshes.
Assuming triangle faces only.
compare number of triangles
if not matching return false.
sort triangles by their size
if the sizes and order does not match between both meshes return false.
find distinct triangle in shapes
So either the biggest or smallest in area, edge length or whatever. If not present then you need other distinct feature like 2 most distant points etc ... If none present even that then you need the RANSAC for this.
Align both meshes so the matching triangles (or feature points) will have the same position in both meshes.
compare matching vertexes
so find the closest vertex form Mesh A to each vertex in mesh B and if the distance of any them cross some threshold return false
return true
In case meshes has no distinct features for 3 you need to either use brute force loop through all combinations of triangles form A and B until #4 returns true or all combinations tested or use RANSAC for this.
There are alternatives to #3 like find the centroid and closest and farthermost points to it and use them as basis vectors instead of triangle. that requires single vertex or close group of vertexes to be the min and max. if not present like in symmetrical meshes like cube icosahedron, sphere you're out of luck.
You can enhance this by using other features from the mesh if present like color, texture coordinate ...
[Edit1] just a crazy thinking on partial approach without the need of aligninig
compute average point C
compute biggest inscribed sphere centered at C
just distance from C to its closest point
compute smallest outscribed sphere centered at C
just distance from C to its farthest point
compare the radiuses between the shapes
if not equal shapes are not identical for sure. If equal then you have to check with approaches above.
The paper On 3D Shape Similarity (Heung-yeung Shum, Martial Hebert, Katsushi Ikeuchi) computes a similarity score between two triangular meshes by comparing semiregular sphere tessellations that have been deformed to approximate the original meshes.
In this case, the meshes are expected to be identical (up to some small error due to the transformation), so an algorithm inspired by the paper could be constructed as follows:
Group the vertices of each mesh A, B by the number of neighboring vertices they have.
Choose one vertex V_A from mesh A and vertex V_Bi from mesh B, both with same number of neighbors.
The vertex and its N neighbors V_n1...V_nN form a triangle fan of N triangles. Construct N transforms which take vertex V_Bi to V_A and each possible fan (starting from a different neighbor V_Bn1, V_Bn2, ..., V_BnN) to V_An1...V_AnN.
Find the minimum of the sums of distances from each vertex of B to the closest vertex to it in A, for each N transforms for each vertex V_Bi.
If a sum of near zero is found, the vertices of the transformed mesh B coincide with vertices of A, a mapping between them can be constructed, and you can do further topological, edge presence or direction checks, as needed.

Project 3D polygon into a 2D plane such that the vertices are in counter clockwise order

Some fast algorithms for working with polygons require the vertices of the polygon to have a specific order (clockwise or counter clockwise with respect to the polygon's plane normal).
To use those algorithms in 3D planar polygons (where all the points lie in a particular plane) one can perform a change of basis to a basis spanned by two orthogonal vectors that lie in the plane and a plane normal vector.
Is there a way to always find a basis in which the polygon vertices are always in counter clockwise (or clockwise) order?
Perhaps the best method is to compute the signed area of the polygon, and if it is negative, you know your vertices are clockwise; so reverse. If it is positive, your vertices are counterclockwise.
Search for "signed area of polygon." Here is one Mathematica link:

Algorithm finding two parallel planes enclosing a set of points

I'm working on the implementation of an algorithm used to determine the safest point for a drone to land, using this paper.
To do so I'm tring to find two parallel planes enclosing a set of 9 points while minimizing the distance r between those two planes.
r will then represent the roughness of the terrain.
I would like a general strategy to solve the problem or a link to a paper describing a solution.
Can you do the following:
Find the convex hull of the 9 points
For each plane p in the convex hull, find the point pt not in p that is the farthest away, let the second plane be that which is parallel to p and passes through pt and compute the distance
Take the minimum
The goal is to find planes normal. Then building the planes is easy.
And there is finite number of candidates for plane normal: cross-products of edge vectors of convex hull (this includes but is not limited to face normals). For this number of points you can just count them all.
Why?
Every plane touches some non-zero number of points (otherwise it can be moved closer).
If we can rotate planes even slightly without losing connection with these points, distance will decrease.
So the optimum planes can not rotate.
If a plane touches two points, it can rotate only around this edge.
A plane cannot rotate if it touches two non-parallel edges.
Then its normal is cross-product of those edge vectors.

Find a set of points of a circle draped on a 3D height map

I have a height map of NxN values.
I would like to find, given a point A (the red dot), whose x and y coordinates are given (and z is known from the data, so A is a vertex of the surface) a set of points that lie on the circumference of the circle with center in A and radius R that are a good approximation of a circular "cloth" (in grey) draped on the imaginary surface described by the data points.
The sampling, the reciprocal distances between the set of points that I am trying to find, doesn't need to be uniform, but still I would like to find at least all the points that are an intersection of the edges of the mesh with the circle at distance R from A.
How to find this set of points?
Is this a known problem?
(source: keplero.com)
-- edit
The assumption that Jan is using is right: the samples form a regular rectangular or square grid (in the X-Y plane) aligned with [0,0]. But I would like to take the displacement in the Z direction into account to compute the distance. you can see the height map as a terrain, and the algorithm I am looking for as the instructions to give to an explorer that, traveling just on paths of given latitude or longitude, mark the points that are at distance R from A. Walking distance, that is taking into account all the Z displacements done so far. The explorer climbs and go down in the valleys too.
The trivial algorithm for this would be something like this. We know that given R, the maximum displacement on the x and y axis corresponds to a completely flat surface. If there is no slope, the x,y points will all be in the bounding square Ax-R < x < Ax+r and Ay-R
At this point, it would start traveling to the close cells, since if the perimeter enters the edge of one cell of the grid, it also have to exit that cell.
I reckon this is going to be quite difficult to solve in an exact fashion, so I would suggest trying the straightforward approach of simulating the paths that your explorers would take on the surface.
Given your starting point A and a travel distance d, calculate a circle of points P on the XY plane that are d from A.
For each of the points p in P, intersect the line segment A-p with your grid so that you end up with a sequence of points where the explorer crosses from one grid square to the next, in the order that this would happen if the explorer were travelling from A. These points should then be given a z-coordinate by interpolation from your grid data.
You can thus advance through this point sequence and keep track of the distance travelled so far. Eventually the target distance will be reached - adjust p to be at this point.
P now contains the perimeter that you're looking for. Adjust the sample fidelity (size of P) according to your needs.
Just to clarify - You have a triangulated surface in 3d and, for a given starting vertex Vi in the mesh you would like to find the set of vertices U that are reachable via paths along the surface (i.e. geodesics) with length Li <= R.
One approach would be to transform this to a graph-based problem:
Form the weighted, undirected graph G(V,E), where V is the set of vertices in the triangulated surface mesh and E is the set of edges in this mesh. The edge weight should be the Euclidean (3d) length of each edge. This graph is a discrete distance map - the distance "along the surface" between each adjacent vertex in the mesh.
Run a variant of Dijkstra's algorithm from the starting vertex Vi, only expanding paths with length Li that satisfy the constraint Li <= R. The set of vertices visited U, will be those that can be reached by the shortest (geodesic) path with Li <= R.
The accuracy of this approach should be related to the resolution of the surface mesh - as long as the surface curvature within each element is not too high the Euclidean edge length should be a good approximation to the actual geodesic distance, if not, the surface mesh should be refined in that area.
Hope this helps.

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