cpp_extract: Extract a routable graph from a geographic source

View source: R/cpp_extract.R

cpp_extractR Documentation

Extract a routable graph from a geographic source

Description

Single entry point to build a makegraph-ready graph from a geographic linestring source. The source is dispatched on automatically from x's type (file extension, or object class). Exactly five forms of x are recognized – see the x parameter below for the precise contract of each, since passing the wrong shape of object for a given source (e.g. only part of an osmdata result) fails loudly rather than silently producing a wrong graph.

Usage

cpp_extract(
  x,
  output = c("graph", "data.frame", "csv"),
  out_prefix = NULL,
  coords = TRUE,
  epsg = NULL,
  keep_length = FALSE,
  snap_digits = NULL,
  osm_params = list(),
  geom_params = list()
)

Arguments

x

One of:

  • a path (character) to a .shp shapefile – the companion .dbf/.prj must sit next to it, same base name;

  • an in-memory sf object (LINESTRING/MULTILINESTRING), e.g. from sf::st_read() on a GeoPackage or any other OGR-readable format;

  • a path (character) to an .osm.pbf file;

  • the full result of osmdata::osmdata_sf() (class "osmdata") – not just its $osm_lines element. $osm_points must also be present: it holds the osm_id of every node osmdata downloaded (including untagged vertices in the middle of a way), which is what lets cpp_extract recover real OSM topology and detect junctions;

  • for osmextract: not a distinct input type – get the path to the raw cached .pbf with osmextract::oe_get(..., download_only = TRUE, skip_vectortranslate = TRUE) (both flags are required: download_only alone still runs the GDAL conversion and returns a .gpkg path instead) and pass that .pbf path like any other .pbf file. Do not let osmextract convert it to sf/GeoPackage via GDAL first: that conversion only keeps tagged nodes by default, which is not enough to reconstruct topology.

GeoPackage is not supported and has no plans to be: convert it to a shapefile first (e.g. via sf::st_write(sf::st_read("file.gpkg"), "file.shp"), or with any GIS tool) and use that instead.

output

One of "graph" (default, returns a ready-to-use cppRouting_graph), "data.frame", or "csv". Common to every source.

out_prefix

Path prefix used when output = "csv". Common to every source.

coords

logical. If TRUE (default), extract each node's coordinates: written to <out_prefix>_coords.csv (output = "csv", including the .pbf max_mem disk-backed pipeline), returned as a data.frame(node_id, X, Y) (output = "data.frame"), or passed to makegraph(coords = ...) (output = "graph"). Set to FALSE to skip this – e.g. if you already have node coordinates elsewhere and only need the graph topology. For the max_mem pipeline this also skips an entire external sort/merge pass, a real saving in disk I/O and time at continent scale, not just a smaller output. If the source coordinates are geographic (lat/lon – always true for .pbf/osmdata) and coords = TRUE, epsg must be supplied (see below), otherwise this errors rather than silently returning coordinates that break the A*/NBA algorithms (see get_distance_pair). Common to every source.

epsg

Optional. A projected EPSG code (or anything sf::st_crs() accepts) to reproject node coordinates into, via sf::st_transform() (requires the sf package). Only takes effect if coords = TRUE and the source CRS is geographic; already-projected coordinates (possible for shapefile/sf sources) are left as-is regardless. Together with osm_params$max_mem on a .pbf source, the reprojection runs in row chunks sized from the max_mem budget, so peak RAM stays within that budget even on the disk-backed pipeline. Common to every source.

keep_length

logical. If TRUE, keep each edge's length (in km) as aux, regardless of how the main cost was actually resolved – e.g. to get a time-based graph while still reporting physical distance. Shapefile/sf sources: the geometric length (unreliable for a geographic CRS, same caveat as geom_params$length_field below – reproject or use geom_params$keep_fields with your own length column instead in that case). OSM sources: the haversine length. output = "csv" carries the same information as output = "data.frame": aux is written to ⁠<out_prefix>_aux.csv⁠. Common to every source.

snap_digits

integer. Shapefile/sf sources: decimal places used to round coordinates before deduplicating line endpoints into nodes. osmdata sources: decimal places used to match line vertex coordinates against $osm_points coordinates. Unused for .pbf (topology comes from OSM node ids directly, no coordinate matching needed). Defaults (NULL) to 7 for geographic (lat/lon) coordinates or 4 for projected (meter-scale) ones – geographic coordinates need many decimal places to distinguish nearby points, but that precision is far too tight for projected coordinates, where it starts picking up floating-point noise between independently-digitized but logically-identical points rather than real geometric differences. The one argument that doesn't sort cleanly into osm_params/geom_params: it applies to shapefile/sf sources and to osmdata, but not to .pbf.

osm_params

