2005. augusztus 26., péntek

Check if the mouse pointer is over or close to a line on a TCanvas


Problem/Question/Abstract:

I am painting a line on a canvas with LineTo. How can I determine if the mouse pointer is over that line or not.

Answer:

This will give you the distance to the line and you can decide in your code how close (in pixels) you want the user to be to the line before selecting it. It takes into account the end points as well, so when the user is past the end points on the extension of the line it is not triggered.

MinDistPointLine calculates the minimum distance of a point to a line. P is the point, the line is between points A and B. It is based on the distance of P to the parametrised point Q = (1 - q) A + qB where 0 <= q <= 1. The distance PQ is 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)

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;

Nincsenek megjegyzések:

Megjegyzés küldése