Ray casting point in polygon test for polygon with ray-aligned edges

1.4k views Asked by At

I tried using the following code for the Even-Odd Rule from Wikipedia

# x, y -- x and y coordinates of point
# poly -- a list of tuples [(x, y), (x, y), ...]
def isPointInPath(x, y, poly):
        num = len(poly)
        i = 0
        j = num - 1
        c = False
        for i in range(num):
                if  ((poly[i][1] > y) != (poly[j][1] > y)) and \
                        (x < (poly[j][0] - poly[i][0]) * (y - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0]):
                    c = not c
                j = i
        return c

Unfortuantely, it's giving wrong results for my simple rectilinear polygon when my test point is aligned with one of the horizontal edges

     -----
     |   |
     | x  ----|
  x  |--------|

Treating a horizontal edge as an edge makes both points regarded as within while ignoring the horizontal edge makes both points regarded as outside

So how can I make the even-odd rule work for such a polygon? Or suggest alternative algorithms?

1

There are 1 answers

1
Rufus On

The following rules taken from here seems to work

Edge Crossing Rules

an upward edge includes its starting endpoint, and excludes its final endpoint;

a downward edge excludes its starting endpoint, and includes its final endpoint;

horizontal edges are excluded

the edge-ray intersection point must be strictly right of the point P.

Note that the above rules follow the convention that

a point on a left or bottom edge is inside, and a point on a right or top edge is outside. This way, if two distinct polygons share a common boundary segment, then a point on that segment will be in one polygon or the other, but not both at the same time.

Also the author notes that this method only works for simple (non-self-intersecting) polygons. It also suggests using an efficient implementation of winding numbers instead which handles non-simple polygons better