A list of options for OSM sources (.pbf/osmdata/osmextract) only, ignored for shapefile/sf. Any subset may be supplied – omitted elements keep their default below; an unrecognized element name raises an error immediately (rather than silently keeping its default, which is what a typo'd list element would otherwise do). Recognized elements:

  • mode: one of "car" (default), "foot", "bicycle" or "hgv" – which access-tag/oneway resolution rules to apply (see graph_from_osmpbf's @details for the exact tags checked per mode). If profile is left NULL, also selects the matching default profile (osm_car_profile/osm_foot_profile/osm_bike_profile/ osm_hgv_profile).

  • profile: a data.frame with columns highway, clazz, speed (see osm_car_profile and friends): which highway tag values to keep, and their class id / default speed (km/h) when not overridden by maxspeed. Defaults (NULL) to the profile matching mode; pass your own to override independently of mode.

  • use_maxspeed: logical, default TRUE. If TRUE, a way's maxspeed tag overrides the profile's default speed when present and parseable (plain km/h, or "<n> mph"). No effect for mode = "foot"/"bicycle".

  • assume_oneway_motorway: logical, default TRUE. If TRUE, motorway/ motorway_link ways are treated as one-way unless explicitly tagged oneway=no. Irrelevant for mode = "foot" (oneway is always ignored for that mode).

  • keep_clazz: logical, default FALSE. If TRUE, keep each edge's resolved highway class id as aux.

  • max_mem: .pbf only (ignored for osmdata). A budget in megabytes for a disk-backed pipeline that spills every intermediate table (not just the final result) to disk, keeping peak RAM close to this budget regardless of the input file's size – for files too large to fit in RAM even with the default pipeline (e.g. a full-planet extract). Requires output = "csv". See graph_from_osmpbf for details and the (rare but possible) requirement that nodes appear in increasing id order in the file.

  • tmp_path: .pbf only. Directory for temporary files when max_mem is set. Defaults to tempdir().

  • progress: logical, default TRUE. Print progress messages while reading/matching.

geom_params

A list of options for shapefile/sf sources only, ignored for OSM sources. Any subset may be supplied – omitted elements keep their default below; an unrecognized element name raises an error immediately (same reasoning as osm_params above). Recognized elements:

  • cost_field: optional, name of a numeric attribute column to use directly as edge cost.

  • speed_field: optional, name of a numeric attribute column holding a speed in km/h. Used with length_field (in km) to derive a cost in minutes as 60 * length / speed. Ignored if cost_field is provided.

  • length_field: optional, name of a numeric attribute column holding each line's length, in km (to match the 60 * length / speed formula above). If NULL and speed_field is used, length is instead computed from the line geometry itself and converted from the CRS's native unit (assumed to be meters, true for any typical projected CRS) to km.

  • direction_field: optional, name of an attribute column describing the direction of travel allowed on each line (e.g. a "sens" column). Combined with direction_values.

  • direction_values: optional, a list with up to three character vectors: forward (only from the line's first point to its last), backward (only from last to first) and twoway (both directions). Values of direction_field not listed anywhere default to twoway, with a warning.

  • directed: logical, default FALSE. Used only when direction_field is NULL. If TRUE, every line is kept as digitized (first point to last point); if FALSE, every line is made bidirectional.

  • keep_fields: optional character vector of extra attribute columns to keep as aux (see makegraph).

Details

Arguments are grouped by which family of source they apply to: arguments that work the same way regardless of source stay as their own top-level parameter; source-specific ones are grouped into the osm_params or geom_params list (see those two parameters below for the full list of what each one accepts) – so a shapefile/sf call never needs to mention profile/ use_maxspeed, and a .pbf/osmdata/osmextract call never needs to mention cost_field/direction_field.

Shapefile/sf sources are assumed to already be topologically clean, i.e. lines only meet at their endpoints. OSM sources (.pbf or osmdata) instead detect junctions in the middle of a way from OSM's own node ids (a node referenced by 2 or more kept ways, or a way's own endpoint); for .pbf, a way referencing a node outside the file (a regional extract cut through it) is dropped entirely, and for osmdata, a way with a vertex that can't be matched against $osm_points is dropped, with a warning. A plain sf object that looks OSM-derived (it has an osm_id column) but isn't the full osmdata result is refused with an explanatory error, rather than silently treated as topologically clean like a plain sf source and producing a wrong graph.

Value

Depending on output: a cppRouting_graph, a named list of two data.frames (data, coords), or (invisibly) the paths of the written CSV files. For output = "data.frame", from/to/node_id are character regardless of source: a node id is a label, not a quantity, matching what makegraph() itself already guarantees for dict$ref. For output = "graph", that same real id is carried through dict$ref; data$from/data$to stay makegraph()'s own compact integer index (its adjacency list is always built on that, not on the original id).


cppRouting documentation built on Nov. 12, 2026, 5:11 p.m.