Advertisement

intersection of two lines

Started by December 25, 2014 08:48 AM
5 comments, last by BornToCode 10 years, 1 month ago

Hello everyone,

I found this code online that determines if two lines intersect and it also calculate the point of intersection. I have been trying to understand how it works but for the life of me I can't.

It works perfectly. but I can't understand how it works. Can someone please try and explain it?

Code is C# based


bool lines_intersect_2d(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) 
{
    //The point of intersection if found
    Vector3 i = Vector3.Zero;

    Vector3 s1 = p1 - p0;
    Vector3 s2 = p3 - p2;

    Vector3 u = p0 - p2;

    float ip = 1f / (-s2.X * s1.Y + s1.X * s2.Y);

    float s = (-s1.Y * u.X + s1.X * u.Y) * ip;
    float t = ( s2.X * u.Y - s2.Y * u.X) * ip;

    if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
        if (i == Vector3.Zero) 
            i = p0 + (s1 * t);
        return true;
    }

    return false;
}

Thank you

Is this a line in 2D or 3D?

Update: just noticed it says 2D in the function name
Advertisement

Is this a line in 2D or 3D?

its 2D. but the guy who wrote this code is using Vector3 for some reason.

I think the best way to just use the Point class in XNA or even Vector2.

Consider all points on a lined defined as s+t*v, where s is a single point on the line, v is the direction of the line, and t is a parameter that produces points along the line. In your code, where you have two points, you can just define s=p0 and v=p1-p0. If t=0, then p=p0; if t=1, then p=p1, and so on.

You want to find the intersection point between two line segments, which is a point common to two line segments. Thus, you have the two lines

  • s0 + t0 * v0, where s0 = p0 and v0 = p1-p0 from your code, and
  • s1 + t1 * v1, where s0 = p2 and v0 = p3-p2 from your code.

Find a common point along the two lines by solving for t0 and/or t1 from

  • ?s0 + t0 * v0 = s1 + t1 * v1

This is a normal linear equation system, so rearrange and reformulate the problem on matrix form.

  • t0 * v0 - t1 * v1 = s1 - s0
  • [v0, -v1] * [t0, t1]T = s1 - s0

Note that I assume column vectors here, and that the V-matrix is a 2-by-2 matrix where the two vectors v0 and v1 are the columns of the V-matrix. Finally, solve for t0 and t1.

  • [t0, t1]T = [v0, -v1]-1 * (s1 - s0)

When you have t0 and t1, just plug any of them back into the corresponding lines to find the intersection point. Both of them will produce the same point.

Now that we have the theory, you can identify the maths with the code:

  • My direction vectors v0 and v1 corresponds to your s1 and s2.
  • My (s1 - s0) corresponds to your u, although there is a sign difference here that will be cancelled later, so no worries.
  • Your ip is the determinant of my [v0, -v1]-1.
  • Your s and t are the x and y coordinates of the multiplication of my V-matrix and (s1 - s0).
  • Your i being assigned inside the if-statements is when you plug one of the t's into its corresponding line equation to produce the intersection point.
  • The first if-statement checks if the resulting points are outside of the two line segments bounded by the two points. That happens when t<0 or when t>1. Remove that if-statement if you want the lines to extend indefinitely.

The theory above to find the intersection point is equally valid for 3-dimensional lines as well. It will, however, find the points along the two lines that are closest to each other, and you need to find some other method to invert the V-matrix since it's no longer square; for example, the pseudo-inverse.

[...] but I can't understand how it works. Can someone please try and explain it?

The method is this: There a re 2 line segments p0p1 and p2p3 given. They can be expressed by using a ray equation (i.e. directed line) when the independent variable of the ray is restricted. In this case

r01( s ) := p0 + s * ( p1 - p0 ) w/ 0 <= s <= 1

r23( t ) := p2 + t * ( p3 - p2 ) w/ 0 <= t <= 1

(maybe in the OP s and t are exchanged; I'm too lazy to actually compute the result).
For the firt computation steps, you ignore the restriction, and ask for where the both rays are equal
r01( s ) = r23( t )
If you solve this for s and t (it is a linear system with 2 unknowns and 2 equations in 2D), you finally have to check whether both s and t fall in the originally defined restriction.
It works perfectly. [...]
No, it does not, at least not on general: It breaks if the 2 lines are parallel / anti-parallel! In that case you'll get a division by zero when computing the value of ip.

In view of haegarr's post, your algorithm tries to solve the following vector equation

p0 + t*(p1-p0) = p2+s*(p3-p2)

for t and s.

Roughly speaking, the left side of this equation forms a line passing through the points p0 and p1 as independent variable t changes. In particular, for 0 <= t <= 1, it forms a section (line segment) between p0 and p1. Similarly, the right side is a line passing through the points p2 and p3 as s changes and forms a section between p2 and p3 for 0 <= s <= 1. Thus the solution of this equation should give the intersection point of these two lines.

More precisely, the algorithm solves transformed version of the above equation of the form

s*s2 - t*s1 = u,

i.e. the linear system of equations

s2.X*s - s1.X*t = u.X

s2.Y*s - s1.Y*t = u.Y,

by using Cramer's rule.

It should by mentioned, that the algorithm your presented gives only the intersection point of sections p0p1 and p2p3, not of the whole lines, since variables t and s are checked to be inside the interval [0,1]. Moreover, it does not work for "non-properly" intersecting lines.

Dietary supplements (suplementy diety)

Advertisement
Another solution is to project the point into the line normal. Then you can check and see if that point lies withing the bounds of the line.

This topic is closed to new replies.

Advertisement