当前位置: 首页 > ops >正文

使用 Python 自动化检查矢量面数据的拓扑错误(含导出/删除选项)

在地理信息系统(GIS)数据处理中,矢量面数据的拓扑关系至关重要。如果拓扑错误没有及时发现和修复,可能会影响后续空间分析、建模与可视化效果。本文介绍如何使用 GeoPandas + Shapely 进行拓扑检查,并提供扩展功能(打印、导出、删除问题要素)。

一、拓扑错误常见类型

在多边形矢量数据中,常见的拓扑问题包括:

非法几何(Invalid Geometry)
多边形自相交或几何结构错误。

带洞要素(Polygons with Holes)
多边形内部包含空洞(通常需要视业务是否允许)。

极小面(Small Polygons)
面积过小的碎片,通常是误差或无意义的边角。

完全重复几何(Duplicate Geometries)
两个要素几何完全相同。

同层重叠(Self-Overlap / Overlap within Layer)
两个多边形在同一层里相互叠压。

二、Python 拓扑检查脚本

# -*- coding: utf-8 -*-
"""
矢量面数据拓扑检查与清洗
记得先把数据加上投影奥
- 检查项:非法几何、带洞、极小面、重复几何、同层重叠
- 可选操作:打印 / 导出 / 删除
"""import geopandas as gpd
from shapely.validation import explain_validity
from shapely.geometry import Polygon, MultiPolygon, box
import shapely
import os# ========= 基本参数 =========
SRC = r""
MIN_AREA_M2 = 10.0            # 极小面阈值(平方米)
FIX_INVALID_BEFORE = True     # 检查前修复非法几何
EXPORT_PROBLEMS = True        # 是否导出问题要素
DELETE_PROBLEMS = False       # 是否直接删除问题要素(谨慎使用)OUT_DIR = os.path.dirname(SRC)# ========= 读取数据 =========
gdf = gpd.read_file(SRC)
print(f"读取完成:{len(gdf)} 要素;原CRS = {gdf.crs}")if gdf.crs is None:gdf = gdf.set_crs(epsg=4326, allow_override=True)print("未检测到CRS,已强制设置 EPSG:4326")# ========= 构造米制副本 =========
try:utm_crs = gdf.estimate_utm_crs()gdf_m = gdf.to_crs(utm_crs)print(f"用于量测的米制CRS:{utm_crs}")
except Exception as e:print("UTM估算失败,仍使用原CRS:", e)gdf_m = gdf.copy()# ========= 几何修复函数 =========
def fix_geom(geom):if geom is None or geom.is_empty:return geomif not geom.is_valid:try:return shapely.make_valid(geom)except Exception:return geom.buffer(0)return geomif FIX_INVALID_BEFORE:gdf["geometry"] = gdf["geometry"].apply(fix_geom)gdf_m["geometry"] = gdf_m["geometry"].apply(fix_geom)# ========= 检查1:非法几何 =========
invalid_idx = [i for i, geom in gdf.geometry.items() if not geom.is_valid]# ========= 检查2:带洞要素 =========
def has_holes(geom):if isinstance(geom, Polygon):return len(geom.interiors) > 0if isinstance(geom, MultiPolygon):return any(len(p.interiors) > 0 for p in geom.geoms)return Falseholes_idx = [i for i, geom in gdf.geometry.items() if has_holes(geom)]# ========= 检查3:极小面 =========
small_idx = [i for i, geom in gdf_m.geometry.items() if geom.area < MIN_AREA_M2]# ========= 检查4:完全重复几何 =========
dup_idx = list(gdf.index[gdf.geometry.duplicated(keep=False)])# ========= 检查5:同层重叠 =========
print("\n[同层重叠] 正在扫描 ...")
overlap_pairs, overlap_ids = [], set()
sindex = gdf_m.sindexfor i, geom in enumerate(gdf_m.geometry):if geom.is_empty:continuecandidate_idx = sindex.query(box(*geom.bounds))for j in candidate_idx:if j <= i:continueg2 = gdf_m.geometry.iloc[j]inter = geom.intersection(g2)if not inter.is_empty and inter.area > 0:overlap_pairs.append((i, j, float(inter.area)))overlap_ids.update([i, j])# ========= 汇总 =========
print("\n—— 拓扑检查汇总 ——")
print(f"非法几何:{len(invalid_idx)}")
print(f"带洞要素:{len(holes_idx)}")
print(f"极小面(<{MIN_AREA_M2} m²):{len(small_idx)}")
print(f"完全重复几何:{len(dup_idx)}")
print(f"同层重叠:{len(overlap_pairs)} 对,涉及 {len(overlap_ids)} 个要素")# ========= 导出 / 删除选项 =========
problem_idx = sorted(set(invalid_idx + holes_idx + small_idx + dup_idx + list(overlap_ids)))if problem_idx:print(f"\n⚠️ 检测到 {len(problem_idx)} 个问题要素:{problem_idx[:20]}{' ...' if len(problem_idx)>20 else ''}")if EXPORT_PROBLEMS:out_path = os.path.join(OUT_DIR, "problems.shp")gdf.loc[problem_idx].to_file(out_path, encoding="utf-8")print(f"已导出问题要素到: {out_path}")if DELETE_PROBLEMS:gdf_clean = gdf.drop(problem_idx)out_clean = os.path.join(OUT_DIR, "cleaned.shp")gdf_clean.to_file(out_clean, encoding="utf-8")print(f"已删除问题要素,结果保存到: {out_clean}")
else:print("\n✅ 数据没有发现拓扑问题!")

