Example #1
0
    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 drawPolygon(self, p, fill):
        """Draw polygon onto canvas."""
        if p is None:
            self.intersection = Polygon()
            self.canvas.create_text(self.canvas.winfo_width() / 2,
                                    self.canvas.winfo_height() / 2,
                                    text='no intersection',
                                    fill=fill)
        else:
            # create single list of (x,y) coordinates
            full = [None] * 2 * p.numEdges()
            idx = 0
            for pt in p:
                full[idx] = pt.x()
                full[idx + 1] = self.toTk(pt.y())
                idx += 2
            self.canvas.create_polygon(full, fill=fill)

            # show points in gray
            for pt in p:
                self.canvas.create_oval(pt.x() - 4,
                                        self.toCartesian(pt.y() - 4),
                                        pt.x() + 4,
                                        self.toCartesian(pt.y() + 4),
                                        fill='gray')
Example #3
0
 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_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))
Example #5
0
 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 __init__(self, master):
        """App to construct polygon by successive left-mouse clicks."""

        master.title(
            "Left press to add point to polygon. Right press to start new one."
        )
        self.master = master

        # keep track of polygons being created
        self.polygons = [Polygon()]

        self.canvas = Canvas(master, width=512, height=512)
        self.canvas.bind("<Button-1>", self.add)
        self.canvas.bind("<Button-2>", self.finalize)
        self.canvas.pack()
Example #7
0
    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))
Example #8
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)
Example #9
0
    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))
Example #10
0
    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 computeHull (points):
    """
    Compute the convex hull for given points and return as polygon.
    Returned polygon is in 'counter-clockwise' fashion, with the 
    interior "to the left" of each edge.
    """
    # sort by x coordinate (and if ==, by y coordinate). 
    n = len(points)
    
    points = sorted(points, key=lambda pt:[pt.x(), pt.y()])
    if n < 3:
        return Polygon(points)
        
    # Compute upper hull by starting with rightmost two points
    upper = Polygon ([points[-1], points[-2]])
    for i in range(n-3, -1, -1):
        upper.add (points[i].x(), points[i].y())

        while upper.numPoints() >=3 and lastThreeNonLeft(upper):
            upper.remove(-2)

    # Compute lower hull by starting with leftmost two points
    lower = Polygon ([points[0], points[1]])
    for i in range(2, n):
        lower.add (points[i].x(), points[i].y())

        while lower.numPoints() >=3 and lastThreeNonLeft(lower):
            lower.remove(-2)
                
    # Merge into upper (skip first and last to avoid duplication) and return.
    upper.remove(-1)
    upper.remove(0)
    for pt in upper:
        lower.add(pt.x(), pt.y())

    return lower
Example #12
0
 def test_simpleonvexShape(self):
     p = Polygon([Point(-2, 2), Point(0, -2), Point(2, 2)])
     self.assertTrue(p.convex())
Example #13
0
 def test_nonConvexShape(self):
     p = Polygon([Point(-2, 2), Point(0, -2), Point(2, 2), Point(0, 0)])
     self.assertFalse(p.convex())
Example #14
0
def convexIntersect(p, q):
    """
    Compute and return polygon resulting from the intersection of
    two convext polygons, p and q.
    """
    intersection = Polygon()
    pn = p.numEdges()
    qn = q.numEdges()
    k = 1
    inside = None              # can't know inside until intersection
    first = None               # remember 1st intersection to know when to stop
    firstp = pe = p.edges()[0] # get first edge of p and q
    firstq = qe = q.edges()[0]
    while k < 2*(pn + qn):
        pt = pe.intersect(qe)
        if pt is not None:
            if first == None:
                first = pt
            elif pt == first:
                # stop when find first intersection again
                break

            intersection.add(pt.x(), pt.y())
            if inhalfplane(pe.tail(), qe):
                inside = p
            else:
                inside = q

        # Identify relationship between edges; either we advance
        # p or we advance q, based on whether p's current edge
        # is aiming at qe (or vice versa).
        advancep = advanceq = False

        if (aim(pe,qe) and aim(qe,pe)) or (not aim(pe,qe) and not aim(qe,pe)):
            if inside is p:
                advanceq = True
            elif inside is q:
                advancep = True
            else:
                # no intersection yet. Choose based on
                # which one is "outside"
                if inhalfplane(pe.tail(), qe):
                    advanceq = True
                else:
                    advancep = True
        elif aim(pe, qe):
            advancep = True
        elif aim(qe, pe):
            advanceq = True

##        if aim(pe, qe):
##            if aim(qe, pe):
##                if inside is p:
##                    advanceq = True
##                elif inside is q:
##                    advancep = True
##                else:
##                    advancep = True    # arbitrary pick
##            else:
##                advancep = True
##        else:
##            if aim(qe, pe):
##                advanceq = True
##            else:
##                if inside is p:
##                    advanceq = True
##                elif inside is q:
##                    advancep = True
##                else:
##                    advancep = True    # arbitrary pick

        if advancep:
            if inside is p:
                intersection.add(pe.tail().x(), pe.tail().y())
            pe = pe.next()
        elif advanceq:
            if inside is q:
                intersection.add(qe.tail().x(), qe.tail().y())
            qe = qe.next()

        k += 1
            
    if intersection.numPoints() == 0:
        if containedWithin(firstp.tail(), q):
            return p
        elif containedWithin(firstq.tail(), p):
            return q
        else:
            return None

    # Return computed intersection
    return intersection
Example #15
0
 def clear(self, event):
     """Clear all polygons and start again."""
     self.polygons = [Polygon()]
     self.visit()
Example #16
0
 def finalize(self, event):
     """Finalize polygon and add a new one."""
     self.polygons.insert(0, Polygon())
     self.visit()