geo/algorithm/
geodesic_destination.rs1use crate::Point;
2use geo_types::CoordNum;
3use geographiclib_rs::{DirectGeodesic, Geodesic};
4
5pub trait GeodesicDestination<T: CoordNum> {
11 fn geodesic_destination(&self, bearing: T, distance: T) -> Point<T>;
35}
36
37impl GeodesicDestination<f64> for Point<f64> {
38 fn geodesic_destination(&self, bearing: f64, distance: f64) -> Point<f64> {
39 let (lat, lon) = Geodesic::wgs84().direct(self.y(), self.x(), bearing, distance);
40 Point::new(lon, lat)
41 }
42}
43
44#[cfg(test)]
45mod test {
46 use super::*;
47 use crate::GeodesicDistance;
48
49 #[test]
50 fn returns_a_new_point() {
51 let p_1 = Point::new(9.177789688110352, 48.776781529534965);
52 let p_2 = p_1.geodesic_destination(45., 10000.);
53
54 assert_relative_eq!(
55 p_2,
56 Point::new(9.27411867078536, 48.8403266058781),
57 epsilon = 1.0e-6
58 );
59
60 let distance = p_1.geodesic_distance(&p_2);
61 assert_relative_eq!(distance, 10000., epsilon = 1.0e-6)
62 }
63
64 #[test]
65 fn bearing_zero_is_north() {
66 let p_1 = Point::new(9.177789688110352, 48.776781529534965);
67 let p_2 = p_1.geodesic_destination(0., 1000.);
68 assert_relative_eq!(p_1.x(), p_2.x(), epsilon = 1.0e-6);
69 assert!(p_2.y() > p_1.y())
70 }
71
72 #[test]
73 fn bearing_90_is_east() {
74 let p_1 = Point::new(9.177789688110352, 48.776781529534965);
75 let p_2 = p_1.geodesic_destination(90., 1000.);
76 assert_relative_eq!(p_1.y(), p_2.y(), epsilon = 1.0e-6);
77 assert!(p_2.x() > p_1.x())
78 }
79}