This page explains and demonstrates the calculation of the intersection of two-dimensional lines using Vector analysis and the parametric form of vectors. Also the perp dot product is used in the calculation.
Following buttions can be used to load predefined line positions for the different cases:
This example application demonstrates the described algorithm for line intersection. The four red points defining the two lines can be freely dragged using the left mouse button to change their positions. The calculated result is updated automatically.
There are two lines specified by four points:
The infinite line g_{A} is defined by the points A_{0} and A_{1}. The line segment between A_{0} and A_{1} is called seg_{A} and its vector is further noted as a.
The same applies accordingly to B_{0}, B_{1}, g_{B} and seg_{B} and b.
This can be formally written as following, introducing also vector notation:
Both lines and line segments can have one of the following relations:
If both lines are parallel, then also a and b have the same or opposite direction and thus are linearly dependent.
To check this case the perp dot product can be used: In this case, the perpendicular vector a^{⊥} to a must be also perpendicular to b. In other words, the perp dot product of a^{⊥} and b is zero.
In short: Lines are parallel if perpDot(a, b) = 0.
If both lines are parallel, they could either be true parallel meaning they do never intersect or they are coincident meaning they lie on each other and are in fact the same line.
To check if both lines are the same, one point can be set into the equation of the other line to test if it lies also on the other line.
So e.g. we could set B_{0} into the line g_{A}, that is B_{0} = A_{0} + s * a for some s.
Now let's define a vector u as u = B_{0} - A_{0}. If both lines are coincident, A_{0} and B_{0} lie on the same line, meaning that u = s * a for some s.
In other words, u is linearly dependent to a, thus u^{⊥} must be also perpendicular to a, that is the perp dot product of u and a is zero.
In short: Lines are coincide if perpDot(a, u) = 0. Otherwise they are true parallel.
However, if line segments are considered (and not infinite lines), then coincidence can still means two cases: Either the line segments overlap or they do not overlap.
To distinigush both cases, solve the line equation of onbe line for the end points of the other line segment and check if both parameters are in range [0, 1].
This can be done in following way:
Put B_{0} in g_{A}, so solve B_{0} = A_{0} + s(B_{0}) * a. This gives s(B_{0}) = a / (B_{0} - A_{0}).
If s(B_{0}) is in range [0, 1], then B_{0} lies on the line segment between A_{0} and A_{1}, else not.
Repeat the same steps for B_{1}, resulting in s(B_{1}) = a / (B_{1} - A_{0}). If s(B_{1}) is in range [0, 1], then B_{1} lies on the line segment between A_{0} and A_{1}, else not.
In total, this means that both line segments partly overlap if either s(B_{0}) is in range [0, 1] or s(B_{1}) is in range [0, 1].
Both line segments totally overlap, so one line segment is completely contained by other line segments if s(B_{0}) and s(B_{1}) are in range [0, 1].
Both line segments are coincide but have no overlap at all, if neither s(B_{0}) nor s(B_{1}) are in range [0, 1].
If both lines are not parallel, then there exists exactly one intersection point.
To calculate the intersection point, we need to find the point at which both line equations are equal: g_{A}(s) = g_{B}(t). This means we need to calculate either s or t.
Let's have a closer look:
g_{A}(s) = g_{B}(t) ---> A_{0} + s * a = B_{0} + t * a
Lets's solve it for s. Therefore first isolate the s term:
s * a = (B_{0} - A_{0}) + t * a
Now comes a trick: Multiply both sides with b^{⊥}. Because b * b^{⊥} is 0, this eliminates t:
s * b^{⊥} * a = b^{⊥} * (B_{0} - A_{0}) + t * b^{⊥} * a
-> s * b^{⊥} * a = b^{⊥} * (B_{0} - A_{0})
-> s = ( b^{⊥} * (B_{0} - A_{0} ) / ( b^{⊥} * a )
Defining vector B_{0} - A_{0} as u, this is the same as s = perpDot(b, u) / perpDot(b, a)
The actual intersection point is then calculated as p = A_{0} + s * a.
Note that we have chosen s arbitrarily - we could have also chosen t to solve for:
A_{0} + s * a = B_{0} + t * a
-> (A_{0} - B_{0}) + s * a = t * a.
Now multiply both sides with a^{⊥}:
-> a^{⊥} * (A_{0} - B_{0}) + s * a^{⊥} * a = t * a^{⊥} * a
-> a^{⊥} * (A_{0} - B_{0}) = t * a^{⊥} * a
-> t = (a^{⊥} * (A_{0} - B_{0})) / (a^{⊥} * a)
Defining vector A_{0} - B_{0} as u, this is the same as t = perpDot(a, u) / perpDot(a, b)
The actual intersection point is then calculated as p = B_{0} + t * b.
To distinguish the three cases if the intersection point is on both line segments, one line segment or not at all on any of the two lines segments (but on the infinite lines), again the calculated values for s and t need to be evaluated:
If s is in range [0, 1] AND t is in range [0, 1], then the intersection point lies inside both line segments.
If s is in range [0, 1] OR t is in range [0, 1], then the intersection point lies on one line segment. If s is in range [0, 1], then it's on line segment seg_{A}, else it's on seg_{B}.
If neither s is in range [0, 1] nor t is in range [0, 1], the intersection point does not lie on any of both line segments.
Hope you liked it!
Sunshine2k, December 2k19
2019/12/17: Initial release.