Как назначить идентификаторы узлов и получить кратчайшие маршруты в stplanr? - PullRequest
0 голосов
/ 20 апреля 2020

CASE

Я хотел бы понять, как использовать stplanr для моих собственных данных узлов и ребер. Узлы имеют определенные c координаты, но ребра между этими узлами не являются линейным расстоянием. Ребра содержат информацию о том, какие узлы они соединяют, каково расстояние и дополнительный весовой коэффициент, который описывает, насколько обременительным является использование этого пути. Поэтому самый короткий путь не всегда самый быстрый.

Решенные проблемы

Сейчас я выяснил, как:

  • преобразовать мои данные ребер в stplanr пространственные объекты
  • применить к ним stplanr функцию
  • учитывать различные веса

Dataprep

# attach packages --------------------------------------------------------------
library(sp)
library(sf)
library(igraph)
library(stplanr)
library(data.table)

# make up some dummy data that has the same structure as my original data ------
routes <- data.frame(X_from = c(1, 3, 3, 2, 1),
                     Y_from = c(3, 3, 2, 1, 3),
                     X_to = c(3, 3, 2, 1, 3),
                     Y_to = c(3, 2, 1, 3, 2),
                     id_from = c(101, 102, 103, 104, 101),
                     id_to = c(102, 103, 104, 101, 103),
                     id_edge = 1:5,
                     distance = c(2.1, 1, 1.5, 2.5, 10))

# convert it to the desired SpatialLinesNetwork format -------------------------
slines <- apply(routes, 1, function(x){
  l1 <- cbind(c(x["X_from"], x["X_to"]),
              c(x["Y_from"], x["Y_to"]))
  Sl1 <- Line(l1)
  S1 <- Lines(list(Sl1), ID = format(x["id_edge"], scientific = FALSE))
})
sl <- SpatialLines(slines)
df <- data.table(len = routes[["distance"]])
rownames(df) <- as.character(routes$id_edge)
sldf <- SpatialLinesDataFrame(sl, df)
sln <- SpatialLinesNetwork(sldf)
plot(sln) # success!

Задачи

Как правильно определить узлы?

Во время моего dataprep я не смог поддерживать идентификаторы узлов. Я могу назначить их, как показано ниже, но это очень важно для ошибок. Кроме того, сам маршрут, похоже, не сохраняется правильно при использовании идентификаторов (красная линия не достигает нужного узла).

# overwrite node/vertex IDs ----------------------------------------------------
V(sln@g)$name <- as.character(101:104)

# length of edges are automatically calculated
sln@sl$length
# [1] 2.000000 1.000000 1.414214 2.236068 2.236068

# add an additional weight information to each edge
(sln@sl$weight <- routes$distance)
# [1]  2.1  1.0  1.5  2.5 10.0

# shortest path ----------------------------------------------------------------
weightfield(sln) # current wightfield
# [1] "length"
(shortest <- sum_network_routes(sln = sln, 
                                start = "101", end = "103", 
                                sumvars = c("length", "weight"))
)
# sum_length,         sum_weight
# 2.2360678,          10

# fastest path -----------------------------------------------------------------
weightfield(sln) <- "weight" # change weightfield
(most_efficient <- sum_network_routes(sln = sln, 
                                      start = "101", end = "103",
                                      sumvars = c("length", "weight"))
) 
# sum_length,         sum_weight
# 3,                  3.1

# plot the results -------------------------------------------------------------
plot(sln)
plot(shortest, add = TRUE, col = "blue")
plot(most_efficient, add = TRUE, col = "red") # only one line of the whole path

Как получить фактический маршрут?

I может вычислить кратчайший путь через sum_network_routes(), получить сводную информацию и может построить путь. Тем не менее, как я могу получить фактический маршрут пройденных вершин / узлов? Я не мог извлечь его из самого объекта. Кроме того, ни одна из функций route_*() или line2route() не работала.

Любая помощь приветствуется :)

...