use crate::transition::candidate::*;
use core::ops::Deref;
use routers_network::{Edge, Entry, Metadata, Network, Node};
use serde::Serialize;
use geo::Coord;
#[derive(Serialize, Debug)]
pub struct RoutedPath<E, M>
where
E: Entry,
M: Metadata,
{
pub discretized: Path<E, M>,
pub interpolated: Path<E, M>,
}
impl<E, M> RoutedPath<E, M>
where
E: Entry,
M: Metadata,
{
pub fn new(collapsed_path: CollapsedPath<E>, network: &impl Network<E, M>) -> Self {
let matched: Vec<Candidate<E>> = collapsed_path
.route
.iter()
.flat_map(|id| collapsed_path.candidates.candidate(id))
.collect();
let discretized = matched
.iter()
.flat_map(|c| PathElement::new(*c, network))
.collect::<Path<E, M>>();
let interpolated = {
let mut elements: Vec<_> = collapsed_path
.interpolated
.iter()
.enumerate()
.flat_map(|(i, reachable)| {
matched
.get(i)
.map(|m| &m.edge)
.into_iter()
.chain(reachable.path.iter())
})
.chain(matched.last().map(|m| &m.edge))
.filter_map(|edge| {
network
.fatten(edge)
.and_then(|fat| PathElement::from_fat(fat, network))
})
.collect::<Vec<PathElement<E, M>>>();
elements.dedup_by(|a, b| {
(a.edge.source.identifier(), a.edge.target.identifier())
== (b.edge.source.identifier(), b.edge.target.identifier())
});
Path { elements }
};
RoutedPath {
discretized,
interpolated,
}
}
}
#[derive(Debug, Serialize)]
pub struct Path<E, M>
where
E: Entry,
M: Metadata,
{
pub elements: Vec<PathElement<E, M>>,
}
impl<E, M> FromIterator<PathElement<E, M>> for Path<E, M>
where
E: Entry,
M: Metadata,
{
fn from_iter<I: IntoIterator<Item = PathElement<E, M>>>(iter: I) -> Self {
let elements = iter.into_iter().collect::<Vec<_>>();
Path { elements }
}
}
impl<E, M> Deref for Path<E, M>
where
E: Entry,
M: Metadata,
{
type Target = Vec<PathElement<E, M>>;
fn deref(&self) -> &Self::Target {
&self.elements
}
}
#[derive(Debug, Serialize)]
pub struct PathElement<E, M>
where
E: Entry,
M: Metadata,
{
pub point: Coord,
pub edge: Edge<Node<E>>,
pub metadata: M,
}
impl<E, M> PathElement<E, M>
where
E: Entry,
M: Metadata,
{
pub fn new(candidate: Candidate<E>, network: &impl Network<E, M>) -> Option<Self> {
Some(PathElement {
point: candidate.position.0,
edge: network.fatten(&candidate.edge)?,
metadata: network.metadata(candidate.edge.id())?.clone(),
})
}
pub fn from_fat(edge: Edge<Node<E>>, network: &impl Network<E, M>) -> Option<Self> {
Some(PathElement {
point: edge.source.position.0,
metadata: network.metadata(edge.id())?.clone(),
edge,
})
}
}