sf::st_intersection未捕获全部交点问题求助
解决sf折线与线串交点缺失问题
核心原因
你遇到的交点缺失,大概率是两个问题导致:
- 浮点精度误差:
st_nearest_points生成的折线端点,和Riv的坐标存在极细微的数值偏差,导致st_intersection的拓扑检测认为二者不相交。 - 零长度折线:如果原始点集
ori中的某些点本身就在Riv上,st_nearest_points会生成零长度的折线,这类线的拓扑结构特殊,st_intersection不会返回有效交点。
最优解决方案:直接提取交点(无需求交)
因为x是通过st_nearest_points(Riv, ori)生成的,每条折线的其中一个端点就是ori点到Riv的最近点(即你要的交点),完全不用调用st_intersection,直接提取即可:
# 提取每条折线中属于Riv的端点(st_nearest_points(a,b)的起点来自a,终点来自b) intersection_points <- st_cast(x, "POINT") %>% slice(seq(1, nrow(.), by = 2)) %>% # 每两个点取第一个(对应Riv上的点) st_sf()
如果你的st_nearest_points调用顺序是st_nearest_points(ori, Riv),就把slice的参数改成seq(2, nrow(.), by = 2),取第二个点
备选方案:修复精度后求交
如果一定要用st_intersection,可以通过以下方式处理精度问题:
方式1:对齐折线端点到Riv
用st_snap将x的端点对齐到Riv的拓扑结构上,消除精度误差:
# tolerance根据坐标系统单位调整(米单位用1e-8,经纬度用1e-10) x_snapped <- st_snap(x, Riv, tolerance = 1e-8) all_intersections <- st_intersection(x_snapped, Riv)
方式2:给Riv做微小缓冲
对Riv做极小的缓冲,让精度偏差的折线能被检测到相交:
# 缓冲距离同样根据坐标单位调整 riv_buffered <- st_buffer(Riv, dist = 1e-8) all_intersections <- st_intersection(x, riv_buffered) %>% st_cast("POINT") # 将面线交的结果转为点
处理零长度折线
如果存在零长度折线(即ori点本身在Riv上),需要单独提取这些点并合并结果:
# 筛选零长度折线(阈值根据坐标单位调整) zero_length_mask <- st_length(x) < 1e-12 # 提取零长度折线对应的ori点(已在Riv上) zero_points <- ori[zero_length_mask, ] # 处理非零长度折线的交点 non_zero_intersections <- st_intersection(x[!zero_length_mask, ], Riv) # 合并所有交点 all_intersection_points <- rbind(non_zero_intersections, zero_points)
内容的提问来源于stack exchange,提问作者C. Guff
相关产品推荐
相关产品推荐

