geo/algorithm/
geodesic_length.rs

1use crate::GeodesicDistance;
2use crate::{Line, LineString, MultiLineString};
3
4/// Determine the length of a geometry on an ellipsoidal model of the earth.
5///
6/// This uses the geodesic measurement methods given by [Karney (2013)]. As opposed to older methods
7/// like Vincenty, this method is accurate to a few nanometers and always converges.
8///
9/// [Karney (2013)]:  https://arxiv.org/pdf/1109.4448.pdf
10pub trait GeodesicLength<T, RHS = Self> {
11    /// Determine the length of a geometry on an ellipsoidal model of the earth.
12    ///
13    /// This uses the geodesic measurement methods given by [Karney (2013)]. As opposed to older methods
14    /// like Vincenty, this method is accurate to a few nanometers and always converges.
15    ///
16    ///
17    /// # Units
18    ///
19    /// - return value: meters
20    ///
21    /// # Examples
22    ///
23    /// ```
24    /// use geo::prelude::*;
25    /// use geo::LineString;
26    ///
27    /// let linestring = LineString::from(vec![
28    ///     // New York City
29    ///     (-74.006, 40.7128),
30    ///     // London
31    ///     (-0.1278, 51.5074),
32    ///     // Osaka
33    ///     (135.5244559, 34.687455)
34    /// ]);
35    ///
36    /// let length = linestring.geodesic_length();
37    ///
38    /// assert_eq!(
39    ///     15_109_158., // meters
40    ///     length.round()
41    /// );
42    /// ```
43    ///
44    /// [Karney (2013)]:  https://arxiv.org/pdf/1109.4448.pdf
45    fn geodesic_length(&self) -> T;
46}
47
48impl GeodesicLength<f64> for Line {
49    /// The units of the returned value is meters.
50    fn geodesic_length(&self) -> f64 {
51        let (start, end) = self.points();
52        start.geodesic_distance(&end)
53    }
54}
55
56impl GeodesicLength<f64> for LineString {
57    fn geodesic_length(&self) -> f64 {
58        let mut length = 0.0;
59        for line in self.lines() {
60            length += line.geodesic_length();
61        }
62        length
63    }
64}
65
66impl GeodesicLength<f64> for MultiLineString {
67    fn geodesic_length(&self) -> f64 {
68        let mut length = 0.0;
69        for line_string in &self.0 {
70            length += line_string.geodesic_length();
71        }
72        length
73    }
74}