All Roads Lead to Offenbach

1 minute read

Published:

10,000 randomly placed points across Europe, each routed to Offenbach am Main via OSRM.

All roads lead to Offenbach

The approach: take the outline of Europe, scatter random points on land, then compute the optimal driving route from each point to Offenbach using a self-hosted OSRM server. The result is a cobweb of routes that reveals the continental road network structure – the major corridors through France, the Alps, the Balkans, and Scandinavia emerge naturally.

Built in R. Geocode the city, sample 10,000 points within a 4,000 km buffer on European land (using the cobweb package’s Europe geometry), then fetch routes in parallel via OSRM:

library(osrm)
library(sf)
library(mapsf)
library(tidygeocoder)
library(parallel)
library(doParallel)
library(foreach)

# Geocode city, sample points on land within buffer
v_raw <- tidygeocoder::geo("Offenbach am Main, Germany", progress_bar = FALSE)
v <- st_as_sf(v_raw[1,], coords = c("long", "lat"), crs = "EPSG:4326")
zone <- st_buffer(st_transform(v, "EPSG:3035"), 4000 * 1000)
land <- st_read(system.file("gpkg/europe.gpkg", package = "cobweb"), layer = "fg")
pts <- st_sample(st_intersection(st_geometry(zone), st_geometry(land)), size = 10000)
df <- data.frame(srcx = v_raw$long, srcy = v_raw$lat,
                 dstx = st_coordinates(st_transform(pts, 4326))[,1],
                 dsty = st_coordinates(st_transform(pts, 4326))[,2])

# Parallel OSRM routing (12 cores)
roads <- get_routes(df, ncl = 12, url = "http://0.0.0.0:5000/")
# ... mf_map(roads) for visualization

The get_routes() helper splits the work across 12 cores, calling osrmRoute() for each origin–destination pair. Map export uses mapsf. Full implementation: streetplotter.R.

Inspired by rcarto’s OSRM server tutorial.