1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
//! This module provides Python bindings for importing and interacting with railway graphs.
//!
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use pythonize::pythonize;
use crate::importer::overpass_importer::OverpassImporter;
use crate::importer::RailwayGraphImporter;
use crate::railway_model::railway_graph::RailwayGraphExt;
use crate::railway_model::RailwayGraph;
use crate::types::{EdgeId, NodeId};
mod overpass_api_client;
/// A Python wrapper for the OverpassImporter struct.
#[pyclass]
pub struct PyOverpassImporter {}
#[pymethods]
impl PyOverpassImporter {
/// Create a new PyOverpassImporter instance.
#[new]
fn new() -> Self {
PyOverpassImporter {}
}
/// Import railway graph data from a JSON string.
///
/// # Arguments
///
/// * `input` - A JSON string containing railway graph data.
///
/// # Returns
///
/// * A PyRailwayGraph instance containing the imported railway graph data.
fn import_graph(&self, input: &str) -> PyResult<PyRailwayGraph> {
let json_value: serde_json::Value = serde_json::from_str(input)
.map_err(|err| PyErr::new::<pyo3::exceptions::PyValueError, _>(format!("{}", err)))?;
let railway_graph = OverpassImporter::import(&json_value)
.map_err(|err| PyErr::new::<pyo3::exceptions::PyValueError, _>(format!("{}", err)))?;
Ok(PyRailwayGraph {
inner: railway_graph,
})
}
}
/// Export a PyRailwayGraph to an SVG string.
///
/// This function generates an SVG representation of the given PyRailwayGraph.
///
/// # Arguments
///
/// * `graph` - A reference to the PyRailwayGraph to be exported.
///
/// # Returns
///
/// * A PyResult containing a String of the SVG representation of the graph, or an error if the
/// conversion failed.
#[pyfunction]
pub fn export_svg(graph: &PyRailwayGraph) -> PyResult<String> {
Ok(crate::export::generate_svg_string(&graph.inner).unwrap())
}
/// A Python wrapper for the RailwayGraph struct.
#[pyclass]
pub struct PyRailwayGraph {
inner: RailwayGraph,
}
#[pymethods]
impl PyRailwayGraph {
/// Get the number of nodes in the railway graph.
///
/// # Returns
///
/// * The number of nodes in the railway graph.
fn node_count(&self) -> usize {
self.inner.physical_graph.graph.node_count()
}
/// Get the number of edges in the railway graph.
///
/// # Returns
///
/// * The number of edges in the railway graph.
fn edge_count(&self) -> usize {
self.inner.physical_graph.graph.edge_count()
}
/// Get a node by its ID from the railway graph.
///
/// # Arguments
///
/// * `node_id` - The ID of the node to retrieve.
///
/// # Returns
///
/// * An optional `RailwayNode` instance if the node with the specified ID is found.
fn get_node_by_id(&self, node_id: NodeId) -> Option<PyObject> {
Some(Python::with_gil(|py| {
pythonize(py, &self.inner.get_node_by_id(node_id).unwrap())
.unwrap()
.to_object(py)
}))
}
/// Get an edge by its ID from the railway graph.
///
/// # Arguments
///
/// * `edge_id` - The ID of the edge to retrieve.
///
/// # Returns
///
/// * An optional `RailwayEdge` instance if the edge with the specified ID is found.
fn get_edge_by_id(&self, edge_id: EdgeId) -> Option<PyObject> {
Some(Python::with_gil(|py| {
pythonize(py, &self.inner.get_edge_by_id(edge_id))
.unwrap()
.to_object(py)
}))
}
}
/// Initialize the openrailwaymap_exporter Python module.
///
/// # Arguments
///
/// * `_py` - The Python interpreter state.
/// * `m` - The Python module object.
///
/// # Returns
///
/// * A PyResult indicating the success or failure of the module initialization.
#[pymodule]
fn openrailwaymap_exporter(py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<PyOverpassImporter>()?;
m.add_class::<PyRailwayGraph>()?;
m.add_function(wrap_pyfunction!(export_svg, m)?)?;
overpass_api_client::init_overpass_api_client(py, m)?;
Ok(())
}