use crate::{ResolutionMethod, 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::new();
for (i, reachable) in collapsed_path.interpolated.iter().enumerate() {
let current = &matched[i];
if let Some(pe) = PathElement::new(*current, network) {
elements.push(pe);
}
if let ResolutionMethod::Standard = reachable.resolution_method {
if let Some(fat) = network.fatten(¤t.edge) {
if let Some(pe) = PathElement::from_fat(fat, network) {
elements.push(pe);
}
}
for edge in &reachable.path {
if let Some(fat) = network.fatten(edge) {
if let Some(pe) = PathElement::from_fat(fat, network) {
elements.push(pe);
}
if let Some(pe) = PathElement::from_fat(fat, network) {
elements.push(pe);
}
}
}
if let Some(next) = matched.get(i + 1) {
if let Some(fat) = network.fatten(&next.edge) {
if let Some(pe) = PathElement::from_fat(fat, network) {
elements.push(pe);
}
}
}
}
}
if let Some(last_candidate) = matched.last() {
if let Some(pe) = PathElement::new(*last_candidate, network) {
elements.push(pe);
}
}
elements.dedup_by(|a, b| a.point == b.point);
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,
})
}
}