I need to test if a point hits a polygon with holes and isles. I'd like to understand how I'm supposed to do this. That's not documented and I can't find any explanation or examples.
What I do is count +1
for every outer polygon hit and -1
for every inner polygon hit. The resulting sum is:
- > 0: hit;
- <= 0: miss (outside or in a hole).
The HitData
class separates paths based on winding number to avoid unnecessary recomputation of orientation
. With Clipper.PointInPolygon()
applied to every path the sum is easy to compute.
But there are two major drawbacks:
- I have to apply
Clipper.PointInPolygon()
to EVERY path; - I can't leverage the hierarchy of
PolyTree
.
Can someone who has hands-on experience with Clipper (@angus-johnson?) clear up this confusion?
Again, my question is: how am I supposed to implement this? Am I re-inventing the wheel, while there's an actual solution readily available in the Clipper Library?
Side note:
PolyTree
still requires to test EVERY path to determine whichPolyNode
the point is in. There's noClipper.PointInPolyTree()
method and, thus, AFAIKPolyTree
doesn't help.
The structure that separates outer and inner polygons:
public class HitData
{
public List<List<IntPoint>> Outer, Inner;
public HitData(List<List<IntPoint>> paths)
{
Outer = new List<List<IntPoint>>();
Inner = new List<List<IntPoint>>();
foreach (List<IntPoint> path in paths)
{
if (Clipper.Orientation(path))
{
Outer.Add(path);
} else {
Inner.Add(path);
}
}
}
}
And this is the algorithm that tests a point:
public static bool IsHit(HitData data, IntPoint point)
{
int hits;
hits = 0;
foreach (List<IntPoint> path in data.Outer)
{
if (Clipper.PointInPolygon(point, path) != 0)
{
hits++;
}
}
foreach (List<IntPoint> path in data.Inner)
{
if (Clipper.PointInPolygon(point, path) != 0)
{
hits--;
}
}
return hits > 0;
}