library(sf) library(dplyr) library(osmextract) setwd("") # ------- Inputs (files expected in your working directory) ------- # Regional .osm.pbf files you have on disk: pbf_files <- c( "us-midwest-latest.osm.pbf", "us-south-latest.osm.pbf", "us-west-latest.osm.pbf", "us-northeast-latest.osm.pbf" ) # Name each region (used for output layer names) region_names <- c("Midwest", "South", "West", "Northeast") stopifnot(length(pbf_files) == length(region_names)) # Highway classes to keep (fixed 'tertiary' typo) wanted_hw <- c("residential","motorway","trunk","primary", "secondary","tertiary","unclassified","living_street") # SQL WHERE clause for oe_read (quote strings for SQL IN) in_list <- paste0("('", paste(wanted_hw, collapse = "', '"), "')") sql <- paste( "SELECT geometry, highway FROM 'lines'", "WHERE highway IN", in_list ) # ------- Process each region ------- intersection_list <- vector("list", length(pbf_files)) for (i in seq_along(pbf_files)) { pbf <- pbf_files[i] reg <- region_names[i] message("Reading roads for: ", reg) # Read filtered road lines from OSM PBF roads <- oe_read(pbf, query = sql) # Persist regional roads to a GeoPackage (one layer per region) st_write(roads, "OSM_roads.gpkg", layer = paste0(reg, "_roads"), delete_layer = TRUE, quiet = TRUE) # Convert linework to vertices and keep only duplicated nodes (intersections) intersections <- roads |> st_cast("MULTIPOINT") |> st_cast("POINT") # Duplicated compares geometry column; TRUE = appears more than once intersections <- intersections[duplicated(intersections$geometry), ] intersection_list[[i]] <- intersections rm(roads, intersections); gc() } # ------- Combine and write out ------- Intersections <- do.call(rbind, intersection_list) # Shapefile output to match your original; consider .gpkg for fewer limits st_write(Intersections, "Intersections.shp", driver = "ESRI Shapefile", delete_layer = TRUE, quiet = TRUE)