GeoPandas中如何筛选与MultiLineString共享1/2/3条边的多边形?
解决思路
核心思路是拆解三角形的边,逐一匹配后统计数量——直接用GeoPandas的高层空间关系方法无法精准统计共享边的条数,具体步骤如下:
提取每个三角形的所有边
每个三角形(Polygon)的边界是LinearRing,我们可以把它拆成3条独立的LineString,同时保留每条边所属的原多边形索引,方便后续统计:from shapely.geometry import LineString def extract_triangle_edges(row): # 获取多边形的边界坐标(排除最后一个重复的闭合点) coords = list(row.geometry.exterior.coords)[:-1] edges = [] for i in range(3): start = coords[i] end = coords[(i+1)%3] # 标准化边的坐标顺序,避免因方向不同导致匹配失败 if start > end: start, end = end, start edges.append(LineString([start, end])) # 返回原多边形索引与对应边的组合 return [(row.name, edge) for edge in edges] # 提取所有边并转为GeoDataFrame all_edges = [] for idx, row in poly.iterrows(): all_edges.extend(extract_triangle_edges(row)) edges_gdf = gpd.GeoDataFrame(all_edges, columns=['poly_id', 'geometry'], crs=poly.crs)判断每条边是否属于目标MultiLineString
先把lines合并为一个单一的MultiLineString,再检查每条边是否是这个集合的一部分。考虑到浮点数精度问题,可给边做微小缓冲后判断交集:# 合并所有lines为一个整体几何对象 lines_union = lines.geometry.unary_union # 用缓冲解决精度误差,判断边是否与目标线集相交 edges_gdf['is_shared'] = edges_gdf.geometry.apply( lambda x: x.buffer(1e-8).intersects(lines_union) )统计每个三角形的共享边数量
按原多边形ID分组,统计匹配成功的边数:# 统计每个多边形的共享边条数 edge_counts = edges_gdf.groupby('poly_id')['is_shared'].sum() # 将统计结果关联回原多边形GeoDataFrame poly['shared_edge_count'] = poly.index.map(edge_counts)生成三个布尔掩码
根据统计的边数直接生成掩码:mask_1 = poly['shared_edge_count'] == 1 mask_2 = poly['shared_edge_count'] == 2 mask_3 = poly['shared_edge_count'] == 3
关键细节
- 坐标标准化:统一边的起点终点顺序,避免因边的方向相反导致匹配失败。
- 精度处理:地理数据的浮点数精度误差是常见问题,缓冲值可根据你的数据坐标单位(如米、度)调整。
内容的提问来源于stack exchange,提问作者Spatial Digger
相关产品推荐
相关产品推荐

