Добавить новый узел в 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