Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function PointInPolygon(X, Y: Integer; Polygon: TPointArray): Boolean;
- (*******************************************************************************
- function PointInPolygon(X, Y: Integer; Polygon: TPointArray): Boolean;
- By: euphemism
- Last Edit: 25 Feb 2012 -- euphemism
- Description: Checks to see if the given point, defined by 'X', and 'Y', lies
- within the given concave/convex polygon, 'Polygon'. Each
- consecutive vertex must be adjacent to the previous one.
- *******************************************************************************)
- var
- I, Len, MaxX, MinX, MaxY, MinY: Integer;
- Crossed0, Crossed1, Crossed2: Extended;
- TestRay0, TestRay1, TestRay2: TLine;
- Sides: Array of TLine;
- begin
- Crossed0 := 0;
- Crossed1 := 0;
- Crossed2 := 0;
- Result := False;
- Len := Length(Polygon);
- SetLength(Sides, Len);
- MaxX := Polygon[1].x;
- MinX := Polygon[0].x;
- MaxY := Polygon[1].y;
- MinY := Polygon[0].y;
- for I := 0 to (Len - 2) do //This loop creates an array of the sides of the polygon.
- begin
- Sides[i].A := Polygon[i];
- Sides[i].B := Polygon[i + 1];
- end;
- Sides[Len - 1].A := Polygon[Len - 1]; //These two lines set the last side of the polygon.
- Sides[Len - 1].B := Polygon[0];
- for I := 0 to (Len - 1) do //This loop finds the minimum X and Y values from the
- begin //passed vertices. This is so we know where to shoot our test ray.
- MaxX := Max(Polygon[i].x, MaxX);
- MinX := Min(Polygon[i].x, MinX);
- MaxY := Max(Polygon[i].y, MaxY);
- MinY := Min(Polygon[i].y, MinY);
- end;
- TestRay0.A := IntToPoint(X, Y); //This sets the test rays to useable segments.
- TestRay0.B := IntToPoint(MinX - 10, MinY - 10);
- TestRay1.A := IntToPoint(X, Y);
- TestRay1.B := IntToPoint(MaxX + 10, MinY - 10);
- TestRay2.A := IntToPoint(X, Y);
- TestRay2.B := IntToPoint(MaxX + 10, MaxY + 10);
- {$IFDEF SMART}
- if ObjDTM_Debug then
- begin
- SMART_DrawPolygons(False, [Polygon], clWhite);
- SMART_DrawLine(False, TestRay0.A, TestRay0.B, clRed);
- SMART_DrawLine(False, TestRay1.A, TestRay1.B, clRed);
- SMART_DrawLine(False, TestRay2.A, TestRay2.B, clRed);
- end;
- {$ENDIF}
- for I := 0 to (Len - 1) do //This loop runs through all sides of the polygon and sees if the
- begin //test rays intersect each side. If so, then we increase the 'CrossedX' values
- //Using multiple test rays ensures accuracy.
- if LinesIntersect(TestRay0, Sides[i]) then
- Crossed0 := Crossed0 + 1;
- if LinesIntersect(TestRay1, Sides[i]) then
- Crossed1 := Crossed1 + 1;
- if LinesIntersect(TestRay2, Sides[i]) then
- Crossed2 := Crossed2 + 1;
- end;
- if Crossed1 <= Crossed0 then
- Crossed0 := Crossed1;
- if Crossed2 <= Crossed0 then //If the test rays crossed an odd number of sides, then the point is within
- Crossed0 := Crossed2; //the polygon, if they crossed an even number of sides, or no sides, the point is outside.
- Result := ((Crossed0 mod 2) = 1); //This line checks to see if the test rays crossed an even or odd
- end; //number of sides, and sets the result accordingly.
- {||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||}
Advertisement
Add Comment
Please, Sign In to add comment