Calculating distance to a path - math

I have a set of points that form a path. I would like to determine the minimum distance from any given point to this path. The path might look something like this:
points = [
[50, 58],
[53, 67],
[59, 82],
[64, 75],
[75, 73]
];
where the first value is the x coordinate and the second the y coordinate. The path is open ended (it will not form a closed loop) and is made of straight segments between the points.
So, given a point, eg. [90, 84], how to calculate the shortest distance from that point to the path?
I'm not necessarily looking for a complete solution, but any pointers and ideas will be appreciated.

It is possible to construct pathological cases in which the closest line segment to a point P connects two points which are themselves farther from P than any other points in the path. Therefore, unless I am missing something very subtle, you must calculate the distance to each line segment to get the shortest distance to the path.
Here is a simple example:
(5,1)-(4,2)-(1,3)-(20,3)-(15,2)-(14,1)
Given point (10,1), the closest distance to the path would be to the point (10,3), which is along the line segment (1,3)-(20,3), but those two points are farther from (10,1) than any other point in the path.
So I don't believe there are any shortcuts to the naïve algorithm of finding the distance to each line segment and taking the minimum.

The best thing would be to find the closest point from a line (making the path) measure the distance and move on along the path (and store the point for shortest distance).

The distance from a point C to a line segment AB is the area of the parallelogram ABCC'.

So, I just though about it for a second. erekalper already posted the distance between a point and a line. However, the problem with this formula is that it assumes the line has infinite length, which is not the case for your problem. Just an example for the problem: Assume a simple line that goes from (0,0) to (0,1) and a point with coordinates (0,10). The formula posted above would return o distance of 0, because if you extend the line it would hit the point. Unfortunately, in your case the line ends at (0,1), thus the distance is actually 9.
Thus my algorithm would be: Check if the angles at the endpoints of your lines are <= 90°. If so, the shortest distance for this path will be computable by the formula already posted. If not, the shortest distance is the distance to one of the endpoints. Do this for all parts of the path, choose the minimum

The distance between a point and a line is given by:
d = |(x_2 - x_1)(y_1 - y_0) - (x_1 - x_0)(y_2 - y_1)| / sqrt((x_2 - x_1)^2 - (y_2 - y_1)^2),
which is an expansion of the dot product, where (x_0, y_0) are the coordinates of the point, and (x_1, y_1) & (x_2, y_2) are the endpoints of the line.
It would be pretty simple to calculate this for each set of points, and then just determine which one is the lowest. I'm not unconvinced there's not a more elegant way to do so, but I'm not aware of it. Though I'd love to see if someone here answers with one!
Edit: Sorry that the math in here looks so messy without formatting. Here's an image of what this equation looks like, done nicely:
(from MathWorld - A Wolfram Web Resource: wolfram.com)
Another edit: As Chris pointed out in his post, this doesn't work if the points are in-line, i.e., if the line is defined by (0,0)-(0,1) and the point by (0,10). Like he explains, you need to check to make sure that the point being looked at isn't actually on the "extended path" of line itself. If it is, then it's just the distance between the closer endpoint and the point. All credit to Chris!

First you need to find out shortest distance to each line segment and then you choose the smallest distance. When you calculate the shortest distance, you need to find out the nearest point in the line segment. If the nearest point is not between the start and end point, you must use the distance to start or end point (whichever is the nearest).
This page has some formulas that you are likely to need.

You need to use linear algebra (shivers) to calculate the distance from the point to each of the lines.
Here is a link to an article that describes the math: Link
And here is a pretty good library. You need to look at the methods called PointSegmentDistance. A segment is apparently a line that begins at one point and ends at the second point, whereas a line has two points but continue in infinity.

Related

Shortest distance to cover all the (N+1) points. All the N points lie on x- axis. Remaining one point lies anywhere in the coordinate plane