三、功能说明

打印模式:直接在终端显示各类拓扑问题数量和索引。

导出模式(EXPORT_PROBLEMS=True):将有问题的要素保存到单独的 problems.shp 文件,方便在 ArcGIS / QGIS 中查看。

删除模式(DELETE_PROBLEMS=True):自动清洗数据,生成 cleaned.shp,但要谨慎使用。

http://www.xdnf.cn/news/19266.html

相关文章:

  • 算法题(196):最大异或对
  • 特殊符号在Html中的代码及常用标签格式的记录
  • Qt组件布局的经验
  • 线程池、锁策略
  • 机器视觉opencv教程(四):图像颜色识别与颜色替换
  • Linux中的ss命令
  • kotlin - 2个Activity实现平行视图,使用SplitPairFilter
  • 网络流量分析——使用Wireshark进行分析
  • Shell脚本编程——变量用法详解
  • Ruoyi-vue-plus-5.x第二篇MyBatis-Plus数据持久层技术:2.2 分页与性能优化
  • DAY17-新世纪DL(DeepLearning/深度学习)战士:Q(机器学习策略)2
  • AI 应用 图文 解说 (二) -- 百度智能云 ASR LIM TTS 语音AI助手源码
  • 自定义AXI_PWM_v1.0——ZYNQ学习笔记15
  • Spring Task快速上手
  • Maven学习笔记01
  • 【stm32】对射式红外传感器计次以及旋转编码器计次
  • SpringBoot 自研运行时 SQL 调用树,3 分钟定位慢 SQL!
  • 用产品经理的思维,重构AI时代的增长Playbook
  • 企业数据湖:从混沌到秩序的分层设计与治理策略
  • 11.1.5 实现文件删除,共享和共享下载排行榜
  • 分布式测试平台ITP:让自动化测试更高效、更稳定
  • SW - 用装配图的方式组合多个子零件然后转换成为零件,可维护性好
  • 组件通信终极指南:从Props Drilling到Context API
  • react-virtualized React 应用中高效渲染大型列表和表格数据的库
  • 扣子(coze)实践指南进阶篇——创建工作流,并将工作流接入智能体
  • 2025年8月个人工作生活总结
  • [Windows] 某音下载工具——自用
  • Selenium 等待机制:编写稳定可靠的自动化脚本
  • Kubernetes中kubeadm、kubectl、kubelet的区别与作用
  • 动态规划入门(三):一些经典动态规划模型