How to determine if a Point is inside of a 2D Polygon that has Arcs

How to determine if a Point is inside of a 2D Polygon that has Arcs

dalexanderSP3WJ
Enthusiast Enthusiast
2,817 Views
2 Replies
Message 1 of 3

How to determine if a Point is inside of a 2D Polygon that has Arcs

dalexanderSP3WJ
Enthusiast
Enthusiast

I have been using the following references to try to determine if a Point is inside of a 2D Polygon that has Arcs:

https://stackoverflow.com/questions/217578/how-can-i-determine-whether-a-2d-point-is-within-a-polygo...

https://stackoverflow.com/questions/34880628/point-inside-compound-polygon

https://scicomp.stackexchange.com/questions/16343/how-to-determine-if-a-point-is-outside-or-inside-a...

 

My approach uses Ray Casting to determine if a point is within the polygon boundary. This is my code that attempts to string the references together:

public static bool IsInsideBoundary(Polyline pline, Point3d pnt, Document currentDoc)
		{
			try
			{
				if (pline.Closed == true)
				{
					Tools.Log("Polyline is Closed");

					// Check if point is on the line -> WORKS
					if (IsPointOnCurve(pline, pnt))
					{
						Log("Point is on the Boundary line");
						return true;
					}
					else
					{
                        int numOfVerts = pline.NumberOfVertices;

						// Get bounding box of boundary
						double minX = pline.GetPoint3dAt(0).X;
						double maxX = pline.GetPoint3dAt(0).X;
						double minY = pline.GetPoint3dAt(0).Y;
						double maxY = pline.GetPoint3dAt(0).Y;

						for (int i = 1; i < numOfVerts; i++)
						{
							Point3d q = pline.GetPoint3dAt(i);
							minX = Math.Min(q.X, minX);
							maxX = Math.Max(q.X, maxX);
							minY = Math.Min(q.Y, minY);
							maxY = Math.Max(q.Y, minY);
						}

						// Check if the given point outside of the bounding box
						if (pnt.X < minX || pnt.X > maxX || pnt.Y < minY || pnt.Y > maxY)
						{
							return false;
						}
						Log("Bounding Box check passed...");
						bool inside = false;
						for (int i = 0, j = numOfVerts - 1; i < numOfVerts; j = i++)
						{
							double a1 = pline.GetPoint3dAt(i).X, a2 = pline.GetPoint3dAt(i).Y;
							double b1 = pnt.X, b2 = pnt.Y;
							double c1 = pline.GetPoint3dAt(j).X, c2 = pline.GetPoint3dAt(j).Y;
							// Use the Jordan Curve Theorem
							double d1 = (c1 - a1) * (b2 - a2) / (c2 - a2) + a1;
							
							// Split arc into monotone parts and check bounds
							if ((a2 > b2) != (c2 > b2) && b1 < d1)
							{
								inside = !inside;
							}
						}
						Log("Point is within the boundary");
						return inside;
						
					}
				}
				else
				{
					Log("Boundary is not closed.");
				}
			}
			catch (System.Exception e)
			{
				Log("InsideBoundary() Failed. Exception: " + e.Message, true);
			}
			return false;
		}

 

This approach works fine for any polygon that has no arcs, but when an arc is introduced, and the point lies within the bounds of the polygon perimeter, a false negative is produced.

Here is an example of the polygons I am testing:

Screenshot 2021-05-10 103719.png

 

Any help would be greatly appreciated, thank you.

0 Likes
Accepted solutions (1)
2,818 Views
2 Replies
Replies (2)
Message 2 of 3

_gile
Consultant
Consultant
Accepted solution

Hi,

You can use the MPolygon way as shown in this reply or the BREP way as in this one from Tony Tanzillo at TheSwamp.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 3

dalexanderSP3WJ
Enthusiast
Enthusiast

@_gile Thank you for the quick turnaround, this helps a ton.

0 Likes