use std::collections::HashMap;
use std::error::Error;
use petgraph::{graph::UnGraph, adj::NodeIndex};
use crate::api::Element;
use super::{
way::{OSMWay, get_osm_ways},
node::{OSMNode, node_dist, get_osm_nodes},
edge::OSMEdge
};
pub type OSMGraph = UnGraph<OSMNode, OSMEdge>;
pub fn create_graph(elements: &Vec<Element>) -> Result<OSMGraph, Box<dyn Error>> {
let ways: Vec<OSMWay> = get_osm_ways(elements)?;
let nodes: Vec<OSMNode> = get_osm_nodes(elements)?;
let mut result = UnGraph::<OSMNode, OSMEdge>::with_capacity(nodes.len(), ways.len());
let mut node_mapping: HashMap<u64, NodeIndex> = HashMap::with_capacity(nodes.len());
for node in nodes {
let petgraph_index = result.add_node(node.clone()).index() as u32;
node_mapping.insert(
node.id(),
petgraph_index
);
}
for way in ways {
let nodes = way.nodes();
for window in nodes.windows(2) {
let node_id_1: u64 = window[0];
let node_id_2: u64 = window[1];
let node_index_1: NodeIndex = node_mapping[&node_id_1];
let node_index_2: NodeIndex = node_mapping[&node_id_2];
let n1: &OSMNode = result.node_weight(node_index_1.into()).unwrap();
let n2: &OSMNode = result.node_weight(node_index_2.into()).unwrap();
result.add_edge(
node_index_1.into(), node_index_2.into(),
OSMEdge::new([n1.id(), n2.id()], node_dist(n1,n2), way.highway_type().to_string())
);
}
}
Ok(result)
}