Unity3D.tips[2]: Intersection point between two lines in 2D

The code

/// 
/// Gets the coordinates of the intersection point of two lines.
/// 
/// A point on the first line.
/// Another point on the first line.
/// A point on the second line.
/// Another point on the second line.
/// Is set to false of there are no solution. true otherwise.
/// The intersection point coordinates. Returns Vector2.zero if there is no solution.
public Vector2 GetIntersectionPointCoordinates(Vector2 A1, Vector2 A2, Vector2 B1, Vector2 B2, out bool found)
{
    float tmp = (B2.x - B1.x) * (A2.y - A1.y) - (B2.y - B1.y) * (A2.x - A1.x);

    if (tmp == 0)
    {
        // No solution!
        found = false;
        return Vector2.zero;
    }

    float mu = ((A1.x - B1.x) * (A2.y - A1.y) - (A1.y - B1.y) * (A2.x - A1.x)) / tmp;

    found = true;

    return new Vector2(
        B1.x + (B2.x - B1.x) * mu,
        B1.y + (B2.y - B1.y) * mu
    );
}

The maths behind

To get the point where two lines intersect, we will do some maths. To the mathematicians who will come across this post, I’m truly sorry for the heart attacks or strokes you may experience by reading this post.

Ok, let’s take a look on the figure:

Study case. We can see two lines crossing in an 2D Euclidian space.
Figure 1

First, sorry, I was too lazy to make a proper figure using computer tools so I just put a scan. XD

Next, here are the definitions:

  • A & B: the two lines,
  • A_1, B_1: the arbitrary starting points of the two lines,
  • A_2, B_2: the arbitrary points which tells the direction of the two lines,
  • X: the intersection point,
  • O: the origin point.

Kewl. Now, what we want is the intersection point X between those two lines. In other words, we want to know the position which starts from either lines’ arbitrary starting point, added by the direction of the line multiplied by a scalar value. So in our figure 1, the X position is:

  • the A_1 position added by the components of \overrightarrow{A_1A_2} multiplied by an unknown which I named \lambda
  • the B_1 position added by the components of \overrightarrow{B_1B_2} multiplied by an unknown which I named \mu

In this case, it is clear that \lambda = \mu = 0.5 so it will be easy to check if our final formula is correct. 🙂

At the point of intersection, we know that:
\begin{array}{rcl} \overrightarrow{OX} = \overrightarrow{OA_1} + \lambda\times\overrightarrow{A_1A_2} & and & \overrightarrow{OX} = \overrightarrow{OB_1} + \mu\times\overrightarrow{B_1B_2} \end{array}

… which gives us:
\begin{array}{rcl} \overrightarrow{OA_1} + \lambda\times\overrightarrow{A_1A_2} & = & \overrightarrow{OB_1} + \mu\times\overrightarrow{B_1B_2} \\ \overrightarrow{OA_1} - \overrightarrow{OB_1} & = & \mu\times\overrightarrow{B_1B_2} - \lambda\times\overrightarrow{A_1A_2} \end{array}

But we can’t use this statement exactly like this to solve our equation as we cannot multiply and divide vectors in this raw format. Also we need to reduce the unkowns count to 1. So we will separate our equation into two equations with the magic of matrices (which I don’t understand well at the moment), one for the x component and one for the y:
\left\{\begin{array}{c}  \overrightarrow{OA_1}_x - \overrightarrow{OB_1}_x = \mu\times\overrightarrow{B_1B_2}_x - \lambda\times\overrightarrow{A_1A_2}_x \\   \overrightarrow{OA_1}_y - \overrightarrow{OB_1}_y = \mu\times\overrightarrow{B_1B_2}_y - \lambda\times\overrightarrow{A_1A_2}_y  \end{array}\right.

To make our equation more readable, we will use some shorthands:
\begin{array}{r}A_\alpha = \overrightarrow{A_1A_2}\end{array}\\  \begin{array}{r}B_\alpha = \overrightarrow{B_1B_2}\end{array}\\  \begin{array}{r}C = \overrightarrow{OA_1} - \overrightarrow{OB_1}\end{array}

… so:
\left\{\begin{array}{c}  C_x = \mu B_{\alpha x} - \lambda A_{\alpha x} \\   C_y = \mu B_{\alpha y} - \lambda A_{\alpha y}  \end{array}\right.

From this point, we can reduce the unknown count. In my case, I have chosen to keep \mu instead of \lambda:
\left\{\begin{array}{c}  C_x A_{\alpha y} = \mu B_{\alpha x} A_{\alpha y} - \lambda A_{\alpha x} A_{\alpha y} \\   C_y A_{\alpha x} = \mu B_{\alpha y} A_{\alpha x} - \lambda A_{\alpha y} A_{\alpha x}  \end{array}\right.\\  \begin{array}{rcl}  C_x A_{\alpha y} - C_y A_{\alpha x} & = & \mu B_{\alpha x} A_{\alpha y} - \lambda A_{\alpha x} A_{\alpha y} - (\mu B_{\alpha y} A_{\alpha x} - \lambda A_{\alpha y} A_{\alpha x}) \\  C_x A_{\alpha y} - C_y A_{\alpha x} & = & \mu B_{\alpha x} A_{\alpha y} - \lambda A_{\alpha x} A_{\alpha y} - \mu B_{\alpha y} A_{\alpha x} + \lambda A_{\alpha y} A_{\alpha x} \\  C_x A_{\alpha y} - C_y A_{\alpha x} & = & \mu B_{\alpha x} A_{\alpha y} - \mu B_{\alpha y} A_{\alpha x} \\  C_x A_{\alpha y} - C_y A_{\alpha x} & = & \mu (B_{\alpha x} A_{\alpha y} - B_{\alpha y} A_{\alpha x}) \\  \mu & = & \frac{C_x A_{\alpha y} - C_y A_{\alpha x}}{B_{\alpha x} A_{\alpha y} - B_{\alpha y} A_{\alpha x}}  \end{array}

And finally, you have to check if B_{\alpha x} A_{\alpha y} - B_{\alpha y} A_{\alpha x} = 0. This will happen if your two lines are parallel or if there is one line defined as a point such as A_1 = A_2 or B_1 = B_2; no solution exists in those cases.

Test 1

Kewl! Now let’s try it with the Figure 1:
\begin{array}{rcl}  \mu & = & \frac{(1 - 1) \times 1 - (2 - 4) \times 2}{2 \times 1 - (-3) \times 2} \\  \mu & = & \frac{4}{8} = 0.5  \end{array}

We can get the X position:
\left\{\begin{array}{l}  \overrightarrow{OX}_x = \overrightarrow{OB_1}_x + B_{\alpha x} \times \mu = 1 + 2 \times 0.5 = 2 \\  \overrightarrow{OX}_y = \overrightarrow{OB_1}_y + B_{\alpha y} \times \mu = 4 + (-3) \times 0.5 = 2.5  \end{array}\right.

Test 2

Ok done! Now let’s try with another figure:

Study case 2. We can see two lines crossing in an 2D Euclidian space.
Figure 2

\begin{array}{rcl}  \mu & = & \frac{((-2) - 2) \times (-1) - ((-2) - (-3)) \times 0}{(-1.5) \times (-1) - 1.5 \times 0} \\  \mu & = & \frac{4}{1.5} \approx 2.666  \end{array}

We can get the X position:
\left\{\begin{array}{l}  \overrightarrow{OX}_x = \overrightarrow{OB_1}_x + B_{\alpha x} \times \mu = 2 + (-1.5) \times 2.666 = -2 \\  \overrightarrow{OX}_y = \overrightarrow{OB_1}_y + B_{\alpha y} \times \mu = (-3) + 1.5 \times 2.666 = 1  \end{array}\right.

Published by Dakwamine

Dakwamine, alias Quang-Minh Dang, né en 1987 en région parisienne. Un type sympa, pas bavard et pragmatique.

2 replies on “Unity3D.tips[2]: Intersection point between two lines in 2D”

  1. Nice explanation. Thanks for the blog, i was scratching my head for a while before reading the blog.

Comments are closed.