为何gdistance::shortestPath未生成直线?常数成本下最小成本路径计算异常排查
修正gdistance最短路径计算的问题,得到预期直线路径
我来帮你分析代码里的问题,以及如何调整来得到常数成本下的直线最短路径:
核心错误点
过渡函数逻辑不符合需求
你写的speed <- function(x){1/(x[2]+x[1])}并不是真正的"常数通行成本"逻辑。在gdistance的transition函数中,transitionFunction的输入x是当前单元格和相邻单元格的成本值组成的向量。当所有单元格值为1时,这个函数会返回0.5,让所有方向(水平/垂直/对角线)的移动成本完全一致,但实际上对角线移动的距离是水平/垂直的√2倍,若成本为常数,移动成本应该和距离成正比,而非固定值。重复地理校正+冗余代码
你已经对trraster执行了geoCorrection(trraster, scl=FALSE),后续又复制过渡矩阵并再次执行geoCorrection(speed, scl=FALSE),这会让过渡矩阵的权重被错误地二次校正,破坏了原本的距离关系。另外,adj <- adjacent(...)到speed[adj] <-trraster[adj]这段代码完全没用,属于冗余操作,还增加了出错概率。
修正后的代码
如果要模拟"所有单元格通行成本为常数"的场景,我们需要让移动成本和实际地理距离挂钩(此时总成本等价于总距离,最短路径就是直线)。修正后的代码如下:
library(gdistance) # 创建栅格,所有单元格赋值为1(代表常数通行成本) raster <- raster(ymn = 35.6, ymx = 35.76, xmx = 139.9, xmn = 139.6, res = 0.001) raster[] <- 1 # 创建过渡矩阵:用function(x)1表示基础成本为1,directions=8开启8方向移动 trraster <- transition(raster, transitionFunction = function(x) 1, directions = 8) # 地理校正:将过渡权重调整为实际地理距离,scl=FALSE表示不缩放权重 trraster <- geoCorrection(trraster, scl = FALSE) # 定义起点和终点(坐标顺序为lon, lat) origin <- c(139.7761, 35.7136) goal <- c(139.7582, 35.66639) # 计算最短路径 path <- shortestPath(trraster, origin, goal, output = "SpatialLines") # 可视化结果 plot(raster(trraster)) lines(path, col = "darkred", lwd = 2)
代码说明
- 过渡函数:
function(x)1设定每个单元格的基础通行成本为1,后续geoCorrection会自动根据单元格间的距离(水平/垂直是单元格分辨率,对角线是√2倍分辨率)调整过渡权重,保证成本与距离成正比。 - 单次地理校正:只执行一次
geoCorrection,确保权重准确反映真实的移动成本差异。 - 移除冗余代码:删掉了无意义的过渡矩阵复制和相邻单元格操作,简化代码逻辑。
运行这段代码后,你就能得到预期的直线最短路径了,因为此时路径的总成本等价于总地理距离,最短路径就是欧几里得直线。
内容的提问来源于stack exchange,提问作者junichiyamasaki
相关产品推荐
相关产品推荐

