def test_defective(self): """ This test case detected defect in algorithm. Resolving it explained how to choose whether to advance p or q before an intersection had been discovered. """ p = Polygon([ Point(241, 243), Point(353, 210), Point(393, 245), Point(375, 398), Point(257, 303) ]) q = Polygon([ Point(108, 189), Point(268, 116), Point(456, 180), Point(434, 226), Point(125, 486) ]) self.assertTrue(p.convex()) self.assertTrue(q.convex()) i1 = convexIntersect(p, q) i2 = convexIntersect(q, p) self.assertTrue(samePolygon(i1, i2))
def test_nonIntersectEndPoints(self): p = Point(0, 0) e = Edge(p, Point(2, 3)) f = Edge(p, Point(-2, 3)) self.assertIsNone(e.intersect(f))
def test_nonIntersectSimplePolygonsOnEndPoints(self): a = Point(0, 0) b = Point(-2, 2) c = Point(2, 2) d = Point(-2, -2) e = Point(2, -2) p = Polygon([a, b, c]) q = Polygon([a, d, e]) self.assertFalse(p.intersect(q))
def computeRandom(x, y, u, v): """ Compute random convex polygon within given (x,y), (u,v) bounding area. Start from relatively small number of points so polygon has some interesting shapes """ points = [Point(random.randint(x,u),random.randint(y,v)) for i in range(10)] return computeHull(points)
def test_enclosing(self): """Detect when polygon wholly contains another polygon.""" square = Polygon( [Point(-8, -8), Point(8, -8), Point(8, 8), Point(-8, 8)]) triangle = Polygon([Point(-3, 0), Point(3, 0), Point(0, 3)]) self.assertTrue(triangle.convex()) self.assertTrue(square.convex()) p = convexIntersect(square, triangle) q = convexIntersect(triangle, square) self.assertEqual(p, q) real = Polygon([Point(-3, 0), Point(3, 0), Point(0, 3)]) self.assertTrue(samePolygon(p, real)) self.assertTrue(samePolygon(real, p))
def aim (p, q): """Return true if p is "aiming towards" q's half-plane edge.""" # First check if p.tail is in the half-plane of q inside = inhalfplane(p.tail(), q) # compute cross product of q x p to determine orientation # en.wikipedia.org/wiki/Cross_product#Computational_geometry # normalize p and q pnorm = Point(p.tail().x() - p.head().x(), p.tail().y() - p.head().y()) qnorm = Point(q.tail().x() - q.head().x(), q.tail().y() - q.head().y()) cross = qnorm.x()*pnorm.y() - qnorm.y()*pnorm.x() if inside: # in half-plane, so now check orientation return cross < 0 else: # not in half-plane. return cross >= 0
def test_noIntersection(self): """Detect no intersection.""" square = Polygon( [Point(-8, -8), Point(8, -8), Point(8, 8), Point(-8, 8)]) triangle = Polygon([Point(23, 0), Point(25, 0), Point(24, 1)]) self.assertTrue(triangle.convex()) self.assertTrue(square.convex()) p = convexIntersect(square, triangle) q = convexIntersect(triangle, square) self.assertEqual(p, q) self.assertIsNone(p)
def intersect(self, e): """Return intersection between two edges (aside from end-points).""" if self.head() == e.head() or self.head() == e.tail(): return None if self.tail() == e.head() or self.tail() == e.tail(): return None # compute intersection of two line segments using x,y coords pt = intersect(self.head().x(), self.head().y(), self.tail().x(), self.tail().y(), e.head().x(), e.head().y(), e.tail().x(), e.tail().y()) if pt is None: return None return Point (pt[0], pt[1])
def test_intersect(self): # Note: only works if convex polygons in # normal form, with points/edges in counter-clockwise # fashion. square = Polygon( [Point(-2, -2), Point(2, -2), Point(2, 2), Point(-2, 2)]) triangle = Polygon([Point(-2, -2), Point(2, -2), Point(0, 4)]) self.assertTrue(triangle.convex()) self.assertTrue(square.convex()) p = convexIntersect(square, triangle) q = convexIntersect(triangle, square) self.assertTrue(samePolygon(p, q)) real = Polygon( [Point(2 / 3, 2), Point(-2 / 3, 2), Point(-2, -2), Point(2, -2)]) self.assertTrue(samePolygon(p, real)) self.assertTrue(samePolygon(real, p))
def add(self, event): """Add point to polygon and redraw.""" self.points.append(Point(event.x, self.toCartesian(event.y))) self.visit()
def test_simpleonvexShape(self): p = Polygon([Point(-2, 2), Point(0, -2), Point(2, 2)]) self.assertTrue(p.convex())
def test_nonConvexShape(self): p = Polygon([Point(-2, 2), Point(0, -2), Point(2, 2), Point(0, 0)]) self.assertFalse(p.convex())
def test_canIntersectEndPointWithRealIntersection(self): e = Edge(Point(0, 0), Point(2, 2)) f = Edge(Point(-2, 2), Point(2, -2)) self.assertTrue(e.intersect(f))
def test_slide(self): """Example to use with slide presentation.""" square = Polygon([ Point(0, 8), Point(0, 0), Point(8, 0), Point(8, 8)]) triangle = Polygon([ Point(8, 10), Point(4, 6), Point(12, 6)]) self.assertTrue (triangle.convex()) self.assertTrue (square.convex()) p = convexIntersect(square, triangle) q = convexIntersect(triangle, square) self.assertEqual(p, q) real = Polygon([ Point(8, 6), Point(8, 8), Point(6, 8), Point(4, 6) ]) self.assertTrue (samePolygon(p, real)) self.assertTrue (samePolygon(real, p))
def test_weakSimple(self): """See Wikipedia for entry on weakly simple polygon.""" m = Point(0, 0) a = Point(0, 4) b = Point(8, 4) c = Point(8, 0) d = Point(4, 0) e = Point(4, 1) f = Point(6, 1) g = Point(6, 3) h = Point(2, 3) j = Point(2, 1) k = Point(4, 1) # same as e l = Point(4, 0) # same as d p = Polygon([a, b, c, d, e, f, g, h, j, k, l, m]) self.assertTrue(p.simple())
def test_intersectNoPointsInCommon(self): square = Polygon( [Point(-2, -2), Point(2, -2), Point(2, 2), Point(-2, 2)]) triangle = Polygon([Point(-3, 0), Point(3, 0), Point(0, 3)]) self.assertTrue(triangle.convex()) self.assertTrue(square.convex()) p = convexIntersect(square, triangle) q = convexIntersect(triangle, square) self.assertTrue(samePolygon(p, q)) real = Polygon([ Point(2, 0), Point(2, 1), Point(1, 2), Point(-1, 2), Point(-2, 1), Point(-2, 0) ]) self.assertTrue(samePolygon(p, real)) self.assertTrue(samePolygon(real, p))
def add(self, x, y): """Extend polygon with additional (x,y) point.""" self.points.append(Point(x, y)) n = len(self.points)