riatelab / osrm

Interface between R and the OpenStreetMap-based routing service OSRM
https://doi.org/10.21105/joss.04574
GNU General Public License v3.0
233 stars 31 forks source link

isochrones for multiple points #74

Closed hmeleiro closed 3 years ago

hmeleiro commented 3 years ago

Is there a way to create ischrones based on multiple points? Or maybe a way to merge the polygons afterwards?

If I wanted to calculate the walking time to subway transportation (independent of which station) how would I proceed? In the following case, I calculate the isochrones of two nearby stations that overlap but I don't know how would I merge them into one coherent isochrone. iso

Thanks anyway! Great package!

rCarto commented 3 years ago

osrmIsochrone() output is an sf object, so you can aggregate two or more isochrone layers. Here is a quick and dirty example :

library(osrm)
#> Data: (c) OpenStreetMap contributors, ODbL 1.0 - http://www.openstreetmap.org/copyright
#> Routing: OSRM - http://project-osrm.org/
library(sf)
#> Linking to GEOS 3.7.1, GDAL 3.1.2, PROJ 7.1.0

# use local instance of OSRM
options(osrm.server = "http://0.0.0.0:5000/", 
        osrm.profile = "car")

# define a break list
bks <-  seq(0,14,2)

# Get isochones with lon/lat coordinates
iso1 <- osrmIsochrone(loc = c(13.40,52.47), 
                     breaks = bks,
                     returnclass="sf")
# Get isochones with lon/lat coordinates
iso2 <- osrmIsochrone(loc = c(13.44, 52.46), 
                      breaks = bks, 
                      returnclass="sf")

# intersect isochrones
inter <- st_intersection(iso1, iso2)
#> although coordinates are longitude/latitude, st_intersection assumes that they are planar
#> Warning: attribute variables are assumed to be spatially constant throughout all
#> geometries
# extrct only polygons
inter <- st_collection_extract(inter, "POLYGON")

# get the min value for each polygons (the quick & dirty way)
for(i in 1:nrow(inter)){
  inter$imin[i] <- min(unlist(inter[i,c(2, 6), drop = T]))
  inter$imax[i] <- min(unlist(inter[i,c(3, 7), drop = T]))
  inter$icenter[i] <- min(unlist(inter[i,c(4, 8), drop = T]))
}

# aggregates isochrone polygons
iso <- aggregate(x = inter[, c("imin", "imax", "icenter")], 
                 by = list(id = inter$icenter), 
                 FUN = "min")
iso <- st_collection_extract(iso, "POLYGON")

# map
plot(iso["icenter"], breaks = bks, 
     border = "grey80", lwd = .5, 
     pal = hcl.colors(7, "Cividis"))

Created on 2021-04-06 by the reprex package (v1.0.0)

hmeleiro commented 3 years ago

Thanks! I was trying something with group_by() but was not getting the desired result.