osmnxr-core
Street-network graph algorithms for OpenStreetMap-style networks, with no dependencies. This crate is the compute core of osmnxr, the R package that brings OSMnx to R: the R layer downloads, models and draws; this crate does the graph math.
It knows nothing about OpenStreetMap, geometry or coordinate systems. A caller hands it edge lists of 0-based node indices with weights and gets back node paths, edge indices, distances and scores. Everything it returns points back into the caller's own data, so attributes and geometry can be recovered exactly, parallel edges included.
Website: https://strategicprojects.github.io/osmnxr-core/ · API: https://strategicprojects.github.io/osmnxr-core/api/osmnxr_core/
What is in it
| Module | Contents |
|---|---|
graph |
Graph: a compressed-sparse-row directed graph built from parallel from/to/weight vectors. |
routing |
Dijkstra; shortest paths that report the edges traversed; Yen's k loopless shortest paths; distance matrices; a travelling-salesman heuristic (nearest neighbour + iterated local search, exact moves on asymmetric matrices, fixed seed); the Pareto front of bicriteria paths by Martins' label-setting, which with a budget is the exact constrained shortest path; and the LARAC Lagrangian relaxation, one Dijkstra per iteration with a proven lower bound, for graphs where exact search is slow. |
centrality |
Betweenness (Brandes) and closeness, with the usual normalisations. |
metrics |
Basic network statistics, compass bearings and the orientation entropy of a street grid. |
simplify |
Topology simplification (maximal chains of degree-2 nodes between endpoints) and connected components. |
spatial |
A uniform-grid index that snaps points to the nearest polyline, with the position along it. |
Example
use Graph;
use ;
// a square 0 -> 1 -> 2 -> 3 -> 0 with a diagonal 0 -> 2
let from = ;
let to = ;
let length = ;
let g = from_edges;
assert_eq!;
let = shortest_path_route.unwrap;
assert_eq!;
// two criteria: length and, say, a penalty for the diagonal
let penalty = ;
let front = pareto_paths;
assert_eq!; // (2.5, 5.0) through the diagonal, (3.0, 0.0) around
cargo run --example grid walks a 3 × 3 grid through shortest path,
alternatives, the Pareto front and a budgeted query.
Install
Rust 1.81 or later. No dependencies, no features, no unsafe.
Conventions
- Nodes are
0 .. n_nodes. Edges are directed: a two-way street is two edges. - Weights are nonnegative and finite. The caller decides what they mean (metres, seconds, a penalty).
- Functions that return edges give indices into the caller's input order.
routing::shortest_path_routereturns CSR slots instead; map them withrouting::csr_edge_orderwhen you need input order. - Unreachable is
f64::INFINITY, an empty path orNone. No value is made up.
How it is checked
- The Pareto front is compared with brute-force enumeration of every simple path on random graphs.
- The travelling-salesman heuristic was benchmarked from R against
TSP::solve_TSPon the same cost matrices: 54 wins, 26 ties and no losses over 80 instances of 8 to 50 stops, matching brute force where feasible. - The LARAC solver found the exact optimum in every one of eight scenarios on the Delhi road network (1.0 million nodes, 2.1 million directed edges); the exact front is still the default in osmnxr, LARAC the fallback for size.
- CI runs
cargo fmt,clippy -D warnings, the tests and the docs on Linux, macOS and Windows, on the oldest supported Rust (1.81) and forwasm32-unknown-unknown.
Family
Acknowledgements
The design follows OSMnx by Geoff Boeing. The algorithms come from the literature: Dijkstra (1959), Yen (1971), Brandes (2001), Martins (1984) for the bicriteria front, Jüttner et al. (2001) for LARAC, and Martin, Otto and Felten (1991) for the double-bridge kick.
License
MIT. See LICENSE-MIT.