Конвертировать Multipolygon в Polygon в Python
Можно ли конвертировать Multipolygon
в Polygon
который заполняет все отверстия или пропускает внутренние области, используя Shapely? Я пытался с тех пор, но я не могу найти это в документации. На следующем рисунке я показываю пример мультиполигона с теми отверстиями, которые я хочу заполнить, и теми квадратами, которые я хочу удалить.
2 ответа
Примерный подход может быть следующим:
- извлечь внешнюю границу отдельных компонентов
MultiPolygon
представляет интерес - расширить-сжать каждую из внешних границ, чтобы заполнить "дыры", которые эти границы приблизительно охватывают, например, чтобы обработать "пончик с разрезом"
- объединить все геометрии, полученные в предыдущем шаге
Например:
#!/usr/bin/env python
from shapely.geometry import MultiPolygon, Polygon
from shapely.ops import cascaded_union
a = 0.25
delta = 0.49
P = MultiPolygon([
(
((0,0),(0,3),(3,3),(3,2-delta),(2,2-delta),(2,2),(1,2),(1,1),(2,1),(2,1+delta),(3,1+delta),(3,0),(0,0)),
[((a, a), (1-a,a), (1-a,1-a), (a,1-a), (a,a))]
)
])
eps = 0.01
omega = cascaded_union([
Polygon(component.exterior).buffer(eps).buffer(-eps) for component in P
])
for x,y in zip(*omega.exterior.coords.xy):
print(x, y)
в то время как приведенный выше скрипт выдает ожидаемый примерный квадрат со стороной длины 3, т.е. он заполняет отверстие в левом нижнем углу, а также "пустое пространство" в центре MultiPolygon
который представляется эквивалентным отверстию в процедуре расширения-сжатия с достаточно высоким значением параметра eps
,
Если этого достаточно, чтобы заполнить дыры в каком-то Mul tiPolygon m
Вы могли бы сделать это:
no_holes = MultiPolygon(Polygon(p.exterior) for p in m)
Если вам также необходимо заполнить отверстия, возникающие при прикосновении к полигонам внутри вашего MultiPolygon, должно работать следующее:
# Create a polygon `b` that contains `m`
xmin, ymin, xmax, ymax = m.bounds
b = Polygon([(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)]).buffer(1, resolution=1)
# Take the complement of `m` in `b`, which is a MultiPolygon.
# Pick the outer polygon and take the complement in `b`.
no_holes = b - min(b - m, key=lambda p: p.bounds)