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}