I have two pairs of latitude and longitude, but each pair also has an associated radius, because the coordinates may be more or less accurate. How to find the minimum distance between two circular areas on Earth?
The .NET code here calculates the distance between two precise geocoordinates, but does not take into account the associated radii.
Example
What is the shortest distance between the perimeters of these two circles, one in London, England and the other in Cancun, Mexico ?
51°31′2″ N 0°7′50″ W radius 90m
21°7′45″ N 86°45′49″ W radius 550m
Also, the distance between these two overlapping areas should be 0 meters:
21°7′46″ N 86°45′49″ W radius 50m
21°7′45″ N 86°45′49″ W radius 550m
A cheap and cheerful approximation would be to find the distance between the centres and then subtract the radius of each circle from that. If the result is negative the circles overlap and the minimum distance is 0; otherwise the minimum distance is the result. This would give the exact answer on a plane.
Actually, except for some odd cases involving nearly antipodal points I think this will give the correct answer on a spheroid too. For (except for the odd cases) if the centres (A and B say) are d apart, then there will be a geodesic from A to B of length d. If we go a distance r (radius of the circle about A) along the geodesic toward B we will get to a point a on the circle, and similarly (from B a distance s going towards A) we get to a point b on the circle about B. The geodesic from A to B is also a geodesic from a to b, and the distance along it is d-r-s. So the distance from a to b is d-r-s. There can't be points (a',b' say) on the circles closer then that, for if there were we could get from A to B by going from A to a', along the geodesic from a' to b' and then from B to b; but the geodesic from A to B is the shortest route.
Assuming the two regions are "close enough" so one can neglect the spherical nature of the problem, along with ...
Assuming that those "confidence regions" are somehow important to the user of the result, along with ...
The fact that a single number as a result would erase the uncertainty of the information (or the measurement errors), I would recommend to not expect a number but an interval to be an adequate result.
Let p1, p2 be two "close enough" centers of regions R1, R2.
Let u1, u2 be the uncertainty of the position in the same distance unit as p1, p2 are measured, as the radius of those circles.
Center distance:
dc p1 p2 = |p2-p1|
BorderDistance Minimum:
bdmin p1 p2 u1 u2 = (dc p1 p2) - u1 - u2
BorderDistance Maximum:
bdmax p1 p2 u1 u2 = (dc p1 p2) + u1 + u2
Then, the distance between those regions is the interval:
[bdmin p1 p2 u1 u2, bdmax p1 p2 u1 u2]
let sq x = x*x
let distance p1 p2 : float =
let x1,y1 = p1
let x2,y2 = p2
sqrt(sq (x2-x1) + sq (y2-y1))
let rdistance p1 u1 p2 u2 =
( (distance p1 p2) - u1 - u2
, (distance p1 p2) + u1 + u2
)
let rdistance3 p1 u1 p2 u2 =
let mi,ma = rdistance p1 u1 p2 u2
(mi,distance p1 p2,ma)
let P1 = (0.0,0.0)
let P2 = (10.0,10.0)
let U1 = 2.0
let U2 = 5.0
printfn "as interval: %A" (rdistance P1 U1 P2 U2)
printfn "as interval with center: %A" (rdistance3 P1 U1 P2 U2)
as interval: (7.142135624, 21.14213562)
as interval with center: (7.142135624, 14.14213562, 21.14213562)
The latter version is nice as it allows users to continue as they please, having all 3 values and also are able to get a feeling for the accuracy.
Discussion:
If the true data looks like the one on the picture, it does not pay off to take spherical geometry formulae for the computation. The reason being, that the size of the circles is magnitudes larger than the error yielded from euklidean geometry.
If, on the other hand, the true data would be at significantly large distances, it would probably not matter if the center points or the edges of the circles were taken for the computation. As then the radius of the circles would be tiny compared to the distance. Then, though, spherical geometry is needed.
Last not least, if this is only one step in a longer series of computations, it pays off to keep accuracy information.
See for example the wikipedia article on interval arithmetic.
If you see U1, U2 as statistical parameters, such as the n% confidence region (think something like standard deviation), then you can try to find a statistical model and reason about it.
Warming up, if we assumed both P1 and P2 were measured points from the same statistical distribution, which they are obviously not. Then, the variance of both points would be the same. Which is obviously not the case. Then, given a series of P1,P2 pairs, you could estimate the underlying distribution and use something like a t-test to test the hypothesis P1 = P2.
Now, what you probably have as your U1, U2 in GPS laymans terms is called "dilution of precision" (DOP, some use 2, actually HDOP,VDOP), which is a single number, aggregating the uncertainty of the GPS fix computation. It is a function of many parameters, as a GPS receiver can actually notice:
Number of visible and used satellites used for the fix
Estimate of time accuracy
Accuracy information stated by the satellites
...
Let's say, the GPS receiver only sees 3 satellites. What it does is "measure" the distance to each satellite which is at a location known to the GPS receiver (the satellites send their positions). So from each of the satellites, the receiver can yield a sphere of its own position, with the radius of the sphere being the distance, the center being the location of the satellite.
Intersecting the Spheres computed for each used satellite, one can receive a volume in which the GPS receiver is located. In the absence of any measurement errors etc. it would actually the be exact location of the receiver...in case of selective availability being turned off. SA is an artificial error satellites can add to their information, which decreases the accuracy, civilian GPS receivers can obtain. I think it has been turned off now for a while...
Since the GPS receiver does not have an atomic clock, but the GPS satellites do have those, the estimation task of the receiver is not only to estimate its 3 coordinates, but also the state of its own cheap clock. This is why a GPS fix with only 3 satellites is also called a 2D fix (as the system of equations is still underdetermined). 4 and more satellites yield a 3D fix.
Beyond that basic theory of how it works, there are factors specific to the location of the GPS receiver. Apart from the number of satellites a receiver can use in a given location, there can be RF frequency reflections etc., which can render the "distance computed by time delay" for one or more satellites errorneous. If, say the GPS receiver sees many more than 4 satellites, it will be able to construe, that some measurements are inconsistent compared to the remaining measurements.
All those aspects shown above are then computed into a single floating point number, named "Dilution of precision".
So, clearly it is not easy to take basic statistical tests for the hypothesis P1 <> P2 and one would have to dig deeper than is possible here in this format.
Related
Given a point p exterior to an axially aligned, origin centered ellipse E, find the (upto) four unique normals to E passing through p.
This is not a Mathematica question. Direct computation is too slow; I am willing to sacrifice precision and accuracy for speed.
I have searched the web, but all I found involved overly complex calculations which if implemented directly appear to lack the performance I need. Is there a more "programmatical" way to do this, like using matrices or scaling the ellipse into a circle?
Let's assume the ellipse E is in "standard position", center at the origin and axes parallel to the coordinate axes:
(x/a)^2 + (y/b)^2 = 1 where a > b > 0
The boundary cases a=b are circles, where the normal lines are simply ones that pass through the center (origin) and are thus easy to find. So we omit discussion of these cases.
The slope of the tangent to the ellipse at any point (x,y) may be found by implicit differentiation:
dy/dx = -(b^2 x)/(a^2 y)
For the line passing through (x,y) and a specified point p = (u,v) not on the ellipse, that is normal to ellipse E when its slope is the negative reciprocal of dy/dx:
(y-v)/(x-u) * (-b^2 x)/(a^2 y) = -1 (N)
which simplifies to:
(x - (1+g)u) * (y + gv) = -g(1+g)uv where g = b^2/(a^2 - b^2)
In this form we recognize it is the equation for a right rectangular hyperbola. Depending on how many points of intersection there are between the ellipse and the hyperbola (2,3,4), we have that many normals to E passing through p.
By reflected symmetry, if p is assumed exterior to E, we may take p to be in the first quadrant:
(u/a)^2 + (v/b)^2 > 1 (exterior to E)
u,v > 0 (1'st quadrant)
We could have boundary cases where u=0 or v=0, i.e. point p lies on an axis of E, but these cases may be reduced to solving a quadratic, because two normals are the (coinciding) lines through the endpoints of that axis. We defer further discussion of these special cases for the moment.
Here's an illustration with a=u=5,b=v=3 in which only one branch of the hyperbola intersects E, and there will be only two normals:
If the system of two equations in two unknowns (x,y) is reduced to one equation in one unknown, the simplest root-finding method to code is a bisection method, but knowing something about the possible locations of roots/intersections will expedite our search. The intersection in the first quadrant is the nearest point of E to p, and likewise the intersection in the third quadrant is the farthest point of E from p. If the point p were a good bit closer to the upper endpoint of the minor axis, the branches of the hyperbola would shift together enough to create up to two more points of intersection in the fourth quadrant.
One approach would be to parameterize E by points of intersection with the x-axis. The lines from p normal to the ellipse must intersect the major axis which is a finite interval [-a,+a]. We can test both the upper and lower points of intersection q=(x,y) of a line passing through p=(u,v) and (z,0) as z sweeps from -a to +a, looking for places where the ellipse and hyperbola intersect.
In more detail:
1. Find the upper and lower points `q` of intersection of E with the
line through `p` and `(z,0)` (amounts to solving a quadratic)
3. Check the sign of a^2 y(x-u) - b^2 x(y-v) at `q=(x,y)`, because it
is zero if and only `q` is a point of normal intersection
Once a subinterval is detected (either for upper or lower portion) where the sign changes, it can be refined to get the desired accuracy. If only modest accuracy is needed, there may be no need to use faster root finding methods, but even if they are needed, having a short subinterval that isolates a root (or root pair in the fourth quadrant) will be useful.
** more to come comparing convergence of various methods **
I had to solve a problem similar to this, for GPS initialization. The question is: what is the latitude of a point interior to the Earth, especially near the center, and is it single-valued? There are lots of methods for converting ECEF cartesian coordinates to geodetic latitude, longitude and altitude (look up "ECEF to Geodetic"). We use a fast one with only one divide and sqrt per iteration, instead of several trig evaluations like most methods, but since I can't find it in the wild, I can't give it to you here. I would start with Lin and Wang's method, since it only uses divisions in its iterations. Here is a plot of the ellipsoid surface normals to points within 100 km of Earth's center (North is up in the diagram, which is really ECEF Z, not Y):
The star-shaped "caustic" in the figure center traces the center of curvature of the WGS-84 ellipsoid as latitude is varied from pole to equator. Note that the center of curvature at the poles is on the opposite side of the equator, due to polar flattening, and that the center of curvature at the equator is nearer to the surface than the axis of rotation.
Wherever lines cross, there is more than one latitude for that cartesian position. The green circle shows where our algorithm was struggling. If you consider that I cut off these normal vectors where they reach the axis, you would have even more normals for a given position for the problem considered in this SO thread. You would have 4 latitudes / normals inside the caustic, and 2 outside.
The problem can be expressed as the solution of a cubic equation which
gives 1, 2, or 3 real roots. For the derivation and closed form
solution see Appendix B of Geodesics on an ellipsoid of revolution. The boundary between 1 and 3 solutions is an astroid.
I'm trying to find a solution to this symbolic non-linear vector equation:
P = a*(V0*t+P0) + b*(V1*t+P1) + (1-a-b)*(V2*t+P2) for a, b and t
where P, V0, V1, V2, P0, P1, P2 are known 3d vectors.
I attempted to do that in Matlab like this:
P = sym('P', [3,1])
P0 = sym('P0', [3,1])
P1 = sym('P1', [3,1])
P2 = sym('P2', [3,1])
V0 = sym('V0', [3,1])
V1 = sym('V1', [3,1])
V2 = sym('V2', [3,1])
syms a b t
F = a*(V0*t+P0) + b*(V1*t+P1) + (1-a-b)*(V2*t+P2) - P
solve(F,a,b,t)
I get
Warning: Explicit solution could not be found.
I'm starting to run out of ideas how to solve it, this isn't the first math package I tried.
The interesting bit is that this equation has a simple geometrical interpretation. If you imagine that points P0-P2 are vertices of a triangle, V0-V2 are roughly vertex normals and point P lies above the triangle, then the equation is satisfied for a triangle containing point P with it's three vertices on the three rays (V*t+P), sharing the same parameter t value. a, b and (1-a-b) become the barycentric coordinates of the point P.
So if the case is not degenerate, there should be only one well defined solution for t.
As symbolic equation, this one has 3 variables, so there is no way to have a single solution.
Imagine you pick any values for say b and t. Then in almost all cases you can solve for a, so you get many different solutions.
If you want to think geometrically, imagine that V0 and V1 point in the upper half-space regarding the (P0,P1,P2) triangle, but V2 point in the lower. Also V0,V1 are perpendicular to the plane of the triangle and V0 and V1 are unit vectors.
Now if you have a plane pinned at the point P, which intersects the rays P0+t*V0 and P1+t*V1 at the same distance above the triangle, you can move the plane in such a way that it stays pinned at P and intersecting the two rays at the same distance. It's only a matter of having had picked V2 in such a way that the point of intersection with this plane moves at the same velocity, so it will correspond to the same t, thus giving you infinitely many solutions.
Another example would be if all V0-V2 were colinear with the triangle P0,P1,P2. Then you trivially get a solution for any t.
So you need more equations to solve this symbolically.
I have an image that represents a projection. I am going to explain the problem with an example:
In the screen, there is a line from one point E(100,200) to another point
H (150,100). A represent one point
that in the real world is at 200 cm of
distance while B is a point that in
real world is at 300 cm of distance.
The thing that I would like to know is this:
Given one point of the line that passes for these two points, is there a way to calculate the z distance data that it should have?
What if the z distance is not a linear function but is some logarithmic function?
If it's not clear ask me everything,
Cheers
I think what you're getting at is perspective correct interpolation. If you know the depth at E and a depth at H, and B is on the line (in the image) joining these two points, solve for the depth at B with:
1/Zb = s * 1/Ze + (1-s) * 1/Zh
where s is the normalized distance/interpolation parameter (between 0 and 1) along the line in screen space, meaning B = s * E + (1-s) * H
Use homogeneous coordinates, which can be linearly interpolated in screen space (for depth and texture): http://www.cs.unc.edu/~olano/papers/2dh-tri/
I am new to this forum and not a native english speaker, so please be nice! :)
Here is the challenge I face at the moment:
I want to calculate the (approximate) relative coordinates of yet unknown points in a 3D euclidean space based on a set of given distances between 2 points.
In my first approach I want to ignore possible multiple solutions, just taking the first one by random.
e.g.:
given set of distances: (I think its creating a pyramid with a right-angled triangle as a base)
P1-P2-Distance
1-2-30
2-3-40
1-3-50
1-4-60
2-4-60
3-4-60
Step1:
Now, how do I calculate the relative coordinates for those points?
I figured that the first point goes to 0,0,0 so the second one is 30,0,0.
After that the third points can be calculated by finding the crossing of the 2 circles from points 1 and 2 with their distances to point 3 (50 and 40 respectively). How do I do that mathematically? (though I took these simple numbers for an easy representation of the situation in my mind). Besides I do not know how to get to the answer in a correct mathematical way the third point is at 30,40,0 (or 30,0,40 but i will ignore that).
But getting the fourth point is not as easy as that. I thought I have to use 3 spheres in calculate the crossing to get the point, but how do I do that?
Step2:
After I figured out how to calculate this "simple" example I want to use more unknown points... For each point there is minimum 1 given distance to another point to "link" it to the others. If the coords can not be calculated because of its degrees of freedom I want to ignore all possibilities except one I choose randomly, but with respect to the known distances.
Step3:
Now the final stage should be this: Each measured distance is a bit incorrect due to real life situation. So if there are more then 1 distances for a given pair of points the distances are averaged. But due to the imprecise distances there can be a difficulty when determining the exact (relative) location of a point. So I want to average the different possible locations to the "optimal" one.
Can you help me going through my challenge step by step?
You need to use trigonometry - specifically, the 'cosine rule'. This will give you the angles of the triangle, which lets you solve the 3rd and 4th points.
The rules states that
c^2 = a^2 + b^2 - 2abCosC
where a, b and c are the lengths of the sides, and C is the angle opposite side c.
In your case, we want the angle between 1-2 and 1-3 - the angle between the two lines crossing at (0,0,0). It's going to be 90 degrees because you have the 3-4-5 triangle, but let's prove:
50^2 = 30^2 + 40^2 - 2*30*40*CosC
CosC = 0
C = 90 degrees
This is the angle between the lines (0,0,0)-(30,0,0) and (0,0,0)- point 3; extend along that line the length of side 1-3 (which is 50) and you'll get your second point (0,50,0).
Finding your 4th point is slightly trickier. The most straightforward algorithm that I can think of is to firstly find the (x,y) component of the point, and from there the z component is straightforward using Pythagoras'.
Consider that there is a point on the (x,y,0) plane which sits directly 'below' your point 4 - call this point 5. You can now create 3 right-angled triangles 1-5-4, 2-5-4, and 3-5-4.
You know the lengths of 1-4, 2-4 and 3-4. Because these are right triangles, the ratio 1-4 : 2-4 : 3-4 is equal to 1-5 : 2-5 : 3-5. Find the point 5 using trigonometric methods - the 'sine rule' will give you the angles between 1-2 & 1-4, 2-1 and 2-4 etc.
The 'sine rule' states that (in a right triangle)
a / SinA = b / SinB = c / SinC
So for triangle 1-2-4, although you don't know lengths 1-4 and 2-4, you do know the ratio 1-4 : 2-4. Similarly you know the ratios 2-4 : 3-4 and 1-4 : 3-4 in the other triangles.
I'll leave you to solve point 4. Once you have this point, you can easily solve the z component of 4 using pythagoras' - you'll have the sides 1-4, 1-5 and the length 4-5 will be the z component.
I'll initially assume you know the distances between all pairs of points.
As you say, you can choose one point (A) as the origin, orient a second point (B) along the x-axis, and place a third point (C) along the xy-plane. You can solve for the coordinates of C as follows:
given: distances ab, ac, bc
assume
A = (0,0)
B = (ab,0)
C = (x,y) <- solve for x and y, where:
ac^2 = (A-C)^2 = (0-x)^2 + (0-y)^2 = x^2 + y^2
bc^2 = (B-C)^2 = (ab-x)^2 + (0-y)^2 = ab^2 - 2*ab*x + x^2 + y^2
-> bc^2 - ac^2 = ab^2 - 2*ab*x
-> x = (ab^2 + ac^2 - bc^2)/2*ab
-> y = +/- sqrt(ac^2 - x^2)
For this to work accurately, you will want to avoid cases where the points {A,B,C} are in a straight line, or close to it.
Solving for additional points in 3-space is similar -- you can expand the Pythagorean formula for the distance, cancel the quadratic elements, and solve the resulting linear system. However, this does not directly help you with your steps 2 and 3...
Unfortunately, I don't know a well-behaved exact solution for steps 2 and 3, either. Your overall problem will generally be both over-constrained (due to conflicting noisy distances) and under-constrained (due to missing distances).
You could try an iterative solver: start with a random placement of all your points, compare the current distances with the given ones, and use that to adjust your points in such a way as to improve the match. This is an optimization technique, so I would look up books on numerical optimization.
If you know the distance between the nodes (fixed part of system) and the distance to the tag (mobile) you can use trilateration to find the x,y postion.
I have done this using the Nanotron radio modules which have a ranging capability.
I have three vertices which make up a plane/polygon in 3D Space, v0, v1 & v2.
To calculate barycentric co-ordinates for a 3D point upon this plane I must first project both the plane and point into 2D space.
After trawling the web I have a good understanding of how to calculate barycentric co-ordinates in 2D space, but I am stuck at finding the best way to project my 3D points into a suitable 2D plane.
It was suggested to me that the best way to achieve this was to "drop the axis with the smallest projection". Without testing the area of the polygon formed when projected on each world axis (xy, yz, xz) how can I determine which projection is best (has the largest area), and therefore is most suitable for calculating the most accurate barycentric co-ordinate?
Example of computation of barycentric coordinates in 3D space as requested by the OP. Given:
3D points v0, v1, v2 that define the triangle
3D point p that lies on the plane defined by v0, v1 and v2 and inside the triangle spanned by the same points.
"x" denotes the cross product between two 3D vectors.
"len" denotes the length of a 3D vector.
"u", "v", "w" are the barycentric coordinates belonging to v0, v1 and v2 respectively.
triArea = len((v1 - v0) x (v2 - v0)) * 0.5
u = ( len((v1 - p ) x (v2 - p )) * 0.5 ) / triArea
v = ( len((v0 - p ) x (v2 - p )) * 0.5 ) / triArea
w = ( len((v0 - p ) x (v1 - p )) * 0.5 ) / triArea
=> p == u * v0 + v * v1 + w * v2
The cross product is defined like this:
v0 x v1 := { v0.y * v1.z - v0.z * v1.y,
v0.z * v1.x - v0.x * v1.z,
v0.x * v1.y - v0.y * v1.x }
WARNING - Almost every thing I know about using barycentric coordinates, and using matrices to solve linear equations, was learned last night because I found this question so interesting. So the following may be wrong, wrong, wrong - but some test values I have put in do seem to work.
Guys and girls, please feel free to rip this apart if I screwed up completely - but here goes.
Finding barycentric coords in 3D space (with a little help from Wikipedia)
Given:
v0 = (x0, y0, z0)
v1 = (x1, y1, z1)
v2 = (x2, y2, z2)
p = (xp, yp, zp)
Find the barycentric coordinates:
b0, b1, b2 of point p relative to the triangle defined by v0, v1 and v2
Knowing that:
xp = b0*x0 + b1*x1 + b2*x2
yp = b0*y0 + b1*y1 + b2*y2
zp = b0*z0 + b1*z1 + b2*z2
Which can be written as
[xp] [x0] [x1] [x2]
[yp] = b0*[y0] + b1*[y1] + b2*[y2]
[zp] [z0] [z1] [z2]
or
[xp] [x0 x1 x2] [b0]
[yp] = [y0 y1 y2] . [b1]
[zp] [z0 z1 z2] [b2]
re-arranged as
-1
[b0] [x0 x1 x2] [xp]
[b1] = [y0 y1 y2] . [yp]
[b2] [z0 z1 z2] [zp]
the determinant of the 3x3 matrix is:
det = x0(y1*z2 - y2*z1) + x1(y2*z0 - z2*y0) + x2(y0*z1 - y1*z0)
its adjoint is
[y1*z2-y2*z1 x2*z1-x1*z2 x1*y2-x2*y1]
[y2*z0-y0*z2 x0*z2-x2*z0 x2*y0-x0*y2]
[y0*z1-y1*z0 x1*z0-x0*z1 x0*y1-x1*y0]
giving:
[b0] [y1*z2-y2*z1 x2*z1-x1*z2 x1*y2-x2*y1] [xp]
[b1] = ( [y2*z0-y0*z2 x0*z2-x2*z0 x2*y0-x0*y2] . [yp] ) / det
[b2] [y0*z1-y1*z0 x1*z0-x0*z1 x0*y1-x1*y0] [zp]
If you need to test a number of points against the triangle, stop here. Calculate the above 3x3 matrix once for the triangle (dividing it by the determinant as well), and then dot product that result to each point to get the barycentric coords for each point.
If you are only doing it once per triangle, then here is the above multiplied out (courtesy of Maxima):
b0 = ((x1*y2-x2*y1)*zp+xp*(y1*z2-y2*z1)+yp*(x2*z1-x1*z2)) / det
b1 = ((x2*y0-x0*y2)*zp+xp*(y2*z0-y0*z2)+yp*(x0*z2-x2*z0)) / det
b2 = ((x0*y1-x1*y0)*zp+xp*(y0*z1-y1*z0)+yp*(x1*z0-x0*z1)) / det
That's quite a few additions, subtractions and multiplications - three divisions - but no sqrts or trig functions. It obviously does take longer than the pure 2D calcs, but depending on the complexity of your projection heuristics and calcs, this might end up being the fastest route.
As I mentioned - I have no idea what I'm talking about - but maybe this will work, or maybe someone else can come along and correct it.
Update: Disregard, this approach does not work in all cases
I think I have found a valid solution to this problem.
NB: I require a projection to 2D space rather than working with 3D Barycentric co-ordinates as I am challenged to make the most efficient algorithm possible. The additional overhead incurred by finding a suitable projection plane should still be smaller than the overhead incurred when using more complex operations such as sqrt or sin() cos() functions (I guess I could use lookup tables for sin/cos but this would increase the memory footprint and defeats the purpose of this assignment).
My first attempts found the delta between the min/max values on each axis of the polygon, then eliminated the axis with the smallest delta. However, as suggested by #PeterTaylor there are cases where dropping the axis with the smallest delta, can yeild a straight line rather than a triangle when projected into 2D space. THIS IS BAD.
Therefore my revised solution is as follows...
Find each sub delta on each axis for the polygon { abs(v1.x-v0.x), abs(v2.x-v1.x), abs(v0.x-v2.x) }, this results in 3 scalar values per axis.
Next, multiply these scaler values to compute a score. Repeat this, calculating a score for each axis. (This way any 0 deltas force the score to 0, automatically eliminating this axis, avoiding triangle degeneration)
Eliminate the axis with the lowest score to form the projection, e.g. If the lowest score is in the x-axis, project onto the y-z plane.
I have not had time to unit test this approach but after preliminary tests it seems to work rather well. I would be eager to know if this is in-fact the best approach?
After much discussion there is actually a pretty simple way to solve the original problem of knowing which axis to drop when projecting to 2D space. The answer is described in 3D Math Primer for Graphics and Game Development as follows...
"A solution to this dilemma is to
choose the plane of projection so as
to maximize the area of the projected
triangle. This can be done by
examining the plane normal; the
coordinate that has the largest
absolute value is the coordinate that
we will discard. For example, if the
normal is [–1, 0, 0], then we would
discard the x values of the vertices
and p, projecting onto the yz plane."
My original solution which involved computing a score per axis (using sub deltas) is flawed as it is possible to generate a zero score for all three axis, in which case the axis to drop remains undetermined.
Using the normal of the collision plane (which can be precomputed for efficiency) to determine which axis to drop when projecting into 2D is therefore the best approach.
To project a point p onto the plane defined by the vertices v0, v1 & v2 you must calculate a rotation matrix. Let us call the projected point pd
e1 = v1-v0
e2 = v2-v0
r = normalise(e1)
n = normalise(cross(e1,e2))
u = normalise(n X r)
temp = p-v0
pd.x = dot(temp, r)
pd.y = dot(temp, u)
pd.z = dot(temp, n)
Now pd can be projected onto the plane by setting pd.z=0
Also pd.z is the distance between the point and the plane defined by the 3 triangles. i.e. if the projected point lies within the triangle, pd.z is the distance to the triangle.
Another point to note above is that after rotation and projection onto this plane, the vertex v0 lies is at the origin and v1 lies along the x axis.
HTH
I'm not sure that the suggestion is actually the best one. It's not too hard to project to the plane containing the triangle. I assume here that p is actually in that plane.
Let d1 = sqrt((v1-v0).(v1-v0)) - i.e. the distance v0-v1.
Similarly let d2 = sqrt((v2-v0).(v2-v0))
v0 -> (0,0)
v1 -> (d1, 0)
What about v2? Well, you know the distance v0-v2 = d2. All you need is the angle v1-v0-v2. (v1-v0).(v2-v0) = d1 d2 cos(theta). Wlog you can take v2 as having positive y.
Then apply a similar process to p, with one exception: you can't necessarily take it as having positive y. Instead you can check whether it has the same sign of y as v2 by taking the sign of (v1-v0)x(v2-v0) . (v1-v0)x(p-v0).
As an alternative solution, you could use a linear algebra solver on the matrix equation for the tetrahedral case, taking as the fourth vertex of the tetrahedron v0 + (v1-v0)x(v2-v0) and normalising if necessary.
You shouldn't need to determine the optimal area to find a decent projection.
It's not strictly necessary to find the "best" projection at all, just one that's good enough, and that doesn't degenerate to a line when projected into 2D.
EDIT - algorithm deleted due to degenerate case I hadn't thought of