Find the shortest distance between a point and a line segment in C#

distance between a point and a line segment

This example treats the segment as parameterized vector where the parameter t varies from 0 to 1. It finds the value of t that minimizes the distance from the point to the line.

If t is between 0.0 and 1.0, then the point on the segment that is closest to the other point lies on the segment. Otherwise the closest point is one of the segment’s end points. The program finds this closest point and calculates the distance between it and the target point.

The following code shows how the program finds the distance between the point pt and the segment p1 --> p2.

// Calculate the distance between
// point pt and the segment p1 --> p2.
private double FindDistanceToSegment(
    PointF pt, PointF p1, PointF p2, out PointF closest)
{
    float dx = p2.X - p1.X;
    float dy = p2.Y - p1.Y;
    if ((dx == 0) && (dy == 0))
    {
        // It's a point not a line segment.
        closest = p1;
        dx = pt.X - p1.X;
        dy = pt.Y - p1.Y;
        return Math.Sqrt(dx * dx + dy * dy);
    }

    // Calculate the t that minimizes the distance.
    float t = ((pt.X - p1.X) * dx + (pt.Y - p1.Y) * dy) /
        (dx * dx + dy * dy);

    // See if this represents one of the segment's
    // end points or a point in the middle.
    if (t < 0)
    {
        closest = new PointF(p1.X, p1.Y);
        dx = pt.X - p1.X;
        dy = pt.Y - p1.Y;
    }
    else if (t > 1)
    {
        closest = new PointF(p2.X, p2.Y);
        dx = pt.X - p2.X;
        dy = pt.Y - p2.Y;
    }
    else
    {
        closest = new PointF(p1.X + t * dx, p1.Y + t * dy);
        dx = pt.X - closest.X;
        dy = pt.Y - closest.Y;
    }

    return Math.Sqrt(dx * dx + dy * dy);
}

The least obvious part of this code is the following statement.

// Calculate the t that minimizes the distance.
float t = ((pt.X - p1.X) * dx + (pt.Y - p1.Y) * dy) /
    (dx * dx + dy * dy);

So where does this formula come from?

To find the shortest distance between that point and the line segment, you need to know some relatively easy calculus and one clever fact. The clever fact is that if T minimizes an equation, then T2 minimizes the equation squared. In this example that means we can minimize the distance squared between the point and the line segment, and then the value t that we find will also minimize the non-squared distance.

A point on the line segment has coordinates X = Pt1.X + t*dx, Y = Pt1.Y + t*dy.

The distance squared between that point and the point P is:

[Pt.X - (Pt1.X + t*dx)]2 + [Pt.Y - (Pt1.Y + t*dy)]2

Taking the derivative with respect to t gives:

2*[Pt.X - (Pt1.X + t*dx)]*dx + 2*[Pt.Y - (Pt1.Y + t*dy)]*dy

To find the minimum, we set this equal to 0 and solve for t.

2*[Pt.X - (Pt1.X + t*dx)]*dx + 2*[Pt.Y - (Pt1.Y + t*dy)]*dy = 0

Now if you divide both sides by 2 and then combine the t terms you get:

-t*(dx2 + dy2) + dx*(Pt.X - Pt1.X) + dy*(Pt.Y - Pt1.Y) = 0

Subtracting the t term from both sides of the equation gives:

dx*(Pt.X - Pt1.X) + dy*(Pt.Y - Pt1.Y) = t*(dx2 + dy2)

Now you can divide both sides by (dx2 + dy2) to get:

t = [dx*(Pt.X - Pt1.X) + dy*(Pt.Y - Pt1.Y)] / (dx2 + dy2)

That’s the equation used in the code.


Download Example   Follow me on Twitter   RSS feed




This entry was posted in algorithms, geometry, graphics, mathematics and tagged , , , , , , , , , , , , , , . Bookmark the permalink.

21 Responses to Find the shortest distance between a point and a line segment in C#

  1. Zeke says:

    Thank you! This worked great for me. 🙂

  2. Jocke says:

    Thank you!

    Finally a function that works for line segments and not just for infinite lines.

  3. Pingback: Find the shortest distance between two line segments in C# -

  4. Pingback: Draw and move line segments in C# -

  5. Steven says:

    THX BRO!!!

  6. Pingback: Make a WPF line editor C# - C# HelperC# Helper

  7. Michael Withers says:

    I have been getting some strange results when using this method is minus numbers typically less and 1. Does any one know if this method should also work correctly for

    a)Negative numbers x / y input
    b) when x / y could be less than 1.

    Also is there a name for the theory / method this code is derived from. I really want to use this method as its alot faster than the alternatives!

    • RodStephens says:

      It seems to work for me. Can you give me some example coordinates where it doesn’t seem to work?

      I don’t know if this method has a name. I derived it a long time ago. If you use it in your code, you might include a link to the page so you can find it later if you need to.

  8. Tegar says:

    Thank you!

  9. can you just give the code in my sql

    • RodStephens says:

      I don’t think MySQL (or any database tool) has any code to do this. You would need to write some code to get the segments’ end points and perform the calculation.

  10. Jim says:

    Been years since I’ve had to look at Algebra so probably a silly question, P1 and P2 does it matter which point on the line segment is which (i.e. most left needs to be P1) or does it make no difference?
    Thx

    • RodStephens says:

      This isn’t a silly question at all. The short answer is, no it doesn’t matter.

      The value t tells you how far you go from point A to point B. If you switch them around, then t tells you how far you go from B to A, but you get the same point either way.

      The reason why this isn’t a silly question is that this method uses vector arithmetic and the parameter t to make sure it doesn’t matter which order you use. If you try to solve equations like y = mx + b, you run into special cases for things like a vertical line (where the slope m is infinite). This technique lets you handle all cases the same way whether the line is vertical, horizontal, or you swap the order of the points.

  11. Dado says:

    How can i call this function?

  12. Joseph Enriquez says:

    Good day sir!

    I’m a student studying C# for my programming subject. I tried replicating this program to function on a Picturebox object in VS2013 but it doesn’t work. I’m currently comparing the code of the two programs, your original version and my modified version and to my rookie eyes, I couldn’t find a difference. I think I’m missing something to allow this program to work inside the Picturebox.

    • RodStephens says:

      Did you download the example? Or just copy and paste the code into your program? The example has more code that’s not shown here to hook up the PictureBox to event handlers that let you pick the segment and point.

  13. Frederic Faulkner says:

    “float t = ((pt.X – p1.X) * dx + (pt.Y – p1.Y) * dy) /
    (dx * dx + dy * dy);”

    Can you explain where this formula comes from? I’ve been racking my brain this morning but it’s been too long since I took Linear Algebra or Calc 3. I understand the concept of a parametric equation, just not why the above formula produces the t that minimizes distance. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *