use geo::Point;
use routers_network::{DirectionAwareEdgeId, Metadata, Node};
use rustc_hash::FxHashMap;
use crate::overture::element::{Connector, Segment};
use crate::overture::graph::{GraphStructure, OvertureNetwork};
use crate::overture::id::OvertureEntryId;
use crate::overture::meta::OvertureEdgeMetadata;
use crate::overture::parsers::Heading;
pub fn build(connectors: Vec<Connector>, segments: Vec<Segment>) -> OvertureNetwork {
let mut hash: FxHashMap<OvertureEntryId, Node<OvertureEntryId>> = FxHashMap::default();
for connector in &connectors {
hash.insert(connector.id, Node::new(connector.position, connector.id));
}
let mut next_synthetic = connectors
.iter()
.map(|c| c.id.identifier)
.chain(segments.iter().map(|s| s.id.identifier))
.max()
.unwrap_or(-1)
+ 1;
let mut graph = GraphStructure::new();
let mut meta: FxHashMap<OvertureEntryId, OvertureEdgeMetadata> = FxHashMap::default();
for segment in &segments {
if !segment.navigable() {
continue;
}
let weight = segment.weight();
let forward = segment.open(Heading::Forward);
let backward = segment.open(Heading::Backward);
let direction_aware = DirectionAwareEdgeId::new(segment.id);
meta.insert(segment.id, OvertureEdgeMetadata::pick(segment));
for pair in segment.connectors.windows(2) {
if let [a, b] = pair {
if !hash.contains_key(&a.id) || !hash.contains_key(&b.id) {
continue;
}
let chain: Vec<OvertureEntryId> = core::iter::once(a.id)
.chain(segment.interior_vertices(a.at, b.at).map(|coord| {
let id = OvertureEntryId::new(next_synthetic);
next_synthetic += 1;
hash.insert(id, Node::new(Point(coord), id));
id
}))
.chain(core::iter::once(b.id))
.collect();
for hop in chain.windows(2) {
if let [s, t] = hop {
if forward {
graph.add_edge(*s, *t, (weight, direction_aware.forward()));
}
if backward {
graph.add_edge(*t, *s, (weight, direction_aware.backward()));
}
}
}
}
}
}
let mut pruned: FxHashMap<OvertureEntryId, Node<OvertureEntryId>> = FxHashMap::default();
for (id, node) in hash {
if graph.contains_node(id) {
pruned.insert(id, node);
}
}
let mut network = OvertureNetwork {
graph,
hash: pruned,
meta,
index: Default::default(),
index_edge: Default::default(),
};
network.rebuild_indices();
network
}