|
Projects
Products
Coding Corner
Components
Tips
Contact
Us
Design
Background
Curriculum
Vitae
Forum
Links
|
|
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;
|