Более быстрый способ пересечения многоугольника с фигурным

У меня большое количество многоугольников (~ 100000), и я пытаюсь найти умный способ вычисления их площади пересечения с помощью ячеек регулярной сетки.

В настоящее время я создаю многоугольники и ячейки сетки, используя shapely (на основе их угловых координат). Затем, используя простой цикл for, я просматриваю каждый многоугольник и сравниваю его с соседними ячейками сетки.

Просто небольшой пример для иллюстрации многоугольников / ячеек сетки.

from shapely.geometry import box, Polygon
# Example polygon 
xy = [[130.21001, 27.200001], [129.52, 27.34], [129.45, 27.1], [130.13, 26.950001]]
polygon_shape = Polygon(xy)
# Example grid cell
gridcell_shape = box(129.5, -27.0, 129.75, 27.25)
# The intersection
polygon_shape.intersection(gridcell_shape).area

(Кстати: ячейки сетки имеют размеры 0,25x0,25, а полигоны 1x1 при макс.)

На самом деле это довольно быстро для отдельной комбинации полигон / ячейка сетки - около 0,003 секунды. Однако запуск этого кода на огромном количестве многоугольников (каждый из которых может пересекать десятки ячеек сетки) занимает около 15+ минут (до 30+ минут в зависимости от количества пересекающихся ячеек сетки) на моем компьютере, что неприемлемо. К сожалению, я понятия не имею, как можно написать код для пересечения многоугольников, чтобы получить область перекрытия. Есть ли у вас какие-либо советы? Есть ли альтернатива shapely?


person HyperCube    schedule 04.02.2013    source источник
comment
Мне любопытно, как вы зацикливаете и пересекаете свои многоугольники. Не могли бы вы показать больше кода процесса? Было бы легче понять, как это можно оптимизировать.   -  person tdedecko    schedule 05.02.2013
comment
Я в основном беру массив значений углов широты и долготы и конвертирую их в цикле for в многоугольники. Затем я сравниваю каждый многоугольник с определенной ячейкой сетки, что снова делается в цикле for. См. Это: stackoverflow.com/a/13956110/1740928   -  person HyperCube    schedule 05.02.2013


Ответы (2)


Рассмотрите возможность использования Rtree, чтобы определить, какие ячейки сетки могут пересекать многоугольники. Таким образом, вы можете удалить цикл for, используемый с массивом lat / lons, который, вероятно, является самой медленной частью.

Структурируйте свой код примерно так:

from shapely.ops import cascaded_union
from rtree import index
idx = index.Index()

# Populate R-tree index with bounds of grid cells
for pos, cell in enumerate(grid_cells):
    # assuming cell is a shapely object
    idx.insert(pos, cell.bounds)

# Loop through each Shapely polygon
for poly in polygons:
    # Merge cells that have overlapping bounding boxes
    merged_cells = cascaded_union([grid_cells[pos] for pos in idx.intersection(poly.bounds)])
    # Now do actual intersection
    print(poly.intersection(merged_cells).area)
person Mike T    schedule 11.02.2013
comment
Это остается невероятно полезным ответом - его следовало принять. У меня была аналогичная проблема, и Rtree заставил алгоритм работать примерно в 5000 раз быстрее. - person Gabriel; 09.01.2016
comment
Обратите внимание, что Rtree можно использовать только для прямоугольников (4 точки), но не для сложных многоугольников. - person Ikar Pohorský; 15.02.2017
comment
Для реальных многоугольников просто добавьте правильную actual geometry intersects? проверку для каждого пересечения границ. Rtree позволяет сократить пространство поиска, и все происходит очень быстро. - person bugmenot123; 16.05.2018
comment
Хотя старый ответ, это результат, который, как я обнаружил, напоминает мне, какой объект ... rtree ... Если у вас сложный поли, просто оберните его, а затем сравните его сначала перед сложным ... Это снова поможет ускорить процесс . + 1 для простого примера - person Angry 84; 30.08.2018
comment
Кстати, shapely имеет реализацию R-tree, как указано в ответе ниже: shapely.readthedocs.io/en/stable/manual.html#str-packed-r-tree - person chris; 11.06.2019

С 2013/2014 у Shapely есть STRtree. Я использовал его, и, похоже, он работает хорошо.

Вот отрывок из строки документации:

STRtree - это R-дерево, которое создается с использованием алгоритма Sort-Tile-Recursive. STRtree принимает последовательность геометрических объектов в качестве параметра инициализации. После инициализации метод запроса можно использовать для выполнения пространственного запроса по этим объектам.

>>> from shapely.geometry import Polygon
>>> from shapely.strtree import STRtree
>>> polys = [Polygon(((0, 0), (1, 0), (1, 1))), Polygon(((0, 1), (0, 0), (1, 0))), Polygon(((100, 100), (101, 100), (101, 101)))]
>>> s = STRtree(polys)
>>> query_geom = Polygon([(-1, -1), (2, 0), (2, 2), (-1, 2)])
>>> result = s.query(query_geom)
>>> polys[0] in result
True
person Phil    schedule 29.03.2017
comment
Это так полезно. Вы знаете, можно ли сериализовать STRtree с помощью библиотек pickle или marshall, чтобы сохранить его для дальнейшего использования? - person eguaio; 31.08.2017
comment
Нет, я не знаком с возможностями сериализации STRtree. Я считаю, что это полностью зависит от сериализации _tree_handle, возвращаемой shapely.geos.GEOSSTRtree_create(max(2, len(geoms))) - person Phil; 16.09.2017