使用R语言OSM数据与geosphere的distm()计算两点距离结果不准确
问题原因与解决方案
1. 核心问题:坐标顺序完全颠倒
geosphere包的distGeo(以及所有基于WGS84的距离函数)要求输入坐标格式为**(经度, 纬度)**,但你的代码存在两处坐标顺序错误:
- 定义兴趣点
p68时,写成了(纬度, 经度); - 提取车站坐标时,将sf对象默认的
(经度, 纬度)格式反转成了(纬度, 经度)。
这导致你计算的是两个错误位置的点之间的距离,自然和谷歌地图的实际直线距离差异巨大。以你的示例为例,正确坐标输入应为:
- 兴趣点:
(8.459728292754358, 49.49443499565662)(经, 纬) - 电车站:
(8.461322, 49.49353)(经, 纬)
用正确顺序调用distGeo(c(8.459728,49.49443), c(8.461322,49.49353)),结果约为152米,和谷歌地图一致。
2. 次要问题:电车站数据获取不准确
你通过route=tram查询的是有轨电车路线,其中的osm_points包含路线上所有节点(包括转弯点、轨道节点等),仅通过na.omit筛选有name的点,无法保证只获取电车站。正确做法是直接查询OSM中标记为有轨电车站的节点,使用railway=tram_stop标签。
修正后的代码
使用sf包的st_distance函数可更简洁地计算距离,自动处理坐标顺序和CRS,无需手动循环:
library(osmdata) library(sf) library(geosphere) # 定义城市 city = "Mannheim" # 定义兴趣点:注意顺序是(经度, 纬度),WGS84坐标系 p68 <- st_sfc(st_point(c(8.459728292754358, 49.49443499565662)), crs = 4326) # 直接查询曼海姆的有轨电车站 mannheim_tram_stops <- getbb(city) %>% opq() %>% add_osm_feature(key = 'railway', value = 'tram_stop') %>% osmdata_sf() # 提取电车站的sf对象,去除无名称的记录 tram_stops <- mannheim_tram_stops$osm_points %>% filter(!is.na(name)) %>% select(osm_id, name, geometry) # 计算兴趣点到所有电车站的距离(自动使用WGS84大圆距离) distances <- st_distance(p68, tram_stops$geometry) # 获取最短距离(单位:米) min_distance <- min(distances) print(min_distance)
补充说明
st_distance默认根据数据CRS选择距离计算方式,对于WGS84(EPSG:4326)会计算大圆距离,和谷歌地图直线距离逻辑一致;- 确保所有空间对象的CRS统一为WGS84,避免坐标系不匹配导致的误差;
- 直接查询
tram_stop能保证获取真正的电车站点,减少无效计算。
内容的提问来源于stack exchange,提问作者Lingo171
相关产品推荐
相关产品推荐

