Determine if two lines intersect - math

I've seen many postings here on stackoverflow, which are discussing this topic. I took a solution from stackoverflow, but I couldn't find the posting. It was to say: If two lines are intersecting, then the crossproduct produces for the left and the right side two different results. One positive and one negative. Otherwise both have the same sign. So far it is okay.
The used formula is, where AB is one line and CD another.
dotproductleft = (B.x-A.x)(C.y-B.y)-(B.y-A.y)(C.x-B.x)
dotproductright = (B.x-A.x)(D.y-B.y)-(B.y-A.y)(D.x-B.x)
If I calculate this for the following given GPS coordinates I get an intersection, in a case where no intersection is possible.
A: x: 15.4433917 y: 47.0697272
B: x: 15.4433661 y: 47.0697722
C: x: 15.4434363 y: 47.0696776
D: x: 15.442966 y: 47.0700098
If I draw it on Google Maps Engine, I can see that there definitely no intersection between these lines.
The results for dotproductleft: -7.372399999828474E-10 and for dotproductright: 1.1921940000328E-8
It is working for other examples very well, but here I've seen that it is not working right. But I couldn't spot any error in the formula.

The lines which contain any line segment (e.g. AB and CD) will always intersect (unless they are parallel).
You want to check if the line segments intersect. This is easy to do by finding the point of intersection and checking if it lies on both line segments.
So, using your example, the two lines (on which line segments AB and CD lie on) intersect at P = (15.4434,47.0697). Now, if P lies on AB then the dot product of PA and PB is negative (since the angle between PA and PB is 180° and cos(180°)=-1).
If you compute the dot product of PA and PB, you will get a positive number (thus it does not lie on AB). However, the dot product of PC and PD gives you a negative number (thus it lies on CD).
Thus, you can check if the line segments intersect if the aforementioned dot products (with the point of intersection) are negative.

Related

finding if a point lies within a set distance from a line, knowing only points along the line

I need to ensure that a point is no more than x distance from a line derived from multiple other points.
If I plot lat/long points every 3 miles, I can infer a 'line' to travel. I want to make sure that 'potential' destinations are no more than 1 mile from that line. (the "multiple" points wont always be the same from instance to instance, BUT will be consistent per instance, and the "acceptable" distance from the line can vary per instance).
The tricky part is I have points, not a line...(the line is implied). Things work out "ok" if my "acceptable distance" is greater then my distance between the multiple points. however... If, say, my multiples are 2.5 apart, and I say a distance of 1 is acceptable for any point of interest. Then there are points between the two original points, that lie along the line but I can figure easily.
So I though since I have ONE measurement, I know the length of a line (on x axis, the distance between 2 of the multiple points..). I could treat that as one of two equal sides of a triangle and figure the hypotenuse.
d = distance between (each, multiple) points.
a = ( d/2 )
b = ( d/2 )
c = sq root of ( a^2 + b^2 )
C is going to be slightly larger then my initial "acceptable distance", so I'll use that.
Is there an better way to figure???
thx
Lets see if I can illustrate
point A point B
O----------------------------------O
distance form point A to point B is 5 miles...
Now...
point A point B
O----------------------------------O
point C
O
Question: is point C inside of 1 mile from the line that connects point A and B?????
How does one express this with math? such that the distance between points can be expressed as a variable.
This is a mapping problem, points of interest close to a 'road' or 'path' that has sample points as Lat/long the point of interest also has a lat/long.
If I use a triangle or intersecting circles, I end up with peaks or humps that are well outside of my 'acceptable distance off path', just to accommodate the space between my samples.
I hope that makes sense.
You can find the distance from a line which is defined by two points using the formula here -> http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
A perpendicular line segment will be your friend in this problem. Find a line segment perpendicular to AB which contains point C.
The intersection of the line segments would be point D.
Get the distance of segment CD and you have your answer.

Tangent circle(s) for two other circles?

There are two circles: a centered at point A, and circle b (center at B). What is the equation to calculate 2D position of all or none tangent circles possible. Main constraint is, that radius is the same for all the circles. As far as I know, there should be either no solution (figure 2), or 2 solutions (figure 1). How to find out if there are solutions, and also position of centers of those solutions (C and D).
Figure 1: 2 solutions should be possible here
Figure 2: No solutions!
Update (solution):
1) Calculate distance from A to B -> |AB|:
2) Checks whether a solution exist, it exist only if:
3) If it exist, calculate half-point between points A and B:
4) Create normalized perpendicular vector to line segment AB:
5) Calculate distance from this H point to C point -> |HC|:
6) Finally calculate point C along the (HC) starting at X at distance |HC|:
I suppose this question should migrate to a more math related site.
Try to imagine where these two tangent circles go when the circles a and b get further and further apart. They get closer to the line AB. Once the AB segment equals 4r these two tangent circles will overlap. From now on, once circles a and b get further apart, there's no tangent circles whatsoever.
If you want to calculate the position of these circles, just assume that the distance between the centers is always 2r:
You should get two, one or none solutions for xC and yC, which will be the centers of your tangent circles. I hope I haven't messed something up.
Solutions
Provided you do know there are solutions ( just check if d(A,B) <= 4r ), these are the coordinates of your two circles:
http://pastebin.com/LeW7Ws98
A little scary, eh? But it's working. There are the following variables:
x_A, y_A - the coordinates of the circle A,
x_B, y_B - the coordinates of the circle B,
r - the radius.
I've checked the solutions with the values from one of my comments below. I think that you can copy these solutions and inject them into your code straight away (provided there's a sqrt function) and get the results after declaring some variables.
These solutions are loosely derived from the Save's proposition but I couldn't comment below his answer - I've got less than 50 reputation points, duh ... ( thanks SO! You're the man! ). However I'm pretty sure they should be valid for my system anyways. Cheers
A solution exists iff d(A,B) = sqrt(2)*2*r
To find the center of the solution circles, that will let you draw the circonferences, you can intersect the circle with center (x_m,y_m), that is the medium point of the segment AB, of radius sqrt(2)*r, with the line perpendicular to AB and passing from (x_m,y_m)
This should give you all the needed information to check if a solution exixsts, and if it does, to draw it.

