从多边形列表中减去内环
Substracting inner rings from a list of polygons
我有一大堆多边形 (>10^6),其中大部分是不相交的,但其中一些多边形是另一个多边形的洞(~10^3 例)。这里有一张图片来解释这个问题,较小的多边形是较大多边形中的一个洞,但两者都是多边形列表中的独立多边形。
现在我想有效地确定哪些多边形是洞并减去洞,即减去完全位于另一个多边形内部的较小多边形和 return "cleaned" 多边形列表。一对孔和父多边形应该像这样转换(所以基本上是从父多边形中减去孔):
在 Whosebug 和 gis.stackexchange.com 上有很多类似的问题,但我还没有找到真正解决这个问题的问题。以下是一些相关问题:
1. 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))
输出如下所示:
现在如何创建新的多边形列表并移除孔洞。 Shapely 提供了从一个多边形中减去另一个多边形的功能(difference) but is there a similar function for lists of polygons (maybe something like unary_union 但重叠被移除)?或者如何有效地确定哪些是孔然后从较大的多边形中减去它们?
你的问题是你不知道哪些是 "holes",对吧?要"efficiently determine which polygons are holes",你可以使用一个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))
我有一大堆多边形 (>10^6),其中大部分是不相交的,但其中一些多边形是另一个多边形的洞(~10^3 例)。这里有一张图片来解释这个问题,较小的多边形是较大多边形中的一个洞,但两者都是多边形列表中的独立多边形。
现在我想有效地确定哪些多边形是洞并减去洞,即减去完全位于另一个多边形内部的较小多边形和 return "cleaned" 多边形列表。一对孔和父多边形应该像这样转换(所以基本上是从父多边形中减去孔):
在 Whosebug 和 gis.stackexchange.com 上有很多类似的问题,但我还没有找到真正解决这个问题的问题。以下是一些相关问题: 1. 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))
输出如下所示:
现在如何创建新的多边形列表并移除孔洞。 Shapely 提供了从一个多边形中减去另一个多边形的功能(difference) but is there a similar function for lists of polygons (maybe something like unary_union 但重叠被移除)?或者如何有效地确定哪些是孔然后从较大的多边形中减去它们?
你的问题是你不知道哪些是 "holes",对吧?要"efficiently determine which polygons are holes",你可以使用一个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))