use geo::{Coord, LineString};
use routers_network::edge::Weight;
use crate::overture::id::OvertureEntryId;
use crate::overture::parsers::{AccessRestriction, Heading, RoadClass, SpeedLimit};
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct SegmentConnector {
pub id: OvertureEntryId,
pub at: f64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Segment {
pub id: OvertureEntryId,
pub geometry: LineString,
pub connectors: Vec<SegmentConnector>,
pub road_class: Option<RoadClass>,
pub is_link: bool,
pub speed_limits: Vec<SpeedLimit>,
pub access: Vec<AccessRestriction>,
}
impl Segment {
pub fn new(
id: OvertureEntryId,
geometry: LineString,
mut connectors: Vec<SegmentConnector>,
road_class: Option<RoadClass>,
is_link: bool,
speed_limits: Vec<SpeedLimit>,
access: Vec<AccessRestriction>,
) -> Self {
connectors.sort_by(|a, b| {
a.at.partial_cmp(&b.at)
.unwrap_or(core::cmp::Ordering::Equal)
});
Segment {
id,
geometry,
connectors,
road_class,
is_link,
speed_limits,
access,
}
}
#[inline]
pub fn navigable(&self) -> bool {
self.road_class.is_some_and(|c| c.navigable()) && self.connectors.len() >= 2
}
#[inline]
pub fn weight(&self) -> Weight {
let base = self.road_class.map_or(Weight::MAX, |c| c.weighting());
if self.is_link {
base.saturating_add(1)
} else {
base
}
}
#[inline]
pub fn open(&self, heading: Heading) -> bool {
!self.access.iter().any(|a| a.denies_driving(heading))
}
pub fn interior_vertices(&self, from: f64, to: f64) -> impl Iterator<Item = Coord> + '_ {
let compression = self
.geometry
.0
.first()
.map_or(1.0, |c| c.y.to_radians().cos());
let mut cumulative = 0.0;
let lengths: Vec<f64> = core::iter::once(0.0)
.chain(self.geometry.lines().map(|line| {
cumulative += ((line.dx() * compression).powi(2) + line.dy().powi(2)).sqrt();
cumulative
}))
.collect();
let total = lengths.last().copied().unwrap_or(0.0);
let epsilon = total * 1e-3;
let (lo, hi) = (
from.min(to) * total + epsilon,
from.max(to) * total - epsilon,
);
self.geometry
.coords()
.copied()
.zip(lengths)
.filter(move |(_, at)| *at > lo && *at < hi)
.map(|(coord, _)| coord)
}
}