Exemple #1
0
        def triangulate_regions(regions):
            """
                Processes a set of regions (non-overlapping polygons tiling a portion of the plane),
                triangulating any region that is not already a triangle, and storing triangulated
                relationships in a DAG.

                Arguments:
                regions -- a set of non-overlapping polygons that tile some part of the plane

                Returns: a triangulation for each individual region in 'regions'
            """
            frontier = []

            for region in regions:
                self.dag.add_node(region)

                # If region is not a triangle, triangulate
                if region.n > 3:
                    triangles = spatial.triangulatePolygon(region)
                    for triangle in triangles:
                        # Connect DAG
                        self.dag.add_node(triangle)
                        self.dag.connect(triangle, region)
                        # Add to frontier
                        frontier.append(triangle)
                else:
                    frontier.append(region)

            return frontier
Exemple #2
0
            def add_bounding_triangle(poly):
                """
                    Calculates a bounding triangle for a polygon

                    Arguments:
                    poly -- a polygon to-be bound

                    Returns: a bounding polygon for 'poly'
                """

                bounding_tri = min_triangle.boundingTriangle(poly.points)
                bounding_regions = spatial.triangulatePolygon(
                    bounding_tri, hole=poly.points)
                return bounding_tri, bounding_regions
Exemple #3
0
        def remove_independent_set(regions):
            """
                Processes a set of regions, detecting and removing an independent set
                of vertices from the regions' graph representation, and re-triangulating
                the resulting holes.

                Arguments:
                regions -- a set of non-overlapping polygons that tile some part of the plane

                Returns: a new set of regions covering the same subset of the plane, with fewer vertices
            """
            # Take note of which points are in which regions
            points_to_regions = {}
            for idx, region in enumerate(regions):
                for point in region.points:
                    if point in points_to_regions:
                        points_to_regions[point].add(idx)
                        continue

                    points_to_regions[point] = set([idx])

            # Connect graph
            g = UndirectedGraph()
            for region in regions:
                for idx in range(region.n):
                    u = region.points[idx % region.n]
                    v = region.points[(idx + 1) % region.n]
                    if not g.contains(u):
                        g.add_node(u)
                    if not g.contains(v):
                        g.add_node(v)
                    g.connect(u, v)

            # Avoid adding points from outer triangle
            removal = g.independent_set(8, avoid=bounding_triangle.points)

            # Track unaffected regions
            unaffected_regions = set([i for i in range(len(regions))])
            new_regions = []
            for p in removal:
                # Take note of affected regions
                affected_regions = points_to_regions[p]
                unaffected_regions.difference_update(points_to_regions[p])

                def calculate_bounding_polygon(p, affected_regions):
                    edges = []
                    point_locations = {}
                    for j, i in enumerate(affected_regions):
                        edge = set(regions[i].points)
                        edge.remove(p)
                        edges.append(edge)
                        for v in edge:
                            if v in point_locations:
                                point_locations[v].add(j)
                            else:
                                point_locations[v] = set([j])

                    boundary = []
                    edge = edges.pop()
                    for v in edge:
                        point_locations[v].remove(len(edges))
                        boundary.append(v)
                    for k in range(len(affected_regions) - 2):
                        v = boundary[-1]
                        i = point_locations[v].pop()
                        edge = edges[i]
                        edge.remove(v)
                        u = edge.pop()
                        point_locations[u].remove(i)
                        boundary.append(u)

                    return shapes.Polygon(boundary)

                # triangulate hole
                poly = calculate_bounding_polygon(p, affected_regions)
                triangles = spatial.triangulatePolygon(poly)
                for triangle in triangles:
                    self.dag.add_node(triangle)
                    for j in affected_regions:
                        region = regions[j]
                        self.dag.connect(triangle, region)
                    new_regions.append(triangle)

            for i in unaffected_regions:
                new_regions.append(regions[i])

            return new_regions
Exemple #4
0
 def testRandomTriangles(self):
     poly = randomConvexPolygon(50)
     regions = triangulatePolygon(poly)
     self.runLocator(regions)