在stplanr中向SpatialLinesNetwork添加新节点

时间:2017-12-01 17:12:38

标签: r network-programming geospatial stplanr

如何使用SpatialPointsDataFrameSpatialLinesNetwork添加新节点?

我的问题的上下文:我有一个总线路径的shapefile和另一个公交车站的shapefile。我想计算沿公交线路的站点之间的距离。理想情况下,每个停靠点都是一个节点,我会使用stplanr::sum_network_routes()来计算它们之间的距离。问题是,当我将总线路由转换为SpatialLinesNetwork时,网络中只有几个节点彼此相距很远并且与公交站点位置无关。

可重现的数据集:

# load library and data
  library(stplanr)
  data(routes_fast)

# convert SpatialLinesDataFrame into  SpatialLinesNetwork
  rnet <- overline(routes_fast, attrib = "length")
  SLN <- SpatialLinesNetwork(rnet)

# identify nodes
  sln_nodes = sln2points(SLN)

# Here is a bus stop which should be added as a node
  new_point <- SpatialPointsDataFrame(coords = cbind(-1.535, 53.809), data= data.frame(id="new"))

# plot
  plot(SLN, col = "gray")                 # network
  plot(sln_nodes, col="red", add = TRUE)  # nodes
  plot(new_point, add=T, col="blue")      # stop to be added as a new node

enter image description here

2 个答案:

答案 0 :(得分:2)

这不能在一开始就回答您的问题,但我相信它确实可以通过展示如何计算您所需的网络距离来解决您的“背景”。这可以使用dodgr(最新dev版本)完成,如下所示:

library (dodgr)
library (stplanr)
library (sf)
library (sp)
dat <- st_as_sf (routes_fast)
net <- weight_streetnet (dat, wt_profile = 1)

net对象是一个简单的data.frame,包含网络的所有边和顶点。然后调整上面的代码,将路由点作为一个简单的矩阵

rnet rnet <- overline(routes_fast, attrib = "length")
SLN <- SpatialLinesNetwork(rnet)
sln_nodes = sln2points(SLN)
xy <- coordinates (sln_nodes)
colnames (xy) <- c ("x", "y")

sln2points只返回“节点”(在stplanr术语中)的节点,它们是连接点。您可以使用公交车站的坐标替换,或者只是将其添加到此矩阵。以下三行将这些坐标转换为dodgr net对象的唯一(最近)顶点ID:

v <- dodgr_vertices (net)
pts <- match_pts_to_graph (v, xy)
pts <- v$id [pts]

要计算网络上pts之间的距离,只需

d <- dodgr_dists (net, from = pts, to = pts)

答案 1 :(得分:1)

感谢这个问题,感谢这个问题以及随后与Andrea Gilardi的合作,我很高兴地宣布,现在可以使用新功能sln_add_node()向sfNetwork对象添加新节点了。

请参见下文,请尝试测试可重复的代码以演示其工作原理:

devtools::install_github("ropensci/stplanr")
#> Skipping install of 'stplanr' from a github remote, the SHA1 (33158a5b) has not changed since last install.
#>   Use `force = TRUE` to force installation
library(stplanr)
#> Registered S3 method overwritten by 'R.oo':
#>   method        from       
#>   throw.default R.methodsS3
#> Warning in fun(libname, pkgname): rgeos: versions of GEOS runtime 3.7.1-CAPI-1.11.1
#> and GEOS at installation 3.7.0-CAPI-1.11.0differ

sample_routes <- routes_fast_sf[2:6, NULL]
sample_routes$value <- rep(1:3, length.out = 5)
rnet <- overline2(sample_routes, attrib = "value")
#> 2019-09-26 16:06:18 constructing segments
#> 2019-09-26 16:06:18 building geometry
#> 2019-09-26 16:06:18 simplifying geometry
#> 2019-09-26 16:06:18 aggregating flows
#> 2019-09-26 16:06:18 rejoining segments into linestrings
plot(sample_routes["value"], lwd = sample_routes$value, main = "Routes")

plot(rnet["value"], lwd = rnet$value, main = "Route network")

sln <- SpatialLinesNetwork(rnet)
#> Linking to GEOS 3.7.1, GDAL 2.4.0, PROJ 5.2.0

new_point_coordinates <- c(-1.540, 53.826)
crs <- sf::st_crs(rnet)
p <- sf::st_sf(geometry = sf::st_sfc(sf::st_point(new_point_coordinates)), crs = crs)
p_dest <- sln2points(sln)[9, ]

# We can identify the nearest point on the network at this point
# and use that to split the associated linestring:

sln_new <- sln_add_node(sln = sln, p = p)
#> although coordinates are longitude/latitude, st_nearest_feature assumes that they are planar
route_new <- route_local(sln = sln_new, from = p, to = p_dest)
plot(sln_new)
plot(p, add = TRUE)
plot(route_new, lwd = 5, add = TRUE)
#> Warning in plot.sf(route_new, lwd = 5, add = TRUE): ignoring all but the
#> first attribute

reprex package(v0.3.0)于2019-09-26创建

如果有使用/兴趣,请在此处查看支持此新功能的小型新函数系列的源代码:https://github.com/ropensci/stplanr/blob/master/R/node-funs.R