6

the call get_osm(muc_bbox, src) takes quite a lot of time (46.151 sec) while loading from a big osm file. I was wondering is it possible to create a center_bbox from a center_bbox so to say on demand? Load a big file into memory once and create small "boxes" from it depending on requierement ? or is there a different approach to this problem? Maybe it is possible to load big file into memory in a different structure and create bboxes from it on demand so it would be faster overall? i uploaded a bigger osm file here OSM File

Thank you in advance! BR.

library(osmar)
library(igraph)

### Get data ----
src <- osmsource_osmosis(file = "~/streets_bayern.osm")

muc_bbox <- center_bbox(11.575278, 48.137222, 41242.57, 41242.57)
muc <- get_osm(muc_bbox, src)

### Reduce to highways: ----
hways <- subset(muc, way_ids = find(muc, way(tags(k == "highway"))))
hways <- find(hways, way(tags(k == "name")))
hways <- find_down(muc, way(hways))
hways <- subset(muc, ids = hways)

#### Plot data ----
## Plot complete data and highways on top:
plot(muc)
plot_ways(muc, col = "lightgrey")
plot_ways(hways, col = "coral", add = TRUE)

### Define route start and end nodes: ----
id<-find(muc, node(tags(v %agrep% "Sendlinger Tor")))[1]
hway_start_node <-find_nearest_node(muc, id, way(tags(k == "highway"))) 
hway_start <- subset(muc, node(hway_start_node))

id <- find(muc, node(attrs(lon > 11.58 & lat > 48.15)))[1]
hway_end_node <- find_nearest_node(muc, id, way(tags(k == "highway")))
hway_end <- subset(muc, node(hway_end_node))

## Add the route start and and nodes to the plot:
plot_nodes(hway_start, add = TRUE, col = "red", pch = 19, cex = 2)
plot_nodes(hway_end, add = TRUE, col = "red", pch = 19, cex = 2)

### Create street graph ----
gr <- as.undirected(as_igraph(hways))

### Compute shortest route: ----
# Calculate route
route <- function(start_node,end_node) {
  get.shortest.paths(gr,
                     from = as.character(start_node),
                     to = as.character(end_node), 
                     mode = "all")[[1]][[1]]}
# Plot route

plot.route <- function(r,color) {
  r.nodes.names <- as.numeric(V(gr)[r]$name)
  r.ways <- subset(hways, ids = osmar::find_up(hways, node(r.nodes.names)))
  plot_ways(r.ways, add = TRUE, col = color, lwd = 2)
}




# Number of new ways to look for 
nways <- 10
# Weight factor applied to already found way
weightfactor <- 2


