PDA

View Full Version : How simply check if mouse cursor is over specific point[i] and over of any ofpoints ?



JC_
31-08-2013, 01:04 PM
There is a better solution to this simple problem? In array of points i will check if is mouse over one specific point[i] and if is on any of points.

after a long time.. :) i found this:



Type
TPoint2D = record
X, Y : Single; // position
mouseover : boolean; // mouse over specific point
Rect : TRect; // mouse vs point
end;

Var
Point : array of TPoint2D;
Count : integer;

selectedPointID : integer;
TrueCount, FalseCount : integer;

moveWithPoint : boolean;
..

Begin

trueCount := 0;
falseCount := 0;

for i := 0 to Count-1 do begin

// mouse over one specific point
if col2d_PointInRect( mousecur.x, mousecur.y, point[i].PointRect ) then
point[i].mouseover := true else point[i].mouseover := false;

// Mouseover
if Point[i].mouseover then begin
inc(trueCount);
if not moveWithPoint then selectedPointID := i + 1; // i can select only one point
end else
inc(falseCount);

// is any point selected ?
if falseCount = shape.count then
begin
selectedPointID := 0; // none
..
end;

// mouse button interaction, move with point
if mouse_Down( 0 ) and (selectedPointID > 0) then begin
moveWithPoint := true;
point[selectedPointID - 1].x := mousecur.x;
point[selectedPointID - 1].y := mousecur.y;
point[selectedPointID - 1].Rect.x := mousecur.x - 5;
point[selectedPointID - 1].Rect.y := mousecur.y - 5;
end;

if not mouse_Down( 0 ) then moveWithPoint := false;

User137
31-08-2013, 01:31 PM
Point is a point, not rectangle :) Every point usually has same size, it is only necessary to save X and Y.

I'm usually using my one and only solution to point picking, that is distance comparison. Think of a situation where 3 points are within eachothers "hitbox" or radius. With normal box focusing, 1 point will overlap the other 2, and they are harder to select. I'll try adapt it to your code, optimizing it without use of sqrt too. And since you can only focus 1 point at the time, i rid of some variables:

Type
TPoint2D = record
x, y : integer;
end;

Var
Point : array of TPoint2D;
Count: integer;
// focusedPoint is -1 if nothing is focused, else it's focused point index
focusedPoint: integer;
...
var dist, nearest, xx, yy: single;
begin
nearest:=8*8; // Point radius 8 in power of 2
focusedPoint:=-1;
for i := 0 to Count-1 do begin
// Get X and Y distance from cursor to point
xx:=mousecur.x-point[i].x;
yy:=mousecur.y-point[i].y;
dist:=xx*xx+yy*yy;
// Think of pythagoras distance formula
// a^2 + b^2 = c^2
// If both sides of comparison are in power of 2, we don't need sqrt()
if dist<nearest then begin
// Current point is closer to cursor than previous best match.
// Set it as the new best match.
nearest:=dist;
focusedPoint:=i;
end;
end;
end;

JC_
31-08-2013, 04:37 PM
Ups.. of course TPoint2D have X,Y.. Rectangle is only "collision checker" :)

i update code above to actual (is possible select only one point and move with him) but i think your code looks better, mathematics is clearer than booleans.. thanks :)