Determine if a point is inside a polygon?

I am making a custom control in Delphi (inherited from TCustomControl ), which consists of several elements of the list of polygons (irregular shapes). I need to implement mouse events for each element, but first I need to determine if the mouse position is in the given polygon ( array of TPoint ). I catch the Hit test message ( WM_NCHITTEST ), and it is here that I will need to perform this check. I have several polygons, I will loop through each element of the polygon and conduct this test to see if the X / Y mouse position is inside this polygon.

 procedure TMyControl.WMNCHitTest(var Message: TWMNCHitTest); var P: TPoint; //X/Y of Mouse Poly: TPoints; //array of TPoint X: Integer; //iterator I: TMyListItem; //my custom list item begin PX:= Message.XPos; PY:= Message.YPos; for X := 0 to Items.Count - 1 do begin I:= Items[X]; //acquire my custom list item by index Poly:= I.Points; //acquire polygon points //Check if Point (P) is within Polygon (Poly)...? end; end; 
+7
source share
4 answers

You can use PtInRegion :

 function PointInPolygon(Point: TPoint; const Polygon: array of TPoint): Boolean; var rgn: HRGN; begin rgn := CreatePolygonRgn(Polygon[0], Length(Polygon), WINDING); Result := PtInRegion(rgn, Point.X, Point.Y); DeleteObject(rgn); end; 
+15
source

You can use the beam casting algorithm found here: http://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm

Most computer graphics classes use this as an example.

+5
source

Checking whether a point is inside the polygon can be done by presenting a horizontal line through this point, and then counting from left to right how many times this imaginary line intersects the polygon. If the number of intersections of the polygons before hitting the point is odd, then the point is inside, even if the point is outside the polygon.

+1
source

There is another method that we widely use that is not related to any math at all and can handle extremely complex embedded controls of any shape whatsoever. Just use the screen image of the control with all the color-coded parts (as shown in the figure below) that the user could click.

When they move their mouse, just look at the color of the pixel under the mouse on our screen image, and this definitely indicates which button / control they are crossed out - white for not above it, and any color series for different parts.

Color mask

// pseudo code

 function MouseOverControl(LocalMousePos:TPoint):ControlID; begin //sanity check Result:=IDNull; if (LocalMouse.X < 0) or (LocalMouse.X > ControlWidth) or (LocalMouse.Y < 0) or (LocalMouse.Y > ControlHeight) then exit; case OffScreenControlMask.Canvas.Pixels[LocalMousePos.X,LocalMousePos.Y] of clwhite:exit; clRed:result:=ControlIDOne; clGreen:result:=ControlIDTwo; clBlue:result:=ControlIDThree; ... etc end; end; 

NOTE. The attached Color Mask image represents five identical rotary controls, divided into quadrants with a central button (and since they all use the same colors, we have constants for each color and we determine which of the five mice is simple XPosition) along with an additional irregular controls on the right and dials or rectangular buttons at the bottom.

0
source

All Articles