solverforge-maps
Generic map and routing utilities for Vehicle Routing Problems (VRP) and similar optimization problems.
Features
- OSM Road Network: Download and cache OpenStreetMap road data via Overpass API
- R-Tree Spatial Indexing: O(log n) coordinate snapping to road network
- Shortest Path Routing: Dijkstra/A* routing with travel times and distances
- Travel Time Matrix: Compute all-pairs travel times with parallel computation
- Route Geometry: Full road-following geometries with Douglas-Peucker simplification
- Polyline Encoding: Google Polyline Algorithm for efficient route transmission
- Input Validation: Fail-fast coordinate and bounding box validation
- Cache Management: In-memory and file-based caching with inspection and eviction
- Graph Analysis: Connectivity analysis for debugging routing failures
- Zero-Erasure Design: No
Arc, noBox<dyn>, concrete types throughout
Installation
[]
= "1.0"
= { = "1", = ["full"] }
Quick Start
use ;
async
API Reference
Coord
Geographic coordinate with latitude and longitude. Validates input on construction.
use ;
// Panics on invalid input (NaN, infinite, out of range)
let coord = new;
// Fallible construction
let coord: = try_new;
assert!;
// Valid ranges: lat [-90, 90], lng [-180, 180]
let coord = try_new.unwrap;
// Distance calculation
let other = new;
let distance_meters = coord.distance_to;
// Tuple conversion
let from_tuple: = .try_into;
let to_tuple: = coord.into;
CoordError
BoundingBox
Rectangular geographic region. Validates that min < max on construction.
use ;
// Panics if min > max
let bbox = new;
// Fallible construction
let bbox: = try_new;
assert!;
// From coordinates
let locations = vec!;
let bbox = from_coords;
// Expansion methods
let expanded = bbox.expand; // Expand by ratio
let expanded = bbox.expand_meters; // Expand by meters
let expanded = bbox.expand_for_routing; // Smart expansion (1.4x detour factor)
// Queries
let center: Coord = bbox.center;
let contains: bool = bbox.contains;
BBoxError
NetworkConfig
Configuration for network loading and routing.
use ;
use Duration;
// Defaults
let config = default;
// Builder pattern
let config = new
.overpass_url
.cache_dir
.connect_timeout
.read_timeout
.speed_profile;
SpeedProfile
Speed profiles for different road types.
use SpeedProfile;
let profile = default;
// Get speed in meters per second (maxspeed tag, highway type)
let speed_mps = profile.speed_mps; // ~27.78 m/s (100 km/h default)
let speed_mps = profile.speed_mps; // ~13.89 m/s (50 km/h from tag)
| Highway Type | Default Speed |
|---|---|
| motorway | 100 km/h |
| trunk | 80 km/h |
| primary | 60 km/h |
| secondary | 50 km/h |
| tertiary | 40 km/h |
| residential | 30 km/h |
| unclassified | 30 km/h |
| service | 20 km/h |
| living_street | 10 km/h |
RoadNetwork
Core routing engine built from OSM data.
Loading a Network
use ;
let bbox = new;
let config = default;
// Load from cache or fetch from API (returns cached reference)
let network: NetworkRef = load_or_fetch.await?;
// Always fetch fresh (bypasses cache)
let network: RoadNetwork = fetch.await?;
NetworkRef is a zero-cost guard that provides access to the cached RoadNetwork. It implements Deref<Target = RoadNetwork> so all methods are available directly.
Routing
use ;
let from = new;
let to = new;
// Route by minimum travel time (default)
let route: = network.route;
// Route with specific objective
let route = network.route_with?; // Minimize time
let route = network.route_with?; // Minimize distance
// Access route data
println!;
println!;
println!;
// Simplify geometry for transmission (Douglas-Peucker algorithm)
let simplified = route.simplify; // tolerance in meters
Coordinate Snapping
use ;
let coord = new;
// Simple snap (returns None if network is empty)
let node = network.snap_to_road;
// Detailed snap with distance information
let snapped: = network.snap_to_road_detailed;
if let Ok = snapped
// Route between pre-snapped coordinates (more efficient for repeated routing)
let from_snap = network.snap_to_road_detailed?;
let to_snap = network.snap_to_road_detailed?;
let route = network.route_snapped?;
Network Statistics
let nodes: usize = network.node_count;
let edges: usize = network.edge_count;
// Connectivity analysis (useful for debugging routing failures)
let components: usize = network.strongly_connected_components;
let largest_fraction: f64 = network.largest_component_fraction;
let is_connected: bool = network.is_strongly_connected;
println!;
println!;
TravelTimeMatrix
Travel time matrix with metadata and analysis methods.
use ;
let locations = vec!;
// Compute matrix (async, parallel via rayon internally)
let matrix: TravelTimeMatrix = network.compute_matrix.await;
// Access travel times
let time: = matrix.get; // From location 0 to 1
let row: = matrix.row; // All times from location 0
let reachable: bool = matrix.is_reachable; // Check if pair is reachable
// Matrix metadata
let size: usize = matrix.size; // Number of locations
let locations: & = matrix.locations; // Snapped coordinates
// Statistics (excluding diagonal and unreachable pairs)
let min: = matrix.min;
let max: = matrix.max;
let mean: = matrix.mean;
// Reachability analysis
let ratio: f64 = matrix.reachability_ratio; // Fraction reachable
let unreachable: = matrix.unreachable_pairs;
// Raw data access
let data: & = matrix.as_slice; // Row-major flat array
The constant UNREACHABLE (i64::MAX) indicates pairs with no path.
Route Geometries
Compute geometries for all location pairs.
use Coord;
use HashMap;
let locations = vec!;
// Async computation
let geometries: =
network.compute_geometries.await;
// Access specific route geometry
if let Some = geometries.get
Cache Management
Inspect and manage the network cache.
use ;
// Get cache statistics
let stats: CacheStats = cache_stats.await;
println!;
println!;
println!;
println!;
println!;
// List cached regions
let regions: = cached_regions.await;
// Evict specific region
let bbox = new;
let evicted: bool = evict.await;
// Clear entire cache
clear_cache.await;
Progress Reporting
Stream progress updates during long operations.
use ;
use mpsc;
let = ;
spawn;
let network = load_or_fetch.await?;
let matrix = network.compute_matrix.await;
RoutingProgress Variants
| Variant | Description |
|---|---|
CheckingCache { percent } |
Checking in-memory and file caches |
DownloadingNetwork { percent, bytes } |
Downloading from Overpass API |
ParsingOsm { percent, nodes, edges } |
Parsing OSM JSON response |
BuildingGraph { percent } |
Building routing graph |
ComputingMatrix { percent, row, total } |
Computing travel time matrix |
ComputingGeometries { percent, pair, total } |
Computing route geometries |
EncodingGeometries { percent } |
Encoding geometries to polylines |
Complete |
Operation finished |
Polyline Encoding
Encode/decode route geometries using Google Polyline Algorithm.
use ;
let coords = vec!;
let encoded: String = encode_polyline;
let decoded: = decode_polyline;
Haversine Distance
Calculate great-circle distance between two coordinates.
use ;
let a = new;
let b = new;
let distance_meters = haversine_distance;
// Or use the method on Coord
let distance_meters = a.distance_to;
Error Handling
use ;
match network.route
Types Summary
Structs
| Type | Description |
|---|---|
Coord |
Geographic coordinate (lat, lng) |
BoundingBox |
Rectangular geographic region |
NetworkConfig |
Configuration for network loading |
SpeedProfile |
Road type speed mapping |
RoadNetwork |
Core routing graph |
NetworkRef |
Zero-cost reference to cached network |
RouteResult |
Single route with geometry |
SnappedCoord |
Coordinate snapped to road network |
TravelTimeMatrix |
N x N travel time matrix |
CacheStats |
Cache statistics and metrics |
EncodedSegment |
Pre-encoded route segment |
Enums
| Type | Description |
|---|---|
CoordError |
Coordinate validation errors |
BBoxError |
Bounding box validation errors |
RoutingError |
Routing operation errors |
RoutingProgress |
Progress reporting events |
Objective |
Routing objective (Time, Distance) |
Constants
| Constant | Value | Description |
|---|---|---|
UNREACHABLE |
i64::MAX |
Sentinel for unreachable pairs |
Caching
Three-tier caching for performance:
- In-Memory Cache: Instant lookup for repeated requests
- File Cache: Persists to
cache_dir(default.osm_cache/) - Overpass API: Downloads fresh data on cache miss
# Clear file cache
// Or programmatically
clear_cache.await;
License
Apache-2.0