使用PostGIS的ST_Intersection函数获取错误结果的技术求助
你遇到的这个问题很典型——PostGIS和ArcGIS在空间相交计算上的行为差异,核心原因通常是拓扑精度阈值的默认设置不同,或者浮点精度导致的细微拓扑偏差。下面是一步步的排查和解决方法:
1. 先确认空间参考完全一致
首先检查两张表的几何字段SRID是否完全匹配,执行:
SELECT ST_SRID(wkb_geometry) FROM public.mountainbike_pavement_temp2 LIMIT 1; SELECT ST_SRID(wkb_geometry) FROM public.mountainbike_strecken_temp2 LIMIT 1;
如果SRID不同,PostGIS自动投影时可能引入精度误差,而ArcGIS的投影处理逻辑更“宽松”,这会导致结果差异。
2. 用ST_Snap添加容差后再做相交
ArcGIS默认会用一个小容差来处理“理论上相交但实际浮点精度导致不重合”的情况,但PostGIS的ST_Intersection是严格精确匹配的。你可以先把其中一个图层的要素对齐到另一个,再计算相交:
SELECT ST_Intersection(ST_Snap(t2.wkb_geometry, t1.wkb_geometry, 0.01), t1.wkb_geometry), t2.sde_id as s_sde, t2.mtb_id, ST_Length(ST_Intersection(ST_Snap(t2.wkb_geometry, t1.wkb_geometry, 0.01), t1.wkb_geometry)) FROM public.mountainbike_pavement_temp2 t1 INNER JOIN public.mountainbike_strecken_temp2 t2 ON t1.wkb_geometry && t2.wkb_geometry;
这里的0.01是容差(单位和你的SRID一致,看起来是米,0.01米足够覆盖细微的顶点偏移),这个方法应该能直接补上缺失的7米——因为ArcGIS就是自动做了类似的对齐操作。
3. 验证顶点是否真的落在目标要素上
你用ST_Distance得到首个顶点到线的距离为0,但可以进一步验证顶点是否被目标要素包含:
SELECT t2.mtb_id, ST_Contains(t1.wkb_geometry, ST_StartPoint(t2.wkb_geometry)) AS start_point_contains, ST_Distance(t1.wkb_geometry, ST_StartPoint(t2.wkb_geometry)) AS exact_distance FROM public.mountainbike_pavement_temp2 t1 INNER JOIN public.mountainbike_strecken_temp2 t2 ON t1.wkb_geometry && t2.wkb_geometry;
有时候ST_Distance返回0是浮点精度的近似值,实际上顶点并没有完全落在要素上,只是距离极小,这就会导致ST_Intersection漏掉这段。
4. 尝试用ST_SharedPaths处理线对线相交
如果你的两个图层都是线要素,ST_SharedPaths专门用于提取两条线的重叠路径,比ST_Intersection更适合线对线的场景:
SELECT (ST_SharedPaths(t1.wkb_geometry, t2.wkb_geometry)).geom AS shared_path, t2.sde_id as s_sde, t2.mtb_id, ST_Length((ST_SharedPaths(t1.wkb_geometry, t2.wkb_geometry)).geom) FROM public.mountainbike_pavement_temp2 t1 INNER JOIN public.mountainbike_strecken_temp2 t2 ON t1.wkb_geometry && t2.wkb_geometry;
这个函数会返回两条线的公共部分,对于线要素的重叠计算精度更高。
先从添加容差的ST_Snap方法开始尝试,这是解决这类跨平台空间计算差异最快速的办法。如果还是不行,再检查数据导入时的精度损失(比如是否丢失了顶点小数位)。
内容的提问来源于stack exchange,提问作者user7882389