Given (N+1) points. All the N points lie on x- axis. Remaining one point (HEAD point) lies anywhere in the coordinate plane.
Given a START point on x- axis.
Find the shortest distance to cover all the points starting from START point.We can traverse a point multiple times.
Example N+1=4
points on x axis
(0,1),(0,2),(0,3)
HEAD Point
(1,1) //only head point can lie anywhere //Rest all on x axis
START Point
(0,1)
I am looking for a method as of how to approach this problem.
Whether we should visit HEAD point first or HEAD point in between.
I tried to find a way using Graph Theory to simplify this problem and reduce the paths that need to be considered. If there is an elegant way to represent this problem using graphs to identify a solution, I was not able to find it. This approach becomes very inefficient as the n increases - the time and memory is O(2^n).
Looking at this as a tree graph, the root node would be the START point, then each of its child nodes would be the points it is connected to.
Since the START point and the rest of the points aside from the HEAD all lay on the x-axis, all non-HEAD points only need to be connected to adjacent points on the x-axis. This is because the distance of the path between any two points is the sum of the distances between any adjacent points along the path between those two points (the subset of nodes representing points on the x-axis does not need to form a complete graph). This reduces the brute force approach some.
Here's a simple example:
The upper left shows the original problem: points on the x-axis along with the START and HEAD points.
In the upper right, this has been transformed into a graph with each node representing a point from the original problem. The edges represent the paths that can be taken between points. This assumes that the START point only represents the first point in the path. Unlike the other nodes, it is only included in the path once. If that is not the case and the path can return to the START point, this would approximately double the possible paths, but the same approach can be followed.
In the bottom left, the START point, a, is the root of a tree graph, and each node connected to the START point is a child node. This process is repeated for each child node until either:
A path that is obviously not optimal is identified, in which case that node can just be excluded from the graph. See the nodes in red boxes; going back and forth between the same nodes is unnecessary.
All points are included when traversing the tree from the root to that node, producing a potential solution.
Note that when creating the tree graph, each time a node is repeated, its "potential" child nodes are the same as the first time the node was included. By "potential", I mean cases above still need to be checked, because the result might include a nonsensical path, in which case that node would not be included. It is also possible a potential solution results from the path after its child nodes are included.
The last step is to add up the distances for each of the potential solutions to determine which path is shortest.
This requires a careful examination of the different cases.
Assume for now START (S) is on the far left, and HEAD (H) is somewhere in the middle the path maybe something like
H
/ \
S ---- * ----*----* * --- * ----*
Or it might be shorter to from H to and from the one of the other node
H
//
S ---- * --- * -- *----------*---*
If S is not at one end you might have something like
H
/ \
* ---- * ----*----* * --- * ----*
--------S
Or even going direct from S to H on the first step
H
/ |
* ---- * ----*----* |
S
A full analysis of cases would be quite extensive.
Actually solving the problem, might depend on the number of nodes you have. If the number is small < 10, then compete enumeration might be possible. Just work out every possible path, eliminate the ones which are illegal, and choose the smallest. The number of paths is I think in the order of n!, so its computable for small n.
For large n you can break the problem into small segments. I think its enough just to consider a small patch with nodes either side of H and a small patch with nodes either side of S.
This is not really a solution, but a possible way to think about tackling the problem.
(To be pedantic stackoverflow.com is not the right site for this question in the stack exchange network. Computational Science : algorithms might be a better place.
This is a fun problem. First, lets try to find a brute force solution, as Poosh did.
Observations about the Shortest Path
No repeated points
You are in an Euclidean geometry, thus the triangle inequality holds: For all points a,b,c, the distance d(a,b) + d(b,c) <= d(a,c). Thus, whenever you have an optimal path that contains a point that occurs more than once, you can remove one of them, which means it is not an optimal path, which leads to a contradiction and proves that your optimal path contains each point exactly once.
Permutations
Our problem is thus to find the permutation, lets call it M_i, of the numbers 1...n for points P1...Pn (where P0 is the fixed start point and Pn the head point, P1...Pn-1 are ordered by increasing x value) that minimizes the sum of |(P_M_i)-(P_M_(i-1))| for i from 1 to n, || being the vector length sqrt(v_x²+v_y²).
The number of permutations of a set of size n is n!. In this case we have n+1 points, so a brute force approach testing all permutations would have complexity (n+1)!, which is higher than even 2^n and definitely not practical, so we need further observations to improve this.
Next Steps
My next step would now be to see if there are any other sequences that can be proven to be not optimal, leading to a reduction in the number of candidates to be tested.
Paths of non-head points
Lets look at all paths (sequences of indices of points that don't contain a head point and that are parts of the optimal path. If we don't change the start and end point of a path, then any other transpositions have no effect on the outside environment and we can perform purely local optimizations. We can prove that those sequences must have monotonic (increasing or decreasing) x coordinate values and thus monotonic indices (as they are ordered by ascending x coordinate between indices 0 and n-1):
We are in a purely one dimensional subspace and the total distance of the path is thus equal to the sum of the absolute values of the differences in x coordinates between one such point and the next. It is clear that this sum is minimized by ordering by x coordinate in either ascending or descending order and thus ordering the indices in the same way. Note that this is true for maximal such paths as well as for all continuous "subpaths" of them.
Wrapping it up
The only choices we have left are:
where do we place the head node in the optimal path?
which way do we order the two paths to the left and right?
This means we have n values for the index of the head node (1...n, 0 is fixed as the start node) and 2x2 values for sort order. So we have 4n choices which we can all calculate and pick the shortest one. One of the sort orders probably determines the other but I leave that to you.
Anyways, the complexity of this algorithm is O(4n) = O(n). Because reading in the input of the problems is in O(n) and writing the output is as well, I believe that is an algorithm of optimal complexity. However, if we could reformulate the problem somewhat, so that we could read and write the input and output in some compressed form, as in only the parameters that we actually need to solve the problem, then it is possible that we could do better.
P.S.: I'm not a mathematician so I probably used wrong words for some concepts and missed the usual notation for the variables and functions. I would be glad for some expert to check this for any obvious errors.

how to find if a particular point exists between two concentric circles or not???i have 3 points given on each circle

i have two concentric circles and three points are given for each circle that are on circumference.
I need a optimized method to check if a given random point exist inbetween these circles or not.
You can compute (x²+y²), x, y, 1 for each point. The last entry is simply the constant one. Put these terms for four given points into a matrix and compute its determinant. The determinant will be zero if the points are cocircular. Otherwise the sign will tell you which point is on which side with respect to the circle defined by the other three. Use a simple example to check which sign corresponds to which direction. Be prepared for the fact that the three circle-defining points being oriented in a clockwise or counter-clockwise orientation will affect this sign, too.
Computing a 4×4 determinant can be done horribly inefficiently, too. I'd suggest you compute all the 2×2 minors from the first two rows, and all the 2×2 minors from the last two, then you can combine them to form the full determinant. See this Math SE post for details. If you need further mathematical help (as opposed to programming help), you might find more suitable answers there.
Nothe that the above works for each circle independently. Check whether the point is inside the one, then check whether it is outside the other. It does not make use of the fact that the circles are assumed to be cocircular.

Check which side of a plane points are on

I'm trying to take an array of 3D points and a plane and divide the points up into 2 arrays based on which side of the plane they are on. Before I get to heavily into debugging I wanted to post what I'm planning on doing to make sure my understanding of how to do this will work.
Basically I have the plane with 3 points and I use (pseudo code):
var v1 = new vector(plane.b.x-plane.a.x, plane.b.y-plane.a.y, plane.b.z-plane.a.z);
var v2 = new vector(plane.c.x-plane.a.x, plane.c.y-plane.a.y, plane.c.z-plane.a.z);
I take the cross product of these two vectors to get the normal vector.
Then I loop through my array of points and turn them into vectors and calculate the dot product against the normal.
Then i use the dot product to determine the side that the point is on.
Does this sound like it would work?
Let a*x+b*y+c*z+d=0 be the equation determining your plane.
Substitute the [x,y,z] coordinates of a point into the left hand side of the equation (I mean the a*x+b*y+c*z+d) and look at the sign of the result.
The points having the same sign are on the same side of the plane.
Honestly, I did not examine the details of what you wrote. I guess you agree that what I propose is simpler.
Following the 'put points into the plane's equation and check the sign' approach given previously. The equation can be easily obtained using SymPy. I used it to find location of points (saved as numpy arrays) in a list of points.
from sympy import Point3D, Plane
plane=Plane(Point3D(point1), Point3D(point2), Point3D(point3))
for point in pointList:
if plane.equation(x=point[0], y=point[1],z=point[2]) > 0:
print "point is on side A"
else:
print "point is on side B"
I haven't tested its speed compared to other methods mentioned above but is definitely the easiest method.
Your approach sounds good. However, when you say "and turn them into vectors", it might not be good (depending on the meaning of your sentence).
You should "turn your points into vector" by computing the difference in terms of coordinates between the current point and one of the points in the plane (for example, one of the 3 points defining the plane). As you wrote it, it sounds like you might have misunderstood that ; but apart from that, it's ok!
take into account the normal vector of the plane
example: for the point A=[-243.815437431962, -41.7407630281635, 10.0]
equation= -2663.1860000000006*Z +21305.488000000005=0
RESULt POSITIVE
but if equation= 2663.1860000000006*Z -21305.488000000005=0
RESULT NEGATIVE

Closest Approach question for math/physics heads

I'm using a Segment to Segment closest approach method which will output the closest distance between two segments of length. Each segment corresponds to a sphere object's origin and destination. The speed is simply from one point, to the other.
Closest Approach can succeed even when there won't be a real collision. So, I'm currently using a 10-step method and calculating the distance between 2 spheres as they move along the two segments. So, basically the length of each segment is the object's traverse in the physics step, and the radius is the objects radius. By stepping, I can tell where they collide, and if they collide (Sort of; for the MOST part.)..
I get the feeling that there could be something better. While I sort of believe that the first closest approach call is required, I think that the method immediately following it is a TAD weak. Can anyone help me out? I can illustrate this if needed.
Thanks alot!
(source: yfrog.com)
(I don't know how to post graphics; bear with me.)
All right, we have two spheres with radii r1 and r2, starting at locations X1 and X2, moving with velocities V1 and V2 (X's and V's are vectors).
The velocity of sphere 1 as seen from sphere 2 is
V = V1-V2
and its direction is
v = V/|V|
The distance sphere 1 must travel (in the frame of sphere 2) to closest approach is
s = Xv
And if X is the initial separation, then the distance of closest approach is
h = |X - Xv|
This is where graphics would help. If h > r1+r2, there will be no collision. Suppose h < r1+r2. At the time of collision, the two sphere centers and the point of closest approach will form a right triangle. The distance from Sphere 1's center to the point of closest approach is
u = sqrt((r1 + r2)^2 - h^2)
So the distance sphere 1 has traveled is
s - u
Now just see if sphere 1 travels that far in the given interval. If so, then you know exactly when and where the spheres were (you must shift back from sphere 2's frame, but that's pretty easy). If not, there's no collision.
Closest approach can be done without simulating time if the position function is invertible and explicit.
Pick a path and object.
Find the point on the path where the two paths are closest. If time has bounds (e.g. paths are line segments), ignore the bounds in this step.
Find the time at which the object is at the point from the previous step.
If time has bounds, limit the picked time by the bounds.
Calculate the position of the other object at the time from the previous step.
Check if the objects overlap.
This won't work for all paths (e.g. some cubic), but should work for linear paths.

Calculating rotation along a path

I am trying to animate an object, let's say its a car. I want it go from point
x1,y1,z1
to point x2,y2,z2 . It moves to those points, but it appears to be drifting rather than pointing in the direction of motion. So my question is: how can I solve this issue in my updateframe() event? Could you point me in the direction of some good resources?
Thanks.
First off how do you represent the road?
I recently done exactly this thing and I used Catmull-Rom splines for the road. To orient an object and make it follow the spline path you need to interpolate the current x,y,z position from a t that walks along the spline, then orient it along the Frenet Coordinates System or Frenet Frame for that particular position.
Basically for each point you need 3 vectors: the Tangent, the Normal, and the Binormal. The Tangent will be the actual direction you will like your object (car) to point at.
I choose Catmull-Rom because they are easy to deduct the tangents at any point - just make the (vector) difference between 2 other near points to the current one. (Say you are at t, pick t-epsilon and t+epsilon - with epsilon being a small enough constant).
For the other 2 vectors, you can use this iterative method - that is you start with a known set of vectors on one end, and you work a new set based on the previous one each updateframe() ).
You need to work out the initial orientation of the car, and the final orientation of the car at its destination, then interpolate between them to determine the orientation in between for the current timestep.
This article describes the mathematics behind doing the interpolation, as well as some other things to do with rotating objects that may be of use to you. gamasutra.com in general is an excellent resource for this sort of thing.
I think interpolating is giving the drift you are seeing.
You need to model the way steering works .. your update function should 1) move the car always in the direction of where it is pointing and 2) turn the car toward the current target .. one should not affect the other so that the turning will happen and complete more rapidly than the arriving.
In general terms, the direction the car is pointing is along its velocity vector, which is the first derivative of its position vector.
For example, if the car is going in a circle (of radius r) around the origin every n seconds then the x component of the car's position is given by:
x = r.sin(2πt/n)
and the x component of its velocity vector will be:
vx = dx/dt = r.(2π/n)cos(2πt/n)
Do this for all of the x, y and z components, normalize the resulting vector and you have your direction.
Always pointing the car toward the destination point is simple and cheap, but it won't work if the car is following a curved path. In which case you need to point the car along the tangent line at its current location (see other answers, above).
going from one position to another gives an object a velocity, a velocity is a vector, and normalising that vector will give you the direction vector of the motion that you can plug into a "look at" matrix, do the cross of the up with this vector to get the side and hey presto you have a full matrix for the direction control of the object in motion.

Resources