R / GIS:找到位置和最近线之间的正交距离

时间:2012-03-20 04:19:37

标签: r gis

我试图找到一组位置坐标和一组线(道路或河流)之间的正交距离。点集以纬度/经度对的形式出现,并且行在shapefile(.shp)中。使用maptoolsPBSmapping在地图上绘制它们不是问题。但我的基本问题是找到从一个地方到达道路或河流的最小距离。在R中有没有办法做到这一点?

3 个答案:

答案 0 :(得分:21)

如果我理解正确,您可以使用gDistance包中的rgeos完成此操作。

将行读作SpatialLines/DataFrame并指向SpatialPoints/DataFrame,然后循环遍历计算距离的每个点:

require(rgeos)
## untested code
shortest.dists <- numeric(nrow(sp.pts))
for (i in seq_len(nrow(sp.pts)) {
    shortest.dists[i] <- gDistance(sp.pts[i,], sp.lns)
}

此处sp.pts是空间点对象,sp.lns是空间线对象。

您必须循环,以便仅将sp.pts中的单个坐标与sp.lns中所有线几何的全部进行比较,否则您将获得所有点上的聚合值的距离。

由于您的数据是纬度/经度,因此您应该将线和点转换为合适的投影,因为gDistance函数采用笛卡尔距离。

更多讨论和示例(编辑)

在线上得到最近的点而不仅仅是距离会很简洁,但是这会打开另一个选项,即你是否需要沿着一条直线的最近的坐标,或者实际的交点,其线段比任何现有顶点都更近。如果您的顶点足够密集以至于差异无关紧要,那么请在spDistsN1包中使用sp。你必须从集合中的每一行中提取所有坐标(不是很难,但有点难看),然后遍历每个感兴趣点计算到行顶点的距离 - 然后你可以找到哪个是最短的并选择从顶点集合坐标,这样您就可以轻松获得距离和坐标。由于函数可以使用longlat = TRUE参数的椭圆距离,因此无需投影。

library(maptools)

## simple global data set, which we coerce to Lines
data(wrld_simpl)

wrld_lines <- as(wrld_simpl, "SpatialLinesDataFrame")

## get every coordinate as a simple matrix (scary but quick)
wrld_coords <- do.call("rbind", lapply(wrld_lines@lines, function(x1) do.call("rbind", lapply(x1@Lines, function(x2) x2@coords[-nrow(x2@coords), ]))))

以交互方式进行检查,您必须对其进行修改以节省坐标或最小距离。这将绘制线条并等待您单击绘图中的任何位置,然后它将从您的单击绘制一条线到最近的顶点

## no out of bounds clicking . . .
par(mar = c(0, 0, 0, 0), xaxs = "i", yaxs = "i") 

plot(wrld_lines, asp = "")

n <- 5

for (i in seq_len(n)) {
xy <- matrix(unlist(locator(1)), ncol = 2)
    all.dists <- spDistsN1(wrld_coords, xy, longlat = TRUE)
    min.index <- which.min(all.dists)
    points(xy, pch = "X")
lines(rbind(xy, wrld_coords[min.index, , drop = FALSE]), col = "green", lwd = 2)
}

答案 1 :(得分:3)

geosphere包具有dist2line函数,可以为lon / lat数据执行此操作。它可以使用Spatial *对象或矩阵。

line <- rbind(c(-180,-20), c(-150,-10), c(-140,55), c(10, 0), c(-140,-60))
pnts <- rbind(c(-170,0), c(-75,0), c(-70,-10), c(-80,20), c(-100,-50), 
         c(-100,-60), c(-100,-40), c(-100,-20), c(-100,-10), c(-100,0))
d <- dist2Line(pnts, line)
d 

结果说明

plot( makeLine(line), type='l')
points(line)
points(pnts, col='blue', pch=20)
points(d[,2], d[,3], col='red', pch='x')
for (i in 1:nrow(d)) lines(gcIntermediate(pnts[i,], d[i,2:3], 10), lwd=2)

答案 2 :(得分:0)

看起来可以使用sf函数在st_distance包中完成。

您将两个sf对象传递给该函数。与其他解决方案相同的问题在于,您需要遍历各个点,以便该函数计算道路上每个点到每个点之间的距离。然后,以最小的结果向量为最短距离。

# Solution for one point
min(st_distance(roads_sf, points_sf[1, ]))

# Iterate over all points using sapply
sapply(1:nrow(points_sf), function(x) min(st_distance(roads_sf, points_sf[x, ])))