def testIndependentSet(self): n = 100 e = 5 * n g = UndirectedGraph() for i in range(e): u = int(random() * n) v = int(random() * n) if u == v: continue if not g.contains(u): g.add_node(u) if not g.contains(v): g.add_node(v) g.connect(u, v) ind_set = g.independent_set(8) for i in ind_set: neighbors = g.e[i] self.assertEqual(neighbors.intersection(ind_set), set([]))
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