如何用Python合并近乎接触的多边形?
Python合并近邻多边形(保留原始顶点)
核心需求
- 消除多边形间距离小于阈值T的间隙
- 严格保留原始多边形的顶点,禁止使用缓冲原始多边形再取并集的方案
- 可借助开源第三方地理空间库实现
可行方案
方案一:基于Shapely+GeoPandas的自定义实现
通过检测近邻多边形对,构造仅填补间隙的“桥”多边形,再合并原始多边形与桥,既保留原始顶点又消除间隙。
步骤拆解
- 近邻多边形检测:遍历所有多边形对,计算两两最小距离,筛选出距离小于T的目标对
- 构造间隙填充桥:找到每对近邻多边形的最近点/边,生成刚好覆盖间隙的桥多边形(不触碰原始多边形的非边缘顶点)
- 合并多边形与桥:将原始多边形和对应的桥合并,得到无间隙的聚合结果
代码示例
import geopandas as gpd from shapely.geometry import Polygon, LineString from shapely.ops import unary_union def create_gap_bridge(poly1, poly2, threshold): # 获取两个多边形的最近点 proj1 = poly1.exterior.project(poly2.centroid) point1 = poly1.exterior.interpolate(proj1) proj2 = poly2.exterior.project(poly1.centroid) point2 = poly2.exterior.interpolate(proj2) # 生成连接两点的线,缓冲后得到填充间隙的桥 connect_line = LineString([point1, point2]) # 缓冲宽度取阈值的一半,确保刚好覆盖间隙;平端缓冲避免超出原始多边形范围 bridge = connect_line.buffer(threshold/2, cap_style=3) # 裁剪桥,仅保留两个多边形之间的区域 bridge = bridge.intersection(poly1.union(poly2).buffer(threshold)) return bridge # 假设polygons是待处理的Polygon对象列表,T为距离阈值 T = 10 gdf = gpd.GeoDataFrame(geometry=polygons) # 检测所有距离小于T的多边形对 near_pairs = [] for i in range(len(gdf)): for j in range(i+1, len(gdf)): if gdf.geometry.iloc[i].distance(gdf.geometry.iloc[j]) < T: near_pairs.append((i, j)) # 合并近邻多边形与桥 merged_geometries = [] processed_indices = set() for i, j in near_pairs: if i not in processed_indices and j not in processed_indices: poly_a = gdf.geometry.iloc[i] poly_b = gdf.geometry.iloc[j] gap_bridge = create_gap_bridge(poly_a, poly_b, T) merged_poly = unary_union([poly_a, poly_b, gap_bridge]) merged_geometries.append(merged_poly) processed_indices.update([i, j]) # 添加未参与合并的独立多边形 for idx in range(len(gdf)): if idx not in processed_indices: merged_geometries.append(gdf.geometry.iloc[idx]) # 最终结果GeoDataFrame final_result = gpd.GeoDataFrame(geometry=merged_geometries)
方案二:利用开源空间聚合库
部分开源地理空间库提供了类似ArcGIS聚合的功能,例如:
- PySAL:可通过空间权重矩阵识别近邻多边形,结合自定义聚合逻辑实现间隙填充
- GDAL/OGR:使用OGR的几何处理API,通过近邻检测与几何合并实现需求
这类库的优势是封装了更高效的空间算法,适合处理大规模多边形数据。
关键注意点
- 构造桥多边形时,需确保仅填充间隙,避免过度扩展覆盖原始多边形的有效区域
- 处理复杂多边形(如凹多边形)时,需优化最近点/边的检测逻辑,避免生成无效的桥
内容的提问来源于stack exchange,提问作者anttikoo
相关产品推荐
相关产品推荐