Compute the tortuosity of a polyline

I have series of (x, y) coordinates, if joined this represent a polyline. This polyline is a geographic track.
All that I need is to get the polyline tortuosity. It should be usefull a sort of percentage. E.g. The path has x% tortuosity.
well, it all depends on how you define tortuosity. there is a wikipedia article regarding tortuosity, which may shed some light on the subject.
an interesting sentence in the article tells us that: "roughness (or tortuosity) could be measured by relative change of curvature". that makes a good starting point.
your polyline is made of adjacent line segments. you can compute the angle between each adjacent line segment. using this information you can get a good idea of tortuosity for your polyline. for example, let seg(n) be the line segment between point n and point n+1:
tortuosity = sum(abs(angle(seg(n), seg(n+1))) for n in 1 to number of segment)
(computing the angle between 2 line segments is left as an exercise, but does not require a degree in mathematics)
the above measure is not scaled: the more points you have, the higher the value might be. you can easily scale this result according to the number of line segments you have:
unit_tortuosity = tortuosity / (n * pi)
(the maximum angle between 2 line segments is pi, adjust your angle() function so that it returns a result between 0 and pi. so your tortuosity would be at most n*pi, hence the above scaling factor which allows to have a value between 0 and 1 with 0 representing a perfectly straight polyline)

How to find the two opposite normals or two segments?

I have a two segments AB and CD (in red). These two segments are facing each others. They are not completely parallel but will never be perpendicular to each others either.
From that, I need to find the two normals of these segments (in blue) that oppose each others (i.e. the two normals are outside ABCD). I know how to calculate the normals of the segments but obviously each segment has two normals, and I cannot figure out how to programmatically select the ones I need. Any suggestion?
Calculate the vector v between the midpoints of the two segments, pointing from AB to CD. Now the projection of the desired normal to AB onto v must be negative and the projection of the desired normal to CD onto v must be positive. So just calculate the normals, check against v, and negate the normals if needed to make them satisfy the condition.
Here it is in Python:
# use complex numbers to define minimal 2d vector datatype
def vec2d(x,y): return complex(x,y)
def rot90(v): return 1j * v
def inner_prod(u, v): return (u * v.conjugate()).real
def outward_normals(a, b, c, d):
n1 = rot90(b - a)
n2 = rot90(d - c)
mid = (c + d - a - b) / 2
if inner_prod(n1, mid) > 0:
n1 = -n1
if inner_prod(n2, mid) < 0:
n2 = -n2
return n1, n2
Note that I assume the endpoints define lines meeting the conditions in the problem. Nor do I check for the edge case when the lines have the same midpoint; the notion of "outside" doesn't apply in that case.
I think there are two cases to consider:
Case 1: Intersection between lines occurs outside the endpoints of either segment.
In this case the midpoint method suggested by #Michael J. Barber will work for sure. So form a vector between the midpoints of the segments, compute the dot product of your normal vectors with this midpoint vector and check the sign.
If you're computing the normal for lineA, the dot product of the normal with the vector midB -> midA should be +ve.
Case 2: Intersection between lines occurs inside the endpoints of one segment.
In this case form a vector between either one of the endpoints of the segment that does not enclose the intersection point and the intersection point itself.
The dot product of the normal for the segment that does enclose the intersection point and this new vector should be +ve.
You can find the outward normal for the other segment by requiring that the dot product between the two normals is -ve (which would only be ambiguous in the case of perpendicular segments).
I've assumed that the segments are not co-linear or actually intersecting.
Hope this helps.
You can reduce the four combinations for the signs as follows:
Calculate the dot product of the normals, a negative sign indicates that both show outside or inside.
As I suppose that your normals have unit lenght, you can detect parallelity if the dot product has magnitude one. A positive value indicates that both show in the same direction, a negative value says that both show in different directions.
It the normals are not parallel: parametrize lines as x(t) = x0 + t * n for a normal n and calculate the t for which both intersect. A negative t will indicate that both show outside. It is enough if you do this for one of the normals, as you reduced your combinations from 4 to 2 in step 1.
If both normals are parralel: Calculate the time t for which the normals hit the midpoint between of your segments. As in 2. is enough if you do this for one of the normals, as you reduced your combinations from 4 to 2 in step 1.

3D Trilateration using given distances of unknown fixed points

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.

Resources