use super::Distance;
use crate::{CoordFloat, Line, LineString, MultiLineString, Point};
pub trait Length<F: CoordFloat> {
fn length<MetricSpace: Distance<F, Point<F>, Point<F>>>(&self) -> F;
}
impl<F: CoordFloat> Length<F> for Line<F> {
fn length<MetricSpace: Distance<F, Point<F>, Point<F>>>(&self) -> F {
MetricSpace::distance(self.start_point(), self.end_point())
}
}
impl<F: CoordFloat> Length<F> for LineString<F> {
fn length<MetricSpace: Distance<F, Point<F>, Point<F>>>(&self) -> F {
let mut length = F::zero();
for line in self.lines() {
length = length + line.length::<MetricSpace>();
}
length
}
}
impl<F: CoordFloat> Length<F> for MultiLineString<F> {
fn length<MetricSpace: Distance<F, Point<F>, Point<F>>>(&self) -> F {
let mut length = F::zero();
for line in self {
length = length + line.length::<MetricSpace>();
}
length
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{coord, Euclidean, Geodesic, Haversine, Rhumb};
#[test]
fn lines() {
let line = Line::new(
coord!(x: -0.1278f64, y: 51.5074),
coord!(x: 2.3522, y: 48.8566),
);
assert_eq!(
343_923., line.length::<Geodesic>().round()
);
assert_eq!(
341_088., line.length::<Rhumb>().round()
);
assert_eq!(
343_557., line.length::<Haversine>().round()
);
assert_eq!(
4., line.length::<Euclidean>().round()
);
let projected_line = Line::new(
coord!(x: 3620451.74f64, y: 3203901.44),
coord!(x: 3760771.86, y: 2889484.80),
);
assert_eq!(344_307., projected_line.length::<Euclidean>().round());
}
#[test]
fn line_strings() {
let line_string = LineString::new(vec![
coord!(x: -58.3816f64, y: -34.6037), coord!(x: -77.0428, y: -12.0464), coord!(x: -47.9292, y: -15.7801), ]);
assert_eq!(
6_302_220., line_string.length::<Geodesic>().round()
);
assert_eq!(
6_332_790., line_string.length::<Rhumb>().round()
);
assert_eq!(
6_304_387., line_string.length::<Haversine>().round()
);
assert_eq!(
59., line_string.length::<Euclidean>().round()
);
let projected_line_string = LineString::from(vec![
coord!(x: 143042.46f64, y: -1932485.45), coord!(x: -1797084.08, y: 583528.84), coord!(x: 1240052.27, y: 207169.12), ]);
assert_eq!(
6_237_538.,
projected_line_string.length::<Euclidean>().round()
);
}
}