Tips

 
  home
     

Projects

Products

Coding Corner
  Components
  Tips

Contact Us

Design Background

Curriculum Vitae

Forum

Links

 

 

Tip #1: Minimum distance between a point and a line
Added: 15Nov2002
Author: Nils Haeck
Category: Geometry

Question:
How can I calculate the distance between a point and a line?

Applicable:
You can use this code when you need to detect whether the mouse click of the user is near or on a line segment or not, like in GetHitTestInfo events.

Answer:
We'll use some optimisation theory: the minimum distance between the point and the line (which can be expressed as a function) will be at the exact location where the derivative of this function is zero.
Perhaps you remember this from school; the minimum or maximum in a parabola is where its gradient is zero.

  • We parametrise the distance of point P to the line between A and B as the distance of point P to a point Q on the line:

    point Q = (1-q)A+qB where 0 <= q <= 1

  • The distance PQ is:

    |PQ| = sqrt( ((1-q)Ax + qBx - Px)^2 + (... Y term) )

  • Differentiating gives dPQ/dq = 2((Bx-Ax)q + (Ax-Px))(Bx - Ax) + (... Y term).

  • dPQ/dq must be zero for minimum so:

    q = (Px-Ax)(Bx-Ax)+(Py-Ay)(By-Ay) / ((Bx-Ax)^2+(By-Ay)^2)

Code Sample:
Note that this code also takes into account situations where your line is actually not a line (A=B) and situations where the point P is past any of the two endpoints. In this case, the distance to the closest endpoint is calculated.


// MinDistPointLine calculates the minimum distance of a point to a line.
// P is the point, the line is between points A and B.
function MinDistPointLine(Px, Py, Ax, Ay, Bx, By: double): double;

implementation

function PointToPointDist(Ax, Ay, Bx, By: double): double;
begin
  Result := sqrt(sqr(Bx-Ax) + sqr(By-Ay));
end;

function MinDistPointLine(Px, Py, Ax, Ay, Bx, By: double): double;
var
  q: double;
begin
  if (Ax=Bx) and (Ay=By) then begin

    // Point to point
    Result := PointToPointDist(Px, Py, Ax, Ay);

  end else begin

    // Minimum
    q := ((Px-Ax)*(Bx-Ax) + (Py-Ay)*(By-Ay)) / (sqr(Bx-Ax) + sqr(By-Ay));

    // Limit q to 0 <= q <= 1
    if q < 0 then q := 0;
    if q > 1 then q := 1;

    // Distance
    Result := PointToPointDist(Px, Py, (1-q)*Ax + q*Bx, (1-q)*Ay + q*By);

  end;
end;

   Page last changed: 05Nov2006 © Copyright 2002-2005 SimDesign