geo/algorithm/
haversine_length.rs

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