osm_graph 0.2.0

This library provides a set of tools for generating isochrones from geographic coordinates. It leverages OpenStreetMap data to construct road networks and calculate areas accessible within specified time limits. The library is designed for both Rust and Python, offering high performance and easy integration into data science workflows.
Documentation
# Rust API

The Rust API exposes the same core functionality without Python overhead.
All async functions require a Tokio runtime.

Full generated API documentation is published alongside this site:  
**[Rust API docs →](https://kyleloving.github.io/osm_graph/rust/osm_graph/index.html)**

---

## Quick example

```rust
use osm_graph::isochrone::{calculate_isochrones_from_point, HullType};
use osm_graph::overpass::NetworkType;

#[tokio::main]
async fn main() {
    let (isochrones, graph) = calculate_isochrones_from_point(
        48.137144,
        11.575399,
        Some(10_000.0),                                        // max_dist in metres; None = auto
        vec![300.0, 600.0, 900.0, 1_200.0, 1_500.0, 1_800.0],
        NetworkType::Drive,
        HullType::Concave,
        false,                                                 // false = simplified (faster)
    )
    .await
    .unwrap();

    println!("{} isochrones, {} nodes", isochrones.len(), graph.graph.node_count());
}
```

---

## Key types

### `NetworkType`

```rust
pub enum NetworkType {
    Drive,
    DriveService,
    Walk,
    Bike,
    All,
    AllPrivate,
}
```

Controls which OSM highway tags are included in the graph.  See the [Quickstart](quickstart.md#choosing-a-network-type) for details.

---

### `HullType`

```rust
pub enum HullType {
    Convex,
    FastConcave,
    Concave,
}
```

Controls how the isochrone boundary is computed from the set of reachable nodes.

---

### `SpatialGraph`

```rust
pub struct SpatialGraph {
    pub graph: Arc<DiGraph<XmlNode, XmlWay>>,
    // internal R-tree omitted
}
```

A petgraph `DiGraph` bundled with an R-tree spatial index.  Both inner fields are
`Arc`-wrapped, so cloning a `SpatialGraph` is O(1).

```rust
// Nearest-node lookup — O(log n)
let node_idx = sg.nearest_node(lat, lon)?;

// Direct petgraph access
let node_count = sg.graph.node_count();
let edge_count = sg.graph.edge_count();
```

---

### `XmlNode`

```rust
pub struct XmlNode {
    pub id: i64,
    pub lat: f64,
    pub lon: f64,
    pub tags: Vec<XmlTag>,
    pub geohash: Option<String>,
}
```

---

### `XmlWay`

```rust
pub struct XmlWay {
    pub id: i64,
    pub tags: Vec<XmlTag>,
    pub length: f64,           // metres
    pub speed_kph: f64,
    pub walk_travel_time: f64, // seconds
    pub bike_travel_time: f64, // seconds
    pub drive_travel_time: f64,// seconds
}
```

---

## Core functions

### `calculate_isochrones_from_point`

```rust
pub async fn calculate_isochrones_from_point(
    lat: f64,
    lon: f64,
    max_dist: Option<f64>,
    time_limits: Vec<f64>,
    network_type: NetworkType,
    hull_type: HullType,
    retain_all: bool,
) -> Result<(Vec<Polygon>, SpatialGraph), OsmGraphError>
```

Fetch (or cache-hit) the road network, run a single Dijkstra pass, and compute
hull polygons for each time limit in parallel threads.

Pass `max_dist = None` to auto-size the bounding box from the largest time limit.
Pass `time_limits = vec![]` to skip isochrone computation and only obtain the `SpatialGraph`.

---

### `routing::route`

```rust
pub fn route(
    sg: &SpatialGraph,
    origin_lat: f64,
    origin_lon: f64,
    dest_lat: f64,
    dest_lon: f64,
    network_type: NetworkType,
) -> Result<Route, OsmGraphError>
```

A\* point-to-point routing.  Returns a `Route`:

```rust
pub struct Route {
    pub coordinates: Vec<(f64, f64)>,   // (lat, lon) per waypoint
    pub cumulative_times_s: Vec<f64>,   // parallel to coordinates
    pub distance_m: f64,
    pub duration_s: f64,
}
```

---

### `overpass::bbox_from_point`

```rust
pub fn bbox_from_point(lat: f64, lon: f64, dist: f64) -> String
```

Construct a `south,west,north,east` bounding-box string for an Overpass API query.

---

### `overpass::make_request`

```rust
pub async fn make_request(url: &str, query: &str) -> Result<String, reqwest::Error>
```

POST a query to an Overpass API endpoint and return the raw XML response.

---

## Error type

```rust
pub enum OsmGraphError {
    XmlParseError(quick_xml::DeError),
    RequestError(reqwest::Error),
    EmptyGraph,
    NodeNotFound,
    InvalidInput(String),
    CacheError(String),
}
```