在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")
)
提前致谢!
答案 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。