Those shapes are usually referred to as isodistances. osrm package provides easy to use interface for OSRM routing service and comes with osrmIsodistance()
function that returns sf
object (a dataframe with support for geometries) with a multipolygon. sf
is well-supported by Leaflet , so we can just add it as a polygon layer. For convenience, we'll also store source locations in sf
object.
By default osrm
uses an OSRM demo server which is not really suitable for heavy traffic and high request rate ( usage policy ), though it should be fine for generating a limited set of isodistance polygons.
library(dplyr)
library(sf)
library(osrm)
library(leaflet)
library(tictoc)
# store locations in sf object
points_sf <- tibble(location = "George Bush International Airport",
lat = 29.990665933195277,
long = -95.33663249561174,
radius = 48280.3 ) %>%
st_as_sf(coords = c("long", "lat"), crs = "WGS84")
points_sf
#> Simple feature collection with 1 feature and 2 fields
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: -95.33663 ymin: 29.99067 xmax: -95.33663 ymax: 29.99067
#> Geodetic CRS: WGS 84
#> # A tibble: 1 × 3
#> location radius geometry
#> * <chr> <dbl> <POINT [°]>
#> 1 George Bush International Airport 48280. (-95.33663 29.99067)
## 30-mile / 48km isodistance polyon
# loc: takes only a single location or first location from dataframe / sf
# breaks: vector of isodistance areas, i.e. c(10000, 25000, 50000) to generate 3 polygons
# res: number of points for one side of square grid, default is (much faster) 30
# tic-toc for timing
tic("osrmIsodistance")
isodist_sf <- osrmIsodistance(loc = points_sf[1,],
breaks = points_sf$radius[1],
res = 100)
toc()
#> osrmIsodistance: 162.23 sec elapsed
resulting sf object:
isodist_sf
#> Simple feature collection with 1 feature and 3 fields
#> Geometry type: MULTIPOLYGON
#> Dimension: XY
#> Bounding box: xmin: -95.73746 ymin: 29.62006 xmax: -94.87008 ymax: 30.32588
#> Geodetic CRS: WGS 84
#> id isomin isomax geometry
#> 1 1 0 48280.3 MULTIPOLYGON (((-95.1592 30...
# leaflet supports sf object, no need to specify lng/lat for markers, polygons
leaflet() %>%
addTiles() %>%
addPolygons(data = isodist_sf, weight = 1, group = "Isodistance") %>%
addMarkers(data = points_sf, label = ~ location, group = "Locations") %>%
addLayersControl(overlayGroups = c("Isodistance", "Locations"),
options = layersControlOptions(collapsed = TRUE))

Created on 2023-07-13 with reprex v2.0.2