Добавить новый узел в SpatialLinesNetwork в stplanr

Как можно использовать SpatialPointsDataFrame добавить новый узел к SpatialLinesNetwork?

контекст моей проблемы: у меня есть шейп-файл автобусного маршрута и другой шейп-файл автобусных остановок. Я хочу рассчитать расстояние между остановками вдоль автобусного маршрута. В идеале каждая остановка была бы узлом, и я бы использовал 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

введите описание изображения здесь

1 ответ

Это не отвечает на ваш вопрос с самого начала, но я полагаю, что это действительно решает ваш "контекст", показывая, как можно рассчитать желаемые расстояния в сети. Это может быть сделано с 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 объект:

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

Чтобы рассчитать расстояния между этими pts в сети, просто

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

Спасибо за вопрос, благодаря этому вопросу и последующему сотрудничеству с Андреа Джиларди, я рад сообщить, что теперь можно добавлять новые узлы в объекты sfNetwork с новой функцией, sln_add_node().

Посмотрите ниже и попробуйте протестировать воспроизводимый код, демонстрирующий, как это работает:

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

Создано 26.09.2019 пакетом REPEX (v0.3.0)

Если это необходимо / интересно, см. Исходный код нового небольшого семейства функций, которые поддерживают эту новую функциональность, здесь: https://github.com/ropensci/stplanr/blob/master/R/node-funs.R

Другие вопросы по тегам