def contains(self, p): """Returns True if p is inside self.""" if self.isConvex(): # If convex, use CCW-esque algorithm inside = False p1 = self.points[0] for i in range(self.n + 1): p2 = self.points[i % self.n] if p.y > min(p1.y, p2.y): if p.y <= max(p1.y, p2.y): if p.x <= max(p1.x, p2.x): if p1.y != p2.y: xints = (p.y - p1.y) * \ (p2.x - p1.x) / (p2.y - p1.y) + p1.x if p1.x == p2.x or p.x <= xints: inside = not inside p1 = p2 return inside else: # If concave, must triangulate and check individual triangles triangles = spatial.triangulatePolygon(self) for triangle in triangles: if triangle.contains(p): return True return False
def smartInteriorPoint(self): """Returns a random interior point via triangulation.""" triangles = spatial.triangulatePolygon(self) areas = [t.area() for t in triangles] total = sum(areas) probabilities = [area / total for area in areas] # Sample triangle according to area r = random() count = 0 for (triangle, prob) in zip(triangles, probabilities): count += prob if count >= r: return triangle.interiorPoint()
def area(self): """Returns the area of the polygon.""" triangles = spatial.triangulatePolygon(self) areas = [t.area() for t in triangles] return sum(areas)