Routing and isochrones

knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 6.5, fig.height = 5.5)
library(osmnxr)
g <- ox_example("olinda")

Routing in osmnxr runs in the Rust core (Dijkstra, Yen, multi-source). We use the bundled real network of central Olinda, Brazil, so this runs offline.

Shortest path by distance

Snap two coordinates to the nearest nodes, then route between them:

orig <- ox_nearest_nodes(g, x = -34.8553, y = -8.0089)
dest <- ox_nearest_nodes(g, x = -34.8505, y = -8.0125)
route <- ox_shortest_path(g, orig, dest, weight = "length")
length(route) # nodes along the route
route_xy <- sf::st_coordinates(g$nodes)[match(route, g$nodes$osmid), ]
plot(g, col = "grey80", lwd = 0.6)
lines(route_xy, col = "#b7410e", lwd = 3)
points(route_xy[c(1, nrow(route_xy)), ], pch = 19, col = "#0d3b66", cex = 1.2)

Travel time instead of distance

Real routing usually minimises time, not distance. Impute free-flow speeds from each road's class, derive per-edge travel times, then route on them (Boeing 2025, routing module):

g <- ox_add_edge_travel_times(g)
head(g$edges[c("highway", "length", "speed_kph", "travel_time")])

route_t <- ox_shortest_path(g, orig, dest, weight = "travel_time")
identical(route_t, route) # may differ: the fastest route is not always shortest

Route alternatives

ox_k_shortest_paths() returns the k shortest loopless routes (Yen's algorithm) — useful for comparing options or modelling redundancy:

ox_k_shortest_paths(g, orig, dest, k = 3, weight = "travel_time")

Isochrones (service areas)

An isochrone is the area reachable from an origin within a budget. With travel_time as the weight, cutoffs are in seconds — here, 1- and 2-minute drive-time service areas from a central point:

centre <- ox_nearest_nodes(g, x = -34.8553, y = -8.0089)
iso <- ox_isochrone(g, centre, cutoffs = c(60, 120), weight = "travel_time")
iso[c("cutoff", "n_nodes")]
plot(g, col = "grey85", lwd = 0.6)
plot(sf::st_geometry(iso), add = TRUE, border = NA,
     col = grDevices::adjustcolor(c("#0d3b66", "#2a9d8f"), 0.4))

Many-to-many distances

For accessibility work you often need a full origin–destination matrix in one call (see the Accessibility article):

hubs <- ox_nearest_nodes(g,
  x = c(-34.8553, -34.8505, -34.852),
  y = c(-8.0089, -8.0125, -8.006))
round(ox_distance_matrix(g, hubs, hubs, weight = "travel_time"))

References

Boeing, G. (2025). Modeling and analyzing urban networks and amenities with OSMnx. Geographical Analysis.



Try the osmnxr package in your browser

Any scripts or data that you put into this service are public.

osmnxr documentation built on Oct. 20, 2026, 1:07 a.m.