Introduction
The match between GTFS shapes and OSM routes geometries using either
GTFShift::osm_shapes_match_routes() or
GTFShift::osm_shapes_to_routes() enables the retrieval of
harmonized geometries for the GTFS network. However, OSM geometries are
often MULTILINESTRING objects. In contrast, GTFS shapes.txt file
requires a sequence of points to define each shape.
GTFShift::create_shapes_from_sf() can be used to
overcome this limitation, encapsulating the conversion of
MULTILINESTRING objects into sorted LINESTRING objects and generating
the corresponding GTFS shapes.txt structured table. Additionally, it can
compute the cumulative distance along the shape
(shape_dist_traveled), an optional parameter recommended
for routes that have looping or inlining.
Example
# Get GTFS from library GTFS database for Portugal
data <- read.csv(system.file("extdata", "gtfs_sources_pt.csv", package = "GTFShift"))
gtfs_id <- "lisboa"
gtfs <- GTFShift::load_feed(data$URL[data$ID == gtfs_id], create_transfers = FALSE)
# Build OSM query
library(osmdata)
q <- opq("Lisbon") |>
add_osm_feature(key = "route", value = c("bus", "tram")) |>
add_osm_feature(key = "network", value = "Carris", key_exact = TRUE)
# Get OSM geometries
shapes_geometry_osm <- GTFShift::osm_shapes_to_routes(gtfs, q)
# Filter GTFS for shapes (mind that OSM might not have a match for all shapes)
osm_shape_ids <- unique(shapes_geometry_osm$shape_id)
gtfs_trips_with_osm_geometry <- gtfs$trips |>
filter(shape_id %in% osm_shape_ids) |>
pull(trip_id) |>
unique()
gtfs <- tidytransit::filter_feed_by_trips(gtfs, trip_ids = gtfs_trips_with_osm_geometry)
# Convert OSM geometries to LINESTRING objects
shapes_osm <- GTFShift::create_shapes_from_sf(shapes_geometry_osm, gtfs)
# Update GTFS shapes with OSM geometries
gtfs$shapes <- shapes_osm
# Write GTFS to file
tidytransit::write_gtfs(gtfs, "gtfs_osm.zip")