48

我有大量的多边形(~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 分钟以上,具体取决于相交网格单元的数量),这是不可接受的。不幸的是,我不知道如何为多边形相交编写代码以获得重叠区域。你有什么建议吗?有没有比匀称的替代品?

4

2 回答 2

74

考虑使用Rtree来帮助识别多边形可能与哪些网格单元相交。这样,您可以删除与纬度/经度数组一起使用的 for 循环,这可能是较慢的部分。

像这样构造你的代码:

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)
于 2013-02-11T00:37:55.253 回答
27

自 2013/2014 年以来,Shapely 拥有 STRtree。我用过它,它似乎运作良好。

这是文档字符串中的一个片段:

STRtree 是使用 Sort-Tile-Recursive 算法创建的 R-tree。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
于 2017-03-29T22:54:47.413 回答