Skip to content

Instantly share code, notes, and snippets.

@szechno
Created November 21, 2025 15:03
Show Gist options
  • Select an option

  • Save szechno/34a16f40a52a92cab572ed9ab3a4d177 to your computer and use it in GitHub Desktop.

Select an option

Save szechno/34a16f40a52a92cab572ed9ab3a4d177 to your computer and use it in GitHub Desktop.
library(mapgl)
library(sf)
library(stringr)
library(dplyr)
library(magrittr)
library(osmdata)
map_start <- c(-0.404549247616387, 50.9365654134795)
initial_zoom <- 10
# local data
border <- read_sf(geodata,
layer = "TSS Boundary")
openbusstops_data <- read_sf(geodata,
layer = "OpenBus Bus Stops")
trainstation_data <- read_sf(geodata,
layer = "ORR Transport_Train_Station_Passengers")
bus_routes <- read_sf(paste0(altdata, "Bus_routes.shp")) |>
st_intersection(border)
# osm data
nominatim_polygon <- nominatimlite::geo_lite_sf(
address = "west sussex, uk",
points_only = FALSE)
bbox <- sf::st_bbox(nominatim_polygon)
train_routes <- opq(bbox) |>
add_osm_feature(key = "route", value = "train") |>
osmdata_sf() |>
use_series(osm_lines)
train_routes <- train_routes |>
st_transform(crs = 27700) |>
st_intersection(border)
airports <- opq(bbox) |>
add_osm_feature(key = "aeroway", value = "aerodrome") |>
osmdata_sf() |>
use_series(osm_polygons) |>
st_transform(crs = 27700) |>
st_intersection(border)
# the map
maplibre() |>
fit_bounds(openbusstops_data) |>
add_fill_layer(
id = "border",
source = border,
fill_color = "lightgrey",
fill_opacity = 0.3
) |>
add_line_layer(
id = "routes",
source = bus_routes,
line_color = "orange",
line_width = 0.5,
line_opacity = 0.5
) |>
add_line_layer(
id = "train_routes",
source = train_routes,
line_color = "navy",
line_width = 2,
line_cap = "round",
line_opacity = 0.5
) |>
add_image("busstop",
url = paste0("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKUAAAC",
"rCAYAAAAHIVyqAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUA",
"AAAJcEhZcwAADsAAAA7AAWrWiQkAAAAZdEVYdFNvZnR3YXJlAHd3d",
"y5pbmtzY2FwZS5vcmeb7jwaAAABh2lUWHRYTUw6Y29tLmFkb2JlLn",
"htcAAAAAAAPD94cGFja2V0IGJlZ2luPSfvu78nIGlkPSdXNU0wTXB",
"DZWhpSHpyZVN6TlRjemtjOWQnPz4NCjx4OnhtcG1ldGEgeG1sbnM6",
"eD0iYWRvYmU6bnM6bWV0YS8iPjxyZGY6UkRGIHhtbG5zOnJkZj0ia",
"HR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW",
"5zIyI+PHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9InV1aWQ6ZmF",
"mNWJkZDUtYmEzZC0xMWRhLWFkMzEtZDMzZDc1MTgyZjFiIiB4bWxu",
"czp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+P",
"HRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj48L3",
"JkZjpEZXNjcmlwdGlvbj48L3JkZjpSREY+PC94OnhtcG1ldGE+DQo",
"8P3hwYWNrZXQgZW5kPSd3Jz8+LJSYCwAACiZJREFUeF7t3XmsXGUd",
"xvHvC7UClaWylKUWTQxqASO21ehJlAQLQhEhoiyWxBiOIVhED1FiA",
"OOCsohH9qAvIgZkMQIuIcEAJaCvEUJq4h9sikhLQdm3Flna1z96ao",
"Zf7+2dmbPMe+99Pskkw/ObuZee+9wzZ+6cBURERGSScTYYoZnAfOA",
"dwFxgJ2AWMAPY1j5YankJeANYAzwFrAZWAvcDr9kHd22UpdwZWAzs",
"D2TAXnmZzbAPku74IrwBPAj8GbgDuK0qbae6LuXWwDHAscD+eZlta",
"R8g6fBFWFeV8xrgOuAV+5g2dFXK2cApwAl5me1oh5I+X4SngcuAHw",
"HP23mT2i7lDOBk4LS8zGbboUw+vgjPAmcCFwLr7LwJbZbyfcAv8jJ",
"bZAcy+fki3A18AXjAzupqq5RLgGvyMtvODmTq8EVYAxwH3GRndbTx",
"RuNrwJV5mW1lBzK1LDho3swVf1j1WeAF4G47H1bTa8pleZldZEOZ2",
"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",
"h8ZyfwnvuiPpwAAAABJRU5ErkJggg==")) |>
add_symbol_layer(
id = "openbusstops_data",
source = openbusstops_data,
icon_image = "busstop",
icon_allow_overlap = FALSE,
icon_size = 0.09,
icon_opacity = 1,
# icon_color = bus_color,
tooltip = concat("Bus stop (8+ buses ph)",
"<br />",
get_column("stop_name"),
"<br />",
get_column("Total_ph"), " bus ph")#,
# text_font = list("Noto Sans Regular") # must include for openfreemaps!!
) |>
add_image(
"trainstation",
url = "https://upload.wikimedia.org/wikipedia/sco/thumb/3/31/National_Rail_logo.svg/62px-National_Rail_logo.svg.png") |>
add_symbol_layer(
id = "trainstation_data",
source = trainstation_data,
icon_image = "trainstation",
icon_allow_overlap = TRUE,
icon_size = interpolate(
column = "Annual_passengers",
type = "linear",
values = c(5000,16507980),
stops = c(0.4,1)
),
text_field = concat(
get_column("Station"),
"\n",
number_format("Annual_passengers")
),
text_offset = c(0, 2),
text_size = 10,
text_halo_width = 2,
text_halo_color = "white"
) |>
add_image(
"airport",
url = "./images/airport.png") |>
add_symbol_layer(
id = "airports",
source = airports,
icon_image = "airport",
icon_allow_overlap = TRUE,
icon_size = interpolate(
column = "Annual_passengers",
type = "linear",
values = c(5000,16507980),
stops = c(0.4,1)
),
text_field = get_column("name"),
text_offset = c(0, 2),
text_size = 10,
text_halo_width = 2,
text_halo_color = "white"
) |>
add_control("<div style='padding: 5px; background-color: #2E8B57; color: white;'>
<h2>Train stations, Bus stops, Airports<br />in West Sussex as icons</h2>
Day 21: icons<br />
data: OpenStreetMaps, ORR, Bus Open Data<br />
πš–πšŠπšŒπš”πšŠβ€€πšœπš£πšŽπšŒπš‘πš—πš˜<br />21 November 2025
</div>",
position = "bottom-right")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment