0

I saw here a solid algorithm that checks if a point is inside the polygon.

def point_inside_polygon(x, y, poly):
    n = len(poly)
    inside = False

    p1x, p1y = poly[0]
    for i in range(n + 1):
        p2x, p2y = poly[i % n]
        if y > min(p1y, p2y):
            if y <= max(p1y, p2y):
                if x <= max(p1x, p2x):
                    if p1y != p2y:
                        xinters = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
                    if p1x == p2x or x <= xinters:
                        inside = not inside
        p1x, p1y = p2x, p2y    
    return inside

Well, I checked it with both points and polygon:

point_inside_polygon(0.3,0.5,[(0.5,0),(1,0.5),(0.5,1),(0,0.5)]) point_inside_polygon(0.3,1,[(0.5,0),(1,0.5),(0.5,1),(0,0.5)])

and of course the output was correct:

True,False

Then I tried to use it my self with the most little changes that I could do to make it fit my program:

class Point2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __str__(self):
        return "(" + str(self.x) + ", " + str(self.y) + ")"
    def __repr__(self):
        return self.__str__()

class Polygon2D:
    def __init__(self, pts):
        self.points = pts       
    def __repr__(self):
        return str(self.points) 
    def is_inside(self, q):
        n = len(self.points)
        inside = False
        p1x, p1y = self.points[0]
        for i in range(n + 1):
            p2x, p2y = self.points[i % n]
            if q.y > min(p1y, p2y):
                if q.y <= max(p1y, p2y):
                    if q.x <= max(p1x, p2x):
                        if p1y != p2y:
                            xinters = (q.y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
                        if p1x == p2x or q.x <= xinters:
                            inside = not inside
        p1x, p1y = p2x, p2y
        return inside

And when I tried:

p.is_inside(Point2D(0.3, 0.5))
p.is_inside(Point2D(0.3, 1))

the output was wrong: False,True.

Help?

RickyA
  • 15,465
  • 5
  • 71
  • 95

1 Answers1

0

The indentation of your p1x, p1y = p2x, p2y in the class case is wrong. It needs to be in the for i in range(n + 1): loop. Now it is only executed just before return.

correct:

class Point2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return "(" + str(self.x) + ", " + str(self.y) + ")"

    def __repr__(self):
        return self.__str__()

class Polygon2D:
    def __init__(self, pts):
        self.points = pts       

    def __repr__(self):
        return str(self.points) 

    def is_inside(self, q):
        n = len(self.points)
        inside = False
        p1x, p1y = self.points[0]

        for i in range(n + 1):
            p2x, p2y = self.points[i % n]
            if q.y > min(p1y, p2y):
                if q.y <= max(p1y, p2y):
                    if q.x <= max(p1x, p2x):
                        if p1y != p2y:
                            xinters = (q.y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
                        if p1x == p2x or q.x <= xinters:
                            inside = not inside
            p1x, p1y = p2x, p2y
        return inside

gives:

>> True
>> False
RickyA
  • 15,465
  • 5
  • 71
  • 95