Related
For 2-dimensional sampled curves (an array of 2D points) there exists the Rahmer-Douglas-Peucker algorithm which only keeps "important" points. It works by calculating the perpendicular distance of each point (or sample) to a line that connects the first and the last point of. If the maximum distance is larger than a value epsilon the point is kept and the array is split into 2 parts. For both parts the operation is repeated (maximal perpendicular distance, if larger than epsilon etc.) The smaller epsilon the more detail is kept.
I am trying to write a function that can also do this for higher arrays of higher dimensional points. But I am unsure how to define distance. Or if this is actually a good idea.
I guess there exist lots of complicated and elegant algorithms that fit the curves to beziers and NURBS and what not. But are there also relatively simple ones?
I would prefer not to use beziers, but simply to identify "important" N-dimensional points.
You could extend your 2D algorithm using algebra and the L2 norm. Let's say you want to calculate the distance from a point X to a line segment PQ (where X, P and Q are defined as N-dimensional vectors).
First you can calculate the vector "proj" as:
Then, the distance is the module of the vector V = PX-proj.
For this calculation you only need the dot product between vectors, and that is well defined for N-dimensional spaces.
Using this approach I have successfuly used Rahmer-Douglas-Peucker algorithm in 3D.
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 have a set of points (with unknow coordinates) and the distance matrix. I need to find the coordinates of these points in order to plot them and show the solution of my algorithm.
I can set one of these points in the coordinate (0,0) to simpify, and find the others. Can anyone tell me if it's possible to find the coordinates of the other points, and if yes, how?
Thanks in advance!
EDIT
Forgot to say that I need the coordinates on x-y only
The answers based on angles are cumbersome to implement and can't be easily generalized to data in higher dimensions. A better approach is that mentioned in my and WimC's answers here: given the distance matrix D(i, j), define
M(i, j) = 0.5*(D(1, j)^2 + D(i, 1)^2 - D(i, j)^2)
which should be a positive semi-definite matrix with rank equal to the minimal Euclidean dimension k in which the points can be embedded. The coordinates of the points can then be obtained from the k eigenvectors v(i) of M corresponding to non-zero eigenvalues q(i): place the vectors sqrt(q(i))*v(i) as columns in an n x k matrix X; then each row of X is a point. In other words, sqrt(q(i))*v(i) gives the ith component of all of the points.
The eigenvalues and eigenvectors of a matrix can be obtained easily in most programming languages (e.g., using GSL in C/C++, using the built-in function eig in Matlab, using Numpy in Python, etc.)
Note that this particular method always places the first point at the origin, but any rotation, reflection, or translation of the points will also satisfy the original distance matrix.
Step 1, arbitrarily assign one point P1 as (0,0).
Step 2, arbitrarily assign one point P2 along the positive x axis. (0, Dp1p2)
Step 3, find a point P3 such that
Dp1p2 ~= Dp1p3+Dp2p3
Dp1p3 ~= Dp1p2+Dp2p3
Dp2p3 ~= Dp1p3+Dp1p2
and set that point in the "positive" y domain (if it meets any of these criteria, the point should be placed on the P1P2 axis).
Use the cosine law to determine the distance:
cos (A) = (Dp1p2^2 + Dp1p3^2 - Dp2p3^2)/(2*Dp1p2* Dp1p3)
P3 = (Dp1p3 * cos (A), Dp1p3 * sin(A))
You have now successfully built an orthonormal space and placed three points in that space.
Step 4: To determine all the other points, repeat step 3, to give you a tentative y coordinate.
(Xn, Yn).
Compare the distance {(Xn, Yn), (X3, Y3)} to Dp3pn in your matrix. If it is identical, you have successfully identified the coordinate for point n. Otherwise, the point n is at (Xn, -Yn).
Note there is an alternative to step 4, but it is too much math for a Saturday afternoon
If for points p, q, and r you have pq, qr, and rp in your matrix, you have a triangle.
Wherever you have a triangle in your matrix you can compute one of two solutions for that triangle (independent of a euclidean transform of the triangle on the plane). That is, for each triangle you compute, it's mirror image is also a triangle that satisfies the distance constraints on p, q, and r. The fact that there are two solutions even for a triangle leads to the chirality problem: You have to choose the chirality (orientation) of each triangle, and not all choices may lead to a feasible solution to the problem.
Nevertheless, I have some suggestions. If the number entries is small, consider using simulated annealing. You could incorporate chirality into the annealing step. This will be slow for large systems, and it may not converge to a perfect solution, but for some problems it's the best you and do.
The second suggestion will not give you a perfect solution, but it will distribute the error: the method of least squares. In your case the objective function will be the error between the distances in your matrix, and actual distances between your points.
This is a math problem. To derive coordinate matrix X only given by its distance matrix.
However there is an efficient solution to this -- Multidimensional Scaling, that do some linear algebra. Simply put, it requires a pairwise Euclidean distance matrix D, and the output is the estimated coordinate Y (perhaps rotated), which is a proximation to X. For programming reason, just use SciKit.manifold.MDS in Python.
The "eigenvector" method given by the favourite replies above is very general and automatically outputs a set of coordinates as the OP requested, however I noticed that that algorithm does not even ask for a desired orientation (rotation angle) for the frame of the output points, the algorithm chooses that orientation all by itself!
People who use it might want to know at what angle the frame will be tipped before hand so I found an equation which gives the answer for the case of up to three input points, however I have not had time to generalize it to n-points and hope someone will do that and add it to this discussion. Here are the three angles the output sides will form with the x-axis as a function of the input side lengths:
angle side a = arcsin(sqrt(((c+b+a)*(c+b-a)*(c-b+a)*(-c+b+a)*(c^2-b^2)^2)/(a^4*((c^2+b^2-a^2)^2+(c^2-b^2)^2))))*180/Pi/2
angle side b = arcsin(sqrt(((c+b+a)*(c+b-a)*(c-b+a)*(-c+b+a)*(c^2+b^2-a^2)^2)/(4*b^4*((c^2+b^2-a^2)^2+(c^2-b^2)^2))))*180/Pi/2
angle side c = arcsin(sqrt(((c+b+a)*(c+b-a)*(c-b+a)*(-c+b+a)*(c^2+b^2-a^2)^2)/(4*c^4*((c^2+b^2-a^2)^2+(c^2-b^2)^2))))*180/Pi/2
Those equations also lead directly to a solution to the OP's problem of finding the coordinates for each point because: the side lengths are already given from the OP as the input, and my equations give the slope of each side versus the x-axis of the solution, thus revealing the vector for each side of the polygon answer, and summing those sides through vector addition up to a desired vertex will produce the coordinate of that vertex. So if anyone can extend my angle equations to handling beyond three input lengths (but I note: that might be impossible?), it might be a very fast way to the general solution of the OP's question, since slow parts of the algorithms that people gave above like "least square fitting" or "matrix equation solving" might be avoidable.
Given the points of a line and a quadratic bezier curve, how do you calculate their nearest point?
There exist a scientific paper regarding this question from INRIA: Computing the minimum distance between two Bézier curves (PDF here)
I once wrote a tool to do a similar task. Bezier splines are typically parametric cubic polynomials. To compute the square of the distance between a cubic segment and a line, this is just the square of the distance between two polynomial functions, itself just another polynomial function! Note that I said the square of the distance, not the square root.
Essentially, for any point on a cubic segment, one could compute the square of the distance from that point to the line. This will be a 6th order polynomial. Can we minimize that square of the distance? Yes. The minimum must occur where the derivative of that polynomial is zero. So differentiate, getting a 5th order polynomial. Use your favorite root finding tool that generates all of the roots numerically. Jenkins & Traub, whatever. Choose the correct solution from that set of roots, excluding any solutions that are complex, and only picking a solution if it lies inside the cubic segment in question. Make sure you exclude the points that correspond to local maxima of the distance.
All of this can be efficiently done, and no iterative optimizer besides a polynomial root finder need be used, thus one does not require the use of optimization tools that require starting values, finding only a solution near that starting value.
For example, in the 3-d figure I show a curve generated by a set of points in 3-d (in red), then I took another set of points that lay in a circle outside, I computed the closest point on the inner curve from each, drawing a line down to that curve. These points of minimum distance were generated by the scheme outlined above.
I just wanna give you a few hints, in for the case Q.B.Curve // segment :
to get a fast enough computation, i think you should first think about using a kind of 'bounding box' for your algorithm.
Say P0 is first point of the Q. B. Curve, P2 the second point, P1 the control point, and P3P4 the segment then :
Compute distance from P0, P1, P2 to P3P4
if P0 OR P2 is nearest point --> this is the nearest point of the curve from P3P4. end :=).
if P1 is nearest point, and Pi (i=0 or 1) the second nearest point, the distance beetween PiPC and P3P4 is an estimate of the distance you seek that might be precise enough, depending on your needs.
if you need to be more acurate : compute P1', which is the point on the Q.B.curve the nearest from P1 : you find it applying the BQC formula with t=0.5. --> distance from PiP1' to P3P4 is an even more accurate estimate -but more costly-.
Note that if the line defined by P1P1' intersects P3P4, P1' is the closest point of QBC from P3P4.
if P1P1' does not intersect P3P4, then you're out of luck, you must go the hard way...
Now if (and when) you need precision :
think about using a divide and conquer algorithm on the parameter of the curve :
which is nearest from P3P4 ?? P0P1' or P1'P2 ??? if it is P0P1' --> t is beetween 0 and 0.5 so compute Pm for t=0.25.
Now which is nearest from P3P4?? P0Pm or PmP1' ?? if it is PmP1' --> compute Pm2 for t=0.25+0.125=0.375 then which is nearest ? PmPm2 or Pm2P1' ??? etc
you will come to accurate solution in no time, like 6 iteration and your precision on t is 0.004 !! you might stop the search when distance beetween two points becomes below a given value. (and not difference beetwen two parameters, since for a little change in parameter, points might be far away)
in fact the principle of this algorithm is to approximate the curve with segments more and more precisely each time.
For the curve / curve case i would first 'box' them also to avoid useless computation, so first use segment/segment computation, then (maybe) segment/curve computation, and only if needed curve/curve computation.
For curve/curve, divide and conquer works also, more difficult to explain but you might figure it out. :=)
hope you can find your good balance for speed/accuracy with this :=)
Edit : Think i found for the general case a nice solution :-)
You should iterate on the (inner) bounding triangles of each B.Q.C.
So we have Triangle T1, points A, B, C having 't' parameter tA, tB, tC.
and Triangle T2, points D, E, F, having t parameter tD, tE, tF.
Initially we have tA=0 tB=0.5 tC= 1.0 and same for T2 tD=0, tE=0.5, tF=1.0
The idea is to call a procedure recursivly that will split T1 and/or T2 into smaller rectangles until we are ok with the precision reached.
The first step is to compute distance from T1 from T2, keeping track of with segments were the nearest on each triangle. First 'trick': if on T1 the segment is AC, then stop recursivity on T1, the nearest point on Curve 1 is either A or C. if on T2 the nearest segment is DF, then stop recursivity on T2, the nearest point on Curve2 is either D or F. If we stopped recursivity for both -> return distance = min (AD, AF, CD, CF). then if we have recursivity on T1, and segment AB is nearest, new T1 becomes : A'=A B= point of Curve one with tB=(tA+tC)/2 = 0.25, C=old B. same goes for T2 : apply recursivityif needed and call same algorithm on new T1 and new T2. Stop algorithm when distance found beetween T1 and T2 minus distance found beetween previous T1 and T2 is below a threshold.
the function might look like ComputeDistance(curveParam1, A, C, shouldSplitCurve1, curveParam2, D, F, shouldSplitCurve2, previousDistance) where points store also their t parameters.
note that distance (curve, segment) is just a particular case of this algorithm, and that you should implement distance (triangle, triangle) and distance (segment, triangle) to have it worked. Have fun.
1.Simple bad method - by iteration go by point from first curve and go by point from second curve and get minimum
2.Determine math function of distance between curves and calc limit of this function like:
|Fcur1(t)-Fcur2(t)| ->0
Fs is vector.
I think we can calculate the derivative of this for determine extremums and get nearest and farest points
I think about this some time later, and post full response.
Formulate your problem in terms of standard analysis: You have got a quantity to minimize (distance), so you formulate an equation for this quantity and find the points where the first derivatives are zero. Parameterize with a single parameter by using the curve's parameter p, which is between 0 for the first point and 1 for the last point.
In the line case, the equation is fairly simple: Get the x/y coordinates from the spline's equation and compute the distance to the given line via vector equations (scalar product with the line's normal).
In the curve's case, the analytical solution could get pretty complicated. You might want to use a numerical minimization technique such as Nelder-Mead or, since you have a 1D continuous problem, simple bisection.
In the case of a Bézier curve and a line
There are three candidates for the closest point to the line:
The place on the Bézier curve segment that is parallel to the line (if such a place exists),
One end of the curve segment,
The other end of the curve segment.
Test all three; the shortest distance wins.
In the case of two Bézier curves
Depends if you want the exact analytical result, or if an optimised numerical result is good enough.
Analytical result
Given two Bézier curves A(t) and B(s), you can derive equations for their local orientation A'(t) and B'(s). The point pairs for which A'(t) = B'(s) are candidates, i.e. the (t, s) for which the curves are locally parallel. I haven't checked, but I assume that A'(t) - B'(s) = 0 can be solved analytically. If your curves are anything like those you show in your example, there should be either only one solution or no solution to that equation, but there could be two (or infinitely many in the case where the curves identical but translated -- in which case you can ignore this because the winner will always be one of the curve segment endpoints).
In an approach similar to the curve-line case outline above, test each of these point pairs, plus the curve segment endpoints. The shortest distance wins.
Numerical result
Let's say the points on the two Bézier curves are defined as A(t) and B(s). You want to minimize the distance d( t, s) = |A(t) - B(s)|. It's a simple two-parameter optimization problem: find the s and t that minimize d( t, s) with the constraints 0 ≤ t ≤ 1 and 0 ≤ s ≤ 1.
Since d = SQRT( ( xA - xB)² + (yA - yB)²), you can also just minimize the function f( t, s) = [d( t, s)]² to save a square root calculation.
There are numerous ready-made methods for such optimization problems. Pick and choose.
Note that in both cases above, anything higher-order than quadratic Bézier curves can giver you more than one local minimum, so this is something to watch out for. From the examples you give, it looks like your curves have no inflexion points, so this concern may not apply in your case.
The point where there normals match is their nearest point. I mean u draw a line orthogonal to the line. .if that line is orthogonal to the curve as well then the point of intersection is the nearest point
I'm not sure if this is the right place to ask, but here goes...
Short version: I'm trying to compute the orientation of a triangle on a plane, formed by the intersection of 3 edges, without explicitly computing the intersection points.
Long version: I need to triangulate a PSLG on a triangle in 3D. The vertices of the PSLG are defined by the intersections of line segments with the plane through the triangle, and are guaranteed to lie within the triangle. Assuming I had the intersection points, I could project to 2D and use a point-line-side (or triangle signed area) test to determine the orientation of a triangle between any 3 intersection points.
The problem is I can't explicitly compute the intersection points because of the floating-point error that accumulates when I find the line-plane intersection. To figure out if the line segments strike the triangle in the first place, I'm using some freely available robust geometric predicates, which give the sign of the volume of a tetrahedron, or equivalently which side of a plane a point lies on. I can determine if the line segment endpoints are on opposite sides of the plane through the triangle, then form tetrahedra between the line segment and each edge of the triangle to determine whether the intersection point lies within the triangle.
Since I can't explicitly compute the intersection points, I'm wondering if there is a way to express the same 2D orient calculation in 3D using only the original points. If there are 3 edges striking the triangle that gives me 9 points in total to play with. Assuming what I'm asking is even possible (using only the 3D orient tests), then I'm guessing that I'll need to form some subset of all the possible tetrahedra between those 9 points. I'm having difficultly even visualizing this, let alone distilling it into a formula or code. I can't even google this because I don't know what the industry standard terminology might be for this type of problem.
Any ideas how to proceed with this? Thanks. Perhaps I should ask MathOverflow as well...
EDIT: After reading some of the comments, one thing that occurs to me... Perhaps if I could fit non-overlapping tetrahedra between the 3 line segments, then the orientation of any one of those that crossed the plane would be the answer I'm looking for. Other than when the edges enclose a simple triangular prism, I'm not sure this sub-problem is solvable either.
EDIT: The requested image.
I am answering this on both MO & SO, expanding the comments I made on MO.
My sense is that no computational trick with signed tetrahedra volumes will avoid the precision issues that are your main concern. This is because, if you have tightly twisted segments, the orientation of the triangle depends on the precise positioning of the cutting plane.
[image removed; see below]
In the above example, the upper plane crosses the segments in the order (a,b,c) [ccw from above]: (red,blue,green), while the lower plane crosses in the reverse order (c,b,a): (green,blue,red). The height
of the cutting plane could be determined by your last bit of precision.
Consequently, I think it makes sense to just go ahead and compute the points of intersection in
the cutting plane, using enough precision to make the computation exact. If your segment endpoints coordinates and plane coefficients have L bits of precision, then there is just a small constant-factor increase needed. Although I am not certain of precisely what that factor is, it is small--perhaps 4. You will not need e.g., L2 bits, because the computation is solving linear equations.
So there will not be an explosion in the precision required to compute this exactly.
Good luck!
(I was prevented from posting the clarifying image because I don't have the reputation. See
the MO answer instead.)
Edit: Do see the MO answer, but here's the image:
I would write symbolic vector equations, you know, with dot and cross products, to find the normal of the intersection triangle. Then, the sign of the dot product of this normal with the initial triangle one gives the orientation. So finally you can express this in a form sign(F(p1,...,p9)), where p1 to p9 are your points and F() is an ugly formula including dot and cross products of differences (pi-pj). Don't know if this can be done simpler, but this general approach does the job.
As I understand it, you have three lines intersecting the plane, and you want to calculate the orientation of the triangle formed by the intersection points, without calculating the intersection points themselves?
If so: you have a plane
N·(x - x0) = 0
and six points...
l1a, l1b, l2a, l2b, l3a, l3b
...forming three lines
l1 = l1a + t(l1b - l1a)
l2 = l2a + u(l2b - l2a)
l3 = l3a + v(l3b - l3a)
The intersection points of these lines to the plane occur at specific values of t, u, v, which I'll call ti, ui, vi
N·(l1a + ti(l1b - l1a) - x0) = 0
N·(x0 - l1a)
ti = ----------------
N·(l1b - l1a)
(similarly for ui, vi)
Then the specific points of intersection are
intersect1 = l1a + ti(l1b - l1a)
intersect2 = l2a + ui(l2b - l2a)
intersect3 = l3a + vi(l3b - l3a)
Finally, the orientation of your triangle is
orientation = direction of (intersect2 - intersect1)x(intersect3 - intersect1)
(x is cross-product) Work backwards plugging the values, and you'll have an equation for orientation based only on N, x0, and your six points.
Let's call your triangle vertices T[0], T[1], T[2], and the first line segment's endpoints are L[0] and L[1], the second is L[2] and L[3], and the third is L[4] and L[5]. I imagine you want a function
int Orient(Pt3 T[3], Pt3 L[6]); // index L by L[2*i+j], i=0..2, j=0..1
which returns 1 if the intersections have the same orientation as the triangle, and -1 otherwise.
The result should be symmetric under interchange of j values, antisymmetric under interchange of i values and T indices. As long as you can compute a quantity with these symmetries, that's all you need.
Let's try
Sign(Product( Orient3D(T[i],T[i+1],L[2*i+0],L[2*i+1]) * -Orient3D(T[i],T[i+1],L[2*i+1],L[2*i+0]) ), i=0..2))
where the product should be taken over cyclic permutations of the indices (modulo 3). I believe this has all the symmetry properties required. Orient3D is Shewchuk's 4-point plane orientation test, which I assume you're using.