def to_graph(polygon: Polygon, extra_points: List[Point], *, convex_divisor: ConvexDivisorType) -> nx.Graph: """ Converts polygon to a region-adjacency graph by dividing it to parts using `convex_divisor` function. Resulting parts become nodes connected when they touch each other. :param polygon: input polygon that will be split :param extra_points: list of points which will be used in splitting the polygon to convex parts :param convex_divisor: function to split the polygon into convex parts :return: graph with parts of the polygon as nodes; edges will keep `side` attributes with the touching segments. """ graph = nx.Graph() polygon_border = polygon.border.raw() holes = list(map(Contour.raw, polygon.holes)) site_points = list(map(Point.raw, extra_points)) polygon_points = {*polygon_border, *chain.from_iterable(holes)} extra_points = list(set(site_points) - polygon_points) parts = convex_divisor(polygon_border, holes, extra_points=extra_points, extra_constraints=()) parts = [Polygon.from_raw((list(part), [])) for part in parts] if len(parts) == 1: graph.add_nodes_from(parts) else: if convex_divisor is constrained_delaunay_triangles: parts_per_sides = defaultdict(set) for part in parts: for side in edges(part.border): parts_per_sides[side].add(part) for side, parts in parts_per_sides.items(): if len(parts) == 2: graph.add_edge(*parts, side=side) else: pairs: Iterator[Tuple[Polygon, Polygon]] = combinations(parts, 2) for part, other in pairs: intersection = part & other if isinstance(intersection, Segment): graph.add_edge(part, other, side=intersection) return graph
def joined_constrained_delaunay_triangles( border: ContourType, holes: Sequence[ContourType] = (), *, extra_points: Sequence[PointType] = (), extra_constraints: Sequence[SegmentType] = () ) -> ConvexPartsType: """Joins polygons to form convex parts of greater size""" triangles = constrained_delaunay_triangles( border, holes, extra_points=extra_points, extra_constraints=extra_constraints) polygons = [ Polygon.from_raw((list(triangle), [])) for triangle in triangles ] initial_polygon = polygons.pop() result = [] while True: resulting_polygon = initial_polygon for index, polygon in enumerate(iter(polygons)): polygon_sides = set(edges(polygon.border)) common_side = next((edge for edge in edges(resulting_polygon.border) if edge in polygon_sides), None) if common_side is None: continue has_point_on_edge = any( Point.from_raw(raw_point) in common_side for raw_point in extra_points) if has_point_on_edge: continue union_ = unite(resulting_polygon, polygon) if isinstance(union_, Polygon) and union_.is_convex: polygons.pop(index) resulting_polygon = union_ if resulting_polygon is not initial_polygon: initial_polygon = resulting_polygon continue result.append(resulting_polygon.border.raw()) if not polygons: return result initial_polygon = polygons.pop()