找到与R中另一个点最近点的直线上的坐标

时间:2016-01-22 15:16:39

标签: r coordinates gis spatial

在R中工作我有2个对象,一个SpatialLinesDataFrame(表示道路网络)和一个SpatialPointsDataFrame(表示对象位置)。我需要在最靠近每个对象位置的点的道路上输出坐标。

我可以从搜索中找到的是用其他语言(例如Python - How to find the closest point on a line segment to an arbitrary point?)执行此操作的方法,或者用于查找点和线之间的最小距离(例如,使用geosphere::dist2Line()或{{1 }})。我只想回到线上最近点的坐标。

编辑: 以下是我的道路网络的一小部分:

rgeos::gDistance()

和我的对象位置:

new("SpatialLinesDataFrame"
    , data = structure(list(ID = c(0, 0, 0, 0, 0, 0, 0),
                            ET_ID = c("4", "4", "4", "4", "4", "4", "4"),
                            length = c(0.280848, 0.812133, 0.0402004, 0.209611, 0.0433089, 0.501865, 0.363501)),
                       .Names = c("ID", "ET_ID", "length"),
                       row.names = c(980L, 982L, 983L, 984L, 987L, 988L, 989L),
                       class = "data.frame")
, lines = list(<S4 object of class structure("Lines", package = "sp")>, 
               <S4 object of class structure("Lines", package = "sp")>, 
               <S4 object of class structure("Lines", package = "sp")>, 
               <S4 object of class structure("Lines", package = "sp")>, 
               <S4 object of class structure("Lines", package = "sp")>, 
               <S4 object of class structure("Lines", package = "sp")>, 
               <S4 object of class structure("Lines", package = "sp")>)
, bbox = structure(c(433266.568837884, 547825.73420664, 437050.511867258, 548168.921069476),
                   .Dim = c(2L, 2L),
                   .Dimnames = list(c("x", "y"), c("min", "max")))
, proj4string = new("CRS", projargs = "+proj=utm +zone=37 +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")
)

提前致谢!

2 个答案:

答案 0 :(得分:2)

如果您不介意自己实现这一点,请从此伪代码移植......

Point snap_to_segment(Point point, Segment segment):
    Point s1 = segment.start;
    Point s2 = segment.end;

    Vector v = s2 - s1;
    Vector w = point - s1;

    double c1 = Vector.dot_product(w,v);
    double c2 = Vector.dot_product(v,v);

    Point snap;

    if c1 <= 0:
        snap = s1

    elif c2 <= c1:
        snap = s2

    else:
        snap = s1 + v * (c1 / c2)

    return snap

除此之外,当我决定使用Shapely时,我在Python上做得比上面的功能要好得多。事实证明:

  

rgeos是Python的Shapely的R对应物。 Shapely和rgeos都基于GEOS(即PostGIS引擎)(source

...但是,在Shapely中我找到了这样的理想点:

desiredPoint = road.distance(road.project(point));

rgeos似乎缺少linestring.project(point)linestring.distance(scalarValue)方法......

答案 1 :(得分:0)

对于那些可能需要它的人来说,这是一个快速破解Heltonbiker在R(2D版本)中的答案。当然更好的方法是使用一个库,但有时你不想要,如果你只需要在一条线上得到最近的点,那就可以了。

findClosestPtToSeg <- function( ptx,pty, sx0,sy0,sx1,sy1 ){

  sdx <- sx1-sx0
  sdy <- sy1-sy0
  wx <- ptx-sx0
  wy <- pty-sy0

  lambda <- (wx*sdx + wy*sdy) / (sdx*sdx + sdy*sdy)
  trunclamb <- min(max(lambda,0),1)

  rv <- list() # return the coordinates in a list
  rv$x <- sx0 + trunclamb*sdx
  rv$y <- sy0 + trunclamb*sdy
  return(rv)
}

以下是一些测试用例的输出:

> findClosestPtToSeg( 1,2, 0,0,1,1 )
$x
[1] 1
$y
[1] 1

> findClosestPtToSeg( -1,-2, 0,0,1,1 )
$x
[1] 0
$y
[1] 0

> findClosestPtToSeg( 0.5,0.6, 0,0,1,1 )
$x
[1] 0.55
$y
[1] 0.55

请注意,它不是漂亮的代码,它不会检查退化间隔并以不同的方式处理输入点(通过坐标传递)而不是返回值(打包在带有名称的列表中)。哦,这是一个快速的黑客,并为我工作得很好。

如果这有帮助,请确保heltonbiker得到任何upvotes。