geo/algorithm/
geodesic_distance.rs

1use crate::Point;
2use geographiclib_rs::{Geodesic, InverseGeodesic};
3
4/// Determine the distance between two geometries 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 GeodesicDistance<T, Rhs = Self> {
11    /// Determine the distance between two geometries 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    /// # Units
17    ///
18    /// - return value: meters
19    ///
20    /// # Examples
21    /// ```rust
22    /// use geo::prelude::*;
23    /// use geo::point;
24    ///
25    /// // New York City
26    /// let p1 = point!(x: -74.006, y: 40.7128);
27    ///
28    /// // London
29    /// let p2 = point!(x: -0.1278, y: 51.5074);
30    ///
31    /// let distance = p1.geodesic_distance(&p2);
32    ///
33    /// assert_eq!(
34    ///     5_585_234., // meters
35    ///     distance.round()
36    /// );
37    /// ```
38    /// [Karney (2013)]:  https://arxiv.org/pdf/1109.4448.pdf
39    fn geodesic_distance(&self, rhs: &Rhs) -> T;
40}
41
42impl GeodesicDistance<f64> for Point {
43    fn geodesic_distance(&self, rhs: &Point) -> f64 {
44        Geodesic::wgs84().inverse(self.y(), self.x(), rhs.y(), rhs.x())
45    }
46}