1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
use num_traits::FromPrimitive;
use crate::algorithm::haversine_distance::HaversineDistance;
use crate::{CoordFloat, Line, LineString, MultiLineString};
/// Determine the length of a geometry using the [haversine formula].
///
/// [haversine formula]: https://en.wikipedia.org/wiki/Haversine_formula
///
/// *Note*: this implementation uses a mean earth radius of 6371.088 km, based on the [recommendation of
/// the IUGG](ftp://athena.fsv.cvut.cz/ZFG/grs80-Moritz.pdf)
pub trait HaversineLength<T, RHS = Self> {
/// Determine the length of a geometry using the [haversine formula].
///
/// # Units
///
/// - return value: meters
///
/// # Examples
///
/// ```
/// use geo::prelude::*;
/// use geo::LineString;
///
/// let linestring = LineString::<f64>::from(vec![
/// // New York City
/// (-74.006, 40.7128),
/// // London
/// (-0.1278, 51.5074),
/// ]);
///
/// let length = linestring.haversine_length();
///
/// assert_eq!(
/// 5_570_230., // meters
/// length.round()
/// );
/// ```
///
/// [haversine formula]: https://en.wikipedia.org/wiki/Haversine_formula
fn haversine_length(&self) -> T;
}
impl<T> HaversineLength<T> for Line<T>
where
T: CoordFloat + FromPrimitive,
{
fn haversine_length(&self) -> T {
let (start, end) = self.points();
start.haversine_distance(&end)
}
}
impl<T> HaversineLength<T> for LineString<T>
where
T: CoordFloat + FromPrimitive,
{
fn haversine_length(&self) -> T {
self.lines().fold(T::zero(), |total_length, line| {
total_length + line.haversine_length()
})
}
}
impl<T> HaversineLength<T> for MultiLineString<T>
where
T: CoordFloat + FromPrimitive,
{
fn haversine_length(&self) -> T {
self.0
.iter()
.fold(T::zero(), |total, line| total + line.haversine_length())
}
}