没有主键的路网,怎么对比质检:空间漏斗与字段角色

十字路口不是「单独数据」;判定字段别被路面宽度带偏

路网质检里有一类需求特别折磨人:待核的国道、省道、县道、乡道、村道等 Shapefile,要和库里的公路基准层逐条对照——看空间是否大致重合,路名、技术等级等属性是否对得上。难处不在「会不会算相交」,而在于:两侧通常没有可靠的唯一主键,无法先按 ID 对齐再比属性。

如果强行「最近线配对」或「缓冲区里随便抓一条」,十字路口、平行辅路、一分多段的打断方式都会把报告搅乱。我在路网对比质检方案里,把目标定成一台智能分拣机:绝对不改原数据;把一致、相似、冲突、真正单独存在的要素分开;每条结论带上重合度与人话原因,交给人工决策。

说明:本文讲方法与边界,不绑定某次项目的具体图层名与阈值终值;默认数字(如重合度 60%)均可配置,换测区应重标定。

流程一览

阶段做什么挡住什么
0. CRS 前置校验两侧同投影且为米制「5 米缓冲」在经纬度下算错
1. 空间初筛索引取候选全量两两计算
2. 候选分组连通分量聚碎片1:N / N:1 路段打断
3. 重合度组级双向覆盖十字路口伪匹配
4. 属性复核字段左右对照次要字段污染总判定
5. 守恒自检ID / 长度盘点算法漏要素

一、没有主键时,空间只能做「候选」,不能直接当答案

有主键时,质检是「先对齐、再比字段」。无主键时,空间关系只能回答:谁有可能是同一条路上的对象。答案必须允许一对多——同一条物理道路在两侧被打断的位置往往不同。

因此漏斗的第一层不是「配对成功/失败」,而是:

  1. 为基准层建空间索引,给每条待核要素取邻域候选;
  2. 以邻近关系建图,做连通分量,把可能同属一条路的碎片收进同一组;
  3. 在组内先把基准候选线段合并,再与待核线段算相交与覆盖,并同时看两个方向的覆盖率(待核→基准、基准→待核)。

「两个方向都要达标」还是「任一方向达标即可」,做成配置。测区道路密度、数字化习惯不同,同一套阈值很难通吃。

二、十字路口:重合度低,但不是「单独数据」

业务上常把「单独」理解成「对面库里没有这条路」。若把十字路口误判成单独,报告会暗示大规模数据缺失,引发错误返工。

更干净的边界是:

情形含义输出
另一侧完全找不到可参与比对的候选真正的单侧存在「单独测试层 / 单独基准层」
有候选,但重合度不够(如十字相交)空间上不该当成同一条路「排除 / 不匹配」,不算单独
重合度够,进入属性阶段可能是同一条路一致 / 相似 / 冲突表

工程上可用两道阈值(均可配):

  • 剔除线(例如 < 15%):典型十字路口,直接不匹配;
  • 放行线(例如 > 60%):并行或大致重合的路段,进入属性复核。

中间灰区如何处理,要在项目里写死,避免同一测区两次跑出不同哲学。

三、属性复核:判定字段 vs 参考字段

空间放行之后,若要求「所有勾选字段全部一致才算一致」,报告会立刻被路面宽度、车道数这类本身带统计口径误差的字段淹没。大量本该进「完全一致」的记录掉进「冲突」,冲突表失去重点。

做法是给每个对照字段两个角色:

  • 判定字段:决定这条记录进「完全一致 / 相似 / 冲突」哪一类。默认往往只勾路名等核心字段。
  • 参考字段:同样输出双方取值与是否一致,但不参与总分档,只供复核时眼看。

字段对应关系不要写死在代码里。加载两侧图层时读取字段结构,按同名预填左右对照,业务人员再改:

  • 左字段 / 右字段
  • 是否启用
  • 比对方式:精确 / 模糊 / 编码枚举 / 数值容差
  • 阈值或容差
  • 报告里的中文显示名
  • 是否计入总体判定

编码类字段(技术等级、路面类型等)优先按编码比,再用字典翻译成人话写进「判定原因」。国道到村道若共用字段结构,字典可全局一份,必要时再按数据源覆盖。

文本模糊匹配也要有细则:完全相等;包含与相似;一方空一方有 → 不一致;双方空 → 可视为一致;空间高度重合但判定字段截然相反 → 标成严重冲突(例如提示「疑似立体交通或错位挂接」),而不是静默算相似。

四、CRS:宁可拦截,不要偷偷重投影

「缓冲区 5 米」「重合度百分之几」都默认长度单位是米。若两侧是地理坐标系(度),或两侧 EPSG 不一致,数值会系统性错,却仍可能跑出漂亮报表。

更稳妥的产品策略是:质检前强制校验,不自动重投影。

校验至少包括:

  1. 两侧 CRS 都已定义;
  2. 两侧完全一致;
  3. 是投影坐标系(米制),不是经纬度。

不通过就明确提示检测到的 CRS,请业务人员在专业 GIS 软件里投影后再来。重投影涉及基准面与带号,藏在质检按钮后面「顺手转一下」,出了错很难追责,也不利于培养作业纪律。

若实现阶段曾为方便做过内存重投影,必须在文档里写清:这是开发便利还是交付承诺;对外口径与对内实现不一致,是质检类工具最常见的信任危机来源之一。

五、输出要白盒,还要守恒

Excel 分拣

一张综合表通常至少包含:

表内容
汇总 Dashboard数量、里程、守恒校验
完全一致空间达标且判定字段一致(或双方空)
属性相似空间达标,文本类判定字段为包含/相似
属性冲突空间达标但判定字段冲突——重点人工核查

每条记录列出双方启用字段的取值,并附上空间重合度、判定结果、判定原因。原因只基于判定字段生成;编码用字典译成人话。

空间上的「单独」

  • 单独测试层:待核侧找不到任何可参与比对的基准候选;
  • 单独基准层:基准侧找不到任何可参与比对的测试候选。

与「有候选但重合度不达标」严格分开落盘,避免和真正的数据缺失混为一谈。

数据守恒自检

分组与分拣之后做盘点:

  • 测试层要素总数 ≈ 各结果表中出现的唯一 ID + 单独测试层要素数;
  • 基准层同理;
  • 必要时再加物理长度守恒。

对不上,说明某类边界被漏掉了。这是算法的自检,不是给甲方看的装饰行。

六、技术选型上的取舍

这一类批处理,全流程 Python(矢量运算 + 报表 + 可打包成免安装程序)通常足够。不必为了「像其它桌面产品」再套一层仅负责调进程的外壳——除非组织统一规定桌面技术栈。

真正要守住的是配置驱动:路径、阈值、字段对照、字典全部可改可保存,禁止把某次测区的字段名写进主程序。

可带走的原则

  1. 无主键时,空间产出候选与分组,不直接宣布身份。
  2. 「单独」= 对面没有任何可比对象;十字路口是排除项。
  3. 判定字段少而硬,参考字段多而软。 宽度类误差不要污染总分类。
  4. CRS 前置拦截优于静默重投影。
  5. 报告必须白盒:重合度 + 原因 + 双方取值。
  6. 用 ID/长度守恒检查自己有没有把要素吃掉。

路网只是「无主键空间匹配」最典型的行业例子。管线、田坎、林班界,只要两侧编码体系对不齐,往往还是同一套漏斗:候选 → 分组 → 重合门槛 → 少数字段做判决 → 其余字段做呈堂证供。