Hi Mark,

What you need to do is build in some tolerance when checking where the user

clicks. In other words, you need to find out how far the click is from a

line, and if this is within the desired tolerance, you will accept it as a

click on the line.

There is two situations

1) Polylines with straight line segments

2) Polylines with curved segments, aka Bezier curves (Polybezier).

For 1) I have a solution for you directly. I wrote this algorithm for a

project quite some time ago and up till now I have never encountered

anywhere a faster method. See code below.

For 2) I want you to have a look at this example (posted on my website). An

executable, but certified virus free :)

http://www.abc-view.com/downloads/bezier.exe

It shows how you can approximate a user-drawn line, with a certain

tolerance. As a part of it, there's code that will detect how far a certain

point (click) is from the bezier curve. I can't give you the source to this

example for free though. Contact me if you're interested. It could fit well

into your map drawing.

Nils Haeck

http://www.abc-view.com/

This is the code for finding a point closest to a line segment. Run it for

each of the segments in your polyline

{

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;

##### Quote

Mark Lauter <marklau...@hotmail.com> wrote in message

news:3cfd2034$1_2@dnews...

##### Quote

> I want to create a polyline that I can interact with a mouse. I've

> considered a few ways to do this and I have run into a wall. The problem

is

> the rectangular nature of TControl. Let's say I have a layer containing

> lines superimposed over a layer of squares. If a line object in the top

> layer is clicked someplace in the rectangle of the line component, but

isn't

> actually on the line, a square component visible but below the line's

> rectangle doesn't receive the click. But what I want to happen is for the

> line component to actually be the line itself not the encompassing

> rectangle. So a click that misses the actual line would just pass through

> to the next control in the z order.

> To help you understand my exact problem I'll provide a little background.

> I'm working on a program that creates a vector based navigation chart

(like

> a road map) and I want to draw interactive course lines. The chart would

> contain other interactive objects, such as ship wreck or reef locations.

> One way I've thought to solve this problem is to create a line layer that

> actually handles all click events (loops the line list looking for click

> matches) and then passes the click off to the next layer in the z order.

> Each layer would check for objects that match the click event and until a

> match was found the event could just be passed down the layer stack. The

> problem with this is that there could potentially be hundreds of

interactive

> objects visible on each layer.

> Any ideas would be greatly appreciated.

> --

> Mark Lauter

> Irreverence is the champion of liberty and its only sure defense.

> - Mark Twain