代码之家  ›  专栏  ›  技术社区  ›  KarateKid

从多边形列表中减去内环

  •  0
  • KarateKid  · 技术社区  · 5 年前

    我有一个很大的多边形列表(>10^6),其中大多数是不相交的,但其中一些多边形是另一个多边形的孔(~10^3种情况)。在这里一幅图片来解释这个问题,较小的多边形是较大多边形中的一个洞,但两者都是多边形列表中独立的多边形。 A large polygon with smaller polygon on the inside.

    现在,我想有效地确定哪些多边形是洞,并减去洞,即减去完全位于另一个多边形内部的较小多边形,并返回一个“清理”多边形列表。一对孔和父多边形应该这样转换(所以基本上从父多边形中减去孔): enter image description here

    Stackoverflow和gis.stackexchange.com上有很多类似的问题,但我还没有找到一个真正解决这些问题的方法。以下是一些相关问题: https://gis.stackexchange.com/questions/5405/using-shapely-translating-between-polygons-and-multipolygons 2。 https://gis.stackexchange.com/questions/319546/converting-list-of-polygons-to-multipolygon-using-shapely

    这是一个示例代码。

    from shapely.geometry import Point
    from shapely.geometry import MultiPolygon
    from shapely.ops import unary_union
    import numpy as np
    
    #Generate a list of polygons, where some are holes in others; 
    def generateRandomPolygons(polygonCount = 100, areaDimension = 1000, holeProbability = 0.5):
        pl = []
        radiusLarge = 2 #In the real dataset the size of polygons can vary
        radiusSmall = 1 #Size of holes can also vary
    
        for i in range(polygonCount):
            x, y = np.random.randint(0,areaDimension,(2))
            rn1 = np.random.random(1)
            pl.append(Point(x, y).buffer(radiusLarge))
            if rn1 < holeProbability: #With a holeProbability add a hole in the large polygon that was just added to the list
                pl.append(Point(x, y).buffer(radiusSmall))
        return pl
    
    polygons = generateRandomPolygons()
    print(len(pl))
    

    输出如下: enter image description here

    difference )但是对于多边形列表是否有类似的功能(可能类似于 unary_union 但重叠部分在哪里被移除?另一种方法是如何有效地确定哪些是孔,然后从较大的多边形中减去它们?

    0 回复  |  直到 5 年前
        1
  •  6
  •   mikewatt    5 年前

    你的问题是你不知道哪些是“洞”,对吧?要“有效地确定哪些多边形是孔”,可以使用 rtree 要加速交叉口检查:

    from rtree.index import Index
    
    # create an rtree for efficient spatial queries
    rtree = Index((i, p.bounds, None) for i, p in enumerate(polygons))
    donuts = []
    
    for i, this_poly in enumerate(polygons):
        # loop over indices of approximately intersecting polygons
        for j in rtree.intersection(this_poly.bounds):
            # ignore the intersection of this polygon with itself
            if i == j:
                continue
            other_poly = polygons[j]
            # ensure the polygon fully contains our match
            if this_poly.contains(other_poly):
                donut = this_poly.difference(other_poly)
                donuts.append(donut)
                break  # quit searching
    
    print(len(donuts))