Determine where the lines defined by two segments intersect in C#

This example determines whether two segments intersect and where the lines that contain them intersect. There are several ways you can approach this problem. This example uses lines defined by parametric equations where 0 <= t1, t2 <= 1:

    X1(t) = x11 + dx1 * t1
Y1(t) = y11 + dy1 * t1
X2(t) = x21 + dx2 * t2
Y2(t) = y21 + dy2 * t2

Setting these equal gives:

    x11 + dx1 * t1 = x21 + dx2 * t2
y11 + dy1 * t1 = y21 + dy2 * t2

Rearranging:

    x11 - x21 + dx1 * t1 = dx2 * t2
y11 - y21 + dy1 * t1 = dy2 * t2
    (x11 - x21 + dx1 * t1) *   dy2  = dx2 * t2 *   dy2
(y11 - y21 + dy1 * t1) * (-dx2) = dy2 * t2 * (-dx2)

Adding the equations gives:

    (x11 - x21) * dy2 + ( dx1 * dy2) * t1 +
(y21 - y11) * dx2 + (-dy1 * dx2) * t1 = 0

Solving for t1 gives:

    t1 * (dy1 * dx2 - dx1 * dy2) =
(x11 - x21) * dy2 + (y21 - y11) * dx2
    t1 = ((x11 - x21) * dy2 + (y21 - y11) * dx2) /
(dy1 * dx2 - dx1 * dy2)

Similarly solve for t2.

Notes:

  • If 0 <= t1 <= 1, then the point lies on segment 1.
  • If 0 <= t2 <= 1, then the point lies on segment 1.
  • If dy1 * dx2 - dx1 * dy2 = 0 then the lines are parallel.
  • If the point of intersection is not on both segments, then this is almost certainly not the point where the two segments are closest.

The FindIntersection method shown in the following code finds the intersection between the lines that contain the segments p1 --> p2 and p3 --> p4.

// Find the point of intersection between
// the lines p1 --> p2 and p3 --> p4.
private void FindIntersection(PointF p1, PointF p2, PointF p3, PointF p4,
out bool lines_intersect, out bool segments_intersect,
out PointF intersection, out PointF close_p1, out PointF close_p2)
{
// Get the segments' parameters.
float dx12 = p2.X - p1.X;
float dy12 = p2.Y - p1.Y;
float dx34 = p4.X - p3.X;
float dy34 = p4.Y - p3.Y;

// Solve for t1 and t2
float denominator = (dy12 * dx34 - dx12 * dy34);

float t1;
try
{
t1 = ((p1.X - p3.X) * dy34 + (p3.Y - p1.Y) * dx34) / denominator;
}
catch
{
// The lines are parallel (or close enough to it).
lines_intersect = false;
segments_intersect = false;
intersection = new PointF(float.NaN, float.NaN);
close_p1 = new PointF(float.NaN, float.NaN);
close_p2 = new PointF(float.NaN, float.NaN);
return;
}
lines_intersect = true;

float t2 = ((p3.X - p1.X) * dy12 + (p1.Y - p3.Y) * dx12) / -denominator;

// Find the point of intersection.
intersection = new PointF(p1.X + dx12 * t1, p1.Y + dy12 * t1);

// The segments intersect if t1 and t2 are between 0 and 1.
segments_intersect = ((t1 >= 0) && (t1 <= 1) && (t2 >= 0) && (t2 <= 1));

// Find the closest points on the segments.
if (t1 < 0)
{
t1 = 0;
}
else if (t1 > 1)
{
t1 = 1;
}

if (t2 < 0)
{
t2 = 0;
}
else if (t2 > 1)
{
t2 = 1;
}

close_p1 = new PointF(p1.X + dx12 * t1, p1.Y + dy12 * t1);
close_p2 = new PointF(p3.X + dx34 * t2, p3.Y + dy34 * t2);
}

   

 

What did you think of this article?




Trackbacks
  • No trackbacks exist for this post.
Comments
  • No comments exist for this post.
Leave a comment

Submitted comments are subject to moderation before being displayed.

 Name

 Email (will not be published)

 Website

Your comment is 0 characters limited to 3000 characters.