如何从Shapely MultiPolygon对象中检测内多边形并避免填充?
检测并处理Shapely MultiPolygon中的内多边形(洞)
核心原理
Shapely的Polygon对象天然区分外边界(exterior)和内边界(interiors,即洞)——五大湖、黑海、里海这类区域本质是陆地多边形的“洞”。只要正确识别并传递这些边界给绘图库,就能实现洞区域不填充的效果。
解决步骤
- 遍历MultiPolygon中的每个子Polygon对象:通过
MultiPolygon.geoms属性获取所有子Polygon。 - 利用绘图库的自动填充规则:matplotlib/cartopy支持根据多边形环的缠绕方向自动识别洞,无需手动判断,只需将Polygon的完整边界(外+内)传入绘图函数。
- Shapefile适配:用
geopandas读取Shapefile时,会自动将带洞的多边形解析为包含interiors的Shapely Polygon对象,后续处理逻辑完全一致。
修改后的测试脚本
import matplotlib.pyplot as plt import cartopy.crs as ccrs from shapely import geometry import random import pickle ! wget -nc https://thredds-su.ipsl.fr/thredds/fileServer/ipsl_thredds/brocksce/tmp/polys.pickle with open('./polys.pickle', "rb") as poly_file: polygons = pickle.load(poly_file) fig = plt.figure(figsize=(10,5)) ax = fig.add_subplot(1, 1, 1, projection=ccrs.Robinson(10)) transform = ccrs.Geodetic() for polygon in polygons.geoms: random_color = "#"+''.join([random.choice('0123456789ABCDEF') for i in range(6)]) # 推荐方式:用cartopy原生方法自动处理洞 ax.add_geometries([polygon], crs=transform, facecolor=random_color, edgecolor="black", lw=0.5) # 手动处理方式(适合细粒度控制) # coords = list(polygon.exterior.coords) # for interior in polygon.interiors: # coords.extend(list(interior.coords)) # ax.fill(*zip(*coords), transform=transform, color=random_color, lw=0.5, edgecolor="black") ax.set_global() ax.gridlines() plt.show()
关键说明
ax.add_geometries是最优方案:cartopy原生支持Shapely几何对象,会自动识别Polygon的interiors作为洞,填充时自动挖空这些区域。- 手动处理逻辑:若需更精细控制,可依次传入外边界和所有内边界的坐标,matplotlib默认的非零环绕数规则会自动区分填充区域和洞。
- Shapefile读取:使用
geopandas.read_file()读取Shapefile后,GeoDataFrame的geometry列会自动生成带正确内外边界的Shapely对象,直接套用上述绘制逻辑即可。
内容的提问来源于stack exchange,提问作者PBrockmann
相关产品推荐
相关产品推荐

