减去多边形并将其转换为Python中没有孔的

问题描述 投票:0回答:1

我有几个蓝色和红色的多边形。我想从蓝色中减去红色。

完成此操作后,剩余的一些多边形可能会有孔。我希望将那些有孔的多边形转换为无孔的多边形。

到目前为止我已经尝试过的事情

from typing import TypedDict
from shapely.geometry import MultiPolygon, Polygon


class Coords(TypedDict):
    x: list[float]
    y: list[float]


def subtract_polygons(group_a: list[Coords], group_b: list[Coords]):
    # Convert polygons to Shapely Polygon objects
    polygons_a = [Polygon(zip(group["x"], group["y"])) for group in group_a]
    polygons_b = [Polygon(zip(group["x"], group["y"])) for group in group_b]

    # Create a "negative" polygon for the hole in group B
    negative_polygons_b = [polygon.exterior for polygon in polygons_b]

    # Subtract each polygon in polygons_b from each polygon in polygons_a
    result_polygons = []
    for polygon_a in polygons_a:
        for negative_polygon_b in negative_polygons_b:
            result_polygon = polygon_a.difference(negative_polygon_b)
            result_polygons.append(result_polygon)

    # Convert the resulting geometry to MultiPolygon
    result_multipolygon = MultiPolygon(result_polygons)

    print("polygons_a", polygons_a)
    print("polygons_b", polygons_b)
    print("negative_polygons_b", negative_polygons_b)
    print("result_multipolygon", result_multipolygon)

group_a: list[Coords] = [
    {"x": [100, 200, 200, 100, 100], "y": [100, 100, 200, 200, 100]},
    {"x": [130, 230, 230, 130, 130], "y": [130, 130, 230, 230, 130]},
    {"x": [180, 280, 280, 180, 180], "y": [180, 180, 280, 280, 180]},
]
group_b: list[Coords] = [
    {"x": [150, 175, 175, 150, 150], "y": [150, 150, 175, 175, 150]},
    {"x": [150, 250, 250, 150, 150], "y": [220, 220, 320, 320, 220]},
]

subtract_polygons(group_a, group_b)

想要的结果:

请注意,这条小线是任意的。我只是想表明它是一个单一的多边形,在这种情况下是凹的,没有孔

输入与实际结果:

控制台输出:

polygons_a [
<POLYGON ((100 100, 200 100, 200 200, 100 200, 100 100))>,
<POLYGON ((130 130, 230 130, 230 230, 130 230, 130 130))>,
<POLYGON ((180 180, 280 180, 280 280, 180 280, 180 180))>
]

polygons_b [
<POLYGON ((150 150, 175 150, 175 175, 150 175, 150 150))>,
<POLYGON ((150 220, 250 220, 250 320, 150 320, 150 220))>
]

negative_polygons_b [
<LINEARRING (150 150, 175 150, 175 175, 150 175, 150 150)>,
<LINEARRING (150 220, 250 220, 250 320, 150 320, 150 220)>
]

result_multipolygon MULTIPOLYGON (
((100 200, 200 200, 200 100, 100 100, 100 200)),
((100 200, 200 200, 200 100, 100 100, 100 200)),
((130 230, 230 230, 230 130, 130 130, 130 230)),
((230 130, 130 130, 130 230, 150 230, 230 230, 230 220, 230 130)),
((180 280, 280 280, 280 180, 180 180, 180 280)),
((280 280, 280 180, 180 180, 180 220, 180 280, 250 280, 280 280))
)
python polygon shapely
1个回答
0
投票

如果我正确理解您想要完成的任务,那么您的脚本中存在几个问题:

  • polygon.exterior 返回一个线性环,而不是一个 Polygon,因此您不能直接使用它来与
  • 进行区分
  • 您想要从 a 组中的每个多边形中减去 b 组中的每个多边形,但您的循环没有执行此操作
  • 根据您的示例输出,您希望合并输出

更正的脚本:

from typing import TypedDict
from matplotlib import pyplot as plt
import shapely
from shapely.geometry import Polygon
from shapely.plotting import plot_polygon


class Coords(TypedDict):
    x: list[float]
    y: list[float]


def subtract_polygons(group_a: list[Coords], group_b: list[Coords]):
    # Convert polygons to Shapely Polygon objects
    polygons_a = [Polygon(zip(group["x"], group["y"])) for group in group_a]
    polygons_b = [Polygon(zip(group["x"], group["y"])) for group in group_b]

    # Create a "negative" polygon for the hole in group B
    negative_polygons_b = [Polygon(polygon.exterior) for polygon in polygons_b]

    # Subtract each polygon in polygons_b from each polygon in polygons_a
    result_polygons = []
    for polygon_a in polygons_a:
        result_polygon = polygon_a
        for negative_polygon_b in negative_polygons_b:
            result_polygon = result_polygon.difference(negative_polygon_b)

        result_polygons.append(result_polygon)

    return shapely.union_all(result_polygons)


group_a: list[Coords] = [
    {"x": [100, 200, 200, 100, 100], "y": [100, 100, 200, 200, 100]},
    {"x": [130, 230, 230, 130, 130], "y": [130, 130, 230, 230, 130]},
    {"x": [180, 280, 280, 180, 180], "y": [180, 180, 280, 280, 180]},
]
group_b: list[Coords] = [
    {"x": [150, 175, 175, 150, 150], "y": [150, 150, 175, 175, 150]},
    {"x": [150, 250, 250, 150, 150], "y": [220, 220, 320, 320, 220]},
]

result = subtract_polygons(group_a, group_b)

# Plot
polygons_a = [Polygon(zip(group["x"], group["y"])) for group in group_a]
polygons_b = [Polygon(zip(group["x"], group["y"])) for group in group_b]

for polygon_a in polygons_a:
    plot_polygon(polygon_a)
for polygon_b in polygons_b:
    plot_polygon(polygon_b, color="red")
plt.show()
plot_polygon(result)
plt.show()
© www.soinside.com 2019 - 2024. All rights reserved.