for (numway in 1:nways) {
  r <- route(hway_start_node,hway_end_node)
  color <- colorRampPalette(c("springgreen","royalblue"))(nways)[numway]
  plot.route(r,color)
  # Modify current route weight
  
  route_nodes <- as.numeric(V(gr)[r]$name)
  #We construct a newosmarobject containing only elements related to the nodes defining the route:
  route_ids <- find_up(hways, node(route_nodes))
  route_muc <- subset(hways, ids = route_ids)
  
  #Route details.
  #In order to present route details like street names,
  #distances, and directions we have to work directly on the internals of the osmar objects.
  #We start by extracting the route’s node IDs (which are in the correct order) and the way IDs (which we have to order)
  #where the nodes are members:
  
  node_ids <- route_muc$nodes$attrs$id
  
  # to delete node ids.
  # gr_muc<-delete_vertices(gr_muc, as.character(node_ids[20]))
  
  way_ids <- local({
    w <- match(node_ids, route_muc$ways$refs$ref)
    route_muc$ways$refs$id[w]
  })
  
  #Then we extract the names of the ways in the correct order:>
  way_names <- local({
    n <- subset(route_muc$ways$tags, k == "name")
    n[match(way_ids, n$id), "v"]
  })
  
  #The next step is to extract the nodes’ coordinates,>
  node_coords <- route_muc$nodes$attrs[, c("lon", "lat")]
  
  #and to compute the distances (meters) and the bearings (degrees) between successive nodes (using thepackagegeosphere):
  node_dirs <- local({
    n <- nrow(node_coords)
    from <- 1:(n - 1)
    to <- 2:n
    cbind(dist = c(0, distHaversine(node_coords[from,], node_coords[to,])),
          bear = c(0, bearing(node_coords[from,], node_coords[to,])))
  })
  
  #Finally, we pack together all the information, and additionally compute the cumulative distance
  #and a16-point compass rose direction (thecompass()function is available in the “navigator ” demo from theosmarpackage):
  
  route_details <- data.frame(way_names, node_dirs)
  route_details$cdist <- cumsum(route_details$dist)
  route_details$coord <- node_coords
  route_details$id <- node_ids
  print(route_details)
 
Andreas
  • 397
  • 4
  • 18
  • 37

1 Answers1

0

You first have to download and install Osmosis on your computer.
The following script allows you to define a box and query the large map you provided :

library(osmar)

# Set Osmosis source
src <- osmsource_osmosis(file = here::here("streets_bayern.osm"))

# Define box
muc_bbox <- center_bbox(11.575278, 48.137222, 1000, 1000)

# normally this should work, but didn't :
# muc  <- get_osm(muc_bbox, src)

# As I had trouble using directly get_osm, used modified source of it instead :
destination <- tempfile(tmpdir = here::here(),pattern = "tmp",fileext=".tmp")
request <- osmar:::osm_request(src, muc_bbox, destination)

# Folder where Osmosis.bat is located
osmosis.path <- 'c:/RDev/Osmosis/bin/'

request <- paste0(osmosis.path,request)

# Run request and check if it worked OK
if (system(request)==127) {stop('Osmosis request failed')}

# get response
response <- readLines(destination)
unlink(destination)

# Parse response
muc <- as_osmar(xmlParse(response))

plot(muc)

Response time is around 10s, much faster than downloading the map from url. enter image description here

Waldi
  • 39,242
  • 6
  • 30
  • 78
  • Thank you very much but that's not the problem. I think you miss understood me. I already do that (see attached file). Try to define a bigger bbox (40000x 40000) and load it with muc <- get_osm(muc_bbox, src) and you will see the problem. – Andreas Jun 21 '20 at 14:35
  • do you mean that nothing happens? – Waldi Jun 21 '20 at 18:18
  • what do you mean? i changed the code to avoid missunderstanding. Loading of this bbox takes 46.151 Sec. If i would to load the whole bavarian map it would grow even bigger. Searching for path in that big bbox will add another long waiting period so i need to be able to create small bboxes from memory or some other structure. – Andreas Jun 21 '20 at 20:14
  • On my computer, the loading + plotting script takes 11s for (1000,1000), 13s for (2000,2000), 18s for (4000,4000) – Waldi Jun 21 '20 at 20:30
  • 4000 = 4km x 4km bbox. You are missing a zero. Try adding as i suggested one more zero -> 40.000 :) – Andreas Jun 21 '20 at 20:56
  • 2
    OK : finally understood the pb :) the as_osmar function is taking most of the time – Waldi Jun 21 '20 at 21:50
  • Yes exactly. So I thought if it would be possible to load big bbox once and generate small ones on demand from memory.. from the big one so to say. Or to use some other data structure to load osm file into memory and then generate bboxes. – Andreas Jun 21 '20 at 22:19
  • i was wondering since matrix operations are optimized and i have all coordinates in a matrix form of the streets the weights of wich i would like to increse: would it be possible to load osm object into a matrix then apply the matrix with the weights and then create a graph? this would provide perfomance increse – Andreas Jun 23 '20 at 20:04
  • @Andreas, I had the same thoughts, but didn't find yet time to explore this direction. What information is important for you in the map : only nodes positions and ways between nodes? Do you need other infos like street names, ...? – Waldi Jun 23 '20 at 20:42
  • i need just the routing information : only nodes positions and ways between nodes and weights – Andreas Jun 23 '20 at 20:47
  • did you had any new idea on this one? Im still fighting it – Andreas Jul 06 '20 at 16:06