geo/algorithm/
haversine_intermediate.rs

1use crate::{CoordFloat, Haversine, InterpolatePoint, Point};
2use num_traits::FromPrimitive;
3
4#[deprecated(
5    since = "0.29.0",
6    note = "Please use the `InterpolatePoint` trait instead"
7)]
8/// Returns a new Point along a great circle route between two existing points
9pub trait HaversineIntermediate<T: CoordFloat> {
10    #[deprecated(
11        since = "0.29.0",
12        note = "Please use `Haversine.point_at_ratio_between` from the `InterpolatePoint` trait instead"
13    )]
14    /// Returns a new `Point` along a great circle route between `self` and `other`.
15    ///
16    /// * `other` - The other point to interpolate towards.
17    /// * `ratio` - How far along the route should the new point be, with 0.0 being at `self`
18    ///   and 1.0 being at `other`.
19    ///
20    /// # Examples
21    ///
22    /// ```
23    /// # use approx::assert_relative_eq;
24    /// # #[allow(deprecated)]
25    /// use geo::HaversineIntermediate;
26    /// use geo::Point;
27    ///
28    /// let p1 = Point::new(10.0, 20.0);
29    /// let p2 = Point::new(125.0, 25.0);
30    ///
31    /// # #[allow(deprecated)]
32    /// let i20 = p1.haversine_intermediate(&p2, 0.2);
33    /// assert_relative_eq!(i20, Point::new(29.8, 29.9), epsilon = 0.2);
34    ///
35    /// # #[allow(deprecated)]
36    /// let i80 = p1.haversine_intermediate(&p2, 0.8);
37    /// assert_relative_eq!(i80, Point::new(103.5, 33.5), epsilon = 0.2);
38    /// ```
39    fn haversine_intermediate(&self, other: &Point<T>, ratio: T) -> Point<T>;
40
41    #[deprecated(
42        since = "0.29.0",
43        note = "Please use `Haversine.points_along_line` from the `InterpolatePoint` trait instead"
44    )]
45    /// Interpolates `Point`s along a great circle route between self and `other`.
46    ///
47    /// As many points as necessary will be added such that the distance between points
48    /// never exceeds `max_dist`.
49    ///
50    /// `include_ends`: Should the start and end points be included in the output?
51    fn haversine_intermediate_fill(
52        &self,
53        other: &Point<T>,
54        max_dist: T,
55        include_ends: bool,
56    ) -> Vec<Point<T>>;
57}
58
59#[allow(deprecated)]
60impl<T> HaversineIntermediate<T> for Point<T>
61where
62    T: CoordFloat + FromPrimitive,
63{
64    fn haversine_intermediate(&self, other: &Point<T>, ratio: T) -> Point<T> {
65        Haversine.point_at_ratio_between(*self, *other, ratio)
66    }
67
68    fn haversine_intermediate_fill(
69        &self,
70        other: &Point<T>,
71        max_dist: T,
72        include_ends: bool,
73    ) -> Vec<Point<T>> {
74        Haversine
75            .points_along_line(*self, *other, max_dist, include_ends)
76            .collect()
77    }
78}
79
80#[cfg(test)]
81mod test {
82    use super::*;
83    #[allow(deprecated)]
84    use crate::HaversineIntermediate;
85
86    #[test]
87    fn f_is_zero_or_one_test() {
88        let p1 = Point::new(10.0, 20.0);
89        let p2 = Point::new(15.0, 25.0);
90        #[allow(deprecated)]
91        let i0 = p1.haversine_intermediate(&p2, 0.0);
92        #[allow(deprecated)]
93        let i100 = p1.haversine_intermediate(&p2, 1.0);
94        assert_relative_eq!(i0.x(), p1.x(), epsilon = 1.0e-6);
95        assert_relative_eq!(i0.y(), p1.y(), epsilon = 1.0e-6);
96        assert_relative_eq!(i100.x(), p2.x(), epsilon = 1.0e-6);
97        assert_relative_eq!(i100.y(), p2.y(), epsilon = 1.0e-6);
98    }
99
100    #[test]
101    fn various_f_values_test() {
102        let p1 = Point::new(10.0, 20.0);
103        let p2 = Point::new(125.0, 25.0);
104        #[allow(deprecated)]
105        let i20 = p1.haversine_intermediate(&p2, 0.2);
106        #[allow(deprecated)]
107        let i50 = p1.haversine_intermediate(&p2, 0.5);
108        #[allow(deprecated)]
109        let i80 = p1.haversine_intermediate(&p2, 0.8);
110        let i20_should = Point::new(29.83519, 29.94841);
111        let i50_should = Point::new(65.87471, 37.72201);
112        let i80_should = Point::new(103.56036, 33.50518);
113        assert_relative_eq!(i20.x(), i20_should.x(), epsilon = 0.2);
114        assert_relative_eq!(i20.y(), i20_should.y(), epsilon = 0.2);
115        assert_relative_eq!(i50.x(), i50_should.x(), epsilon = 0.2);
116        assert_relative_eq!(i50.y(), i50_should.y(), epsilon = 0.2);
117        assert_relative_eq!(i80.x(), i80_should.x(), epsilon = 0.2);
118        assert_relative_eq!(i80.y(), i80_should.y(), epsilon = 0.2);
119    }
120
121    #[test]
122    fn should_be_north_pole_test() {
123        let p1 = Point::new(0.0, 10.0);
124        let p2 = Point::new(180.0, 10.0);
125        #[allow(deprecated)]
126        let i50 = p1.haversine_intermediate(&p2, 0.5);
127        let i50_should = Point::new(90.0, 90.0);
128        assert_relative_eq!(i50.x(), i50_should.x(), epsilon = 1.0e-6);
129        assert_relative_eq!(i50.y(), i50_should.y(), epsilon = 1.0e-6);
130    }
131
132    #[test]
133    fn should_be_start_end_test() {
134        let p1 = Point::new(30.0, 40.0);
135        let p2 = Point::new(40.0, 50.0);
136        let max_dist = 1500000.0; // meters
137        #[allow(deprecated)]
138        let route = p1.haversine_intermediate_fill(&p2, max_dist, true);
139        assert_eq!(route, vec![p1, p2]);
140    }
141
142    #[test]
143    fn should_add_i50_test() {
144        let p1 = Point::new(30.0, 40.0);
145        let p2 = Point::new(40.0, 50.0);
146        let max_dist = 1000000.0; // meters
147        #[allow(deprecated)]
148        let i50 = p1.clone().haversine_intermediate(&p2, 0.5);
149        #[allow(deprecated)]
150        let fill = p1.haversine_intermediate_fill(&p2, max_dist, true);
151        assert_eq!(fill, vec![p1, i50, p2]);
152        #[allow(deprecated)]
153        let fill = p1.haversine_intermediate_fill(&p2, max_dist, false);
154        assert_eq!(fill, vec![i50]);
155    }
156
157    #[test]
158    fn should_add_i25_i50_i75_test() {
159        let p1 = Point::new(30.0, 40.0);
160        let p2 = Point::new(40.0, 50.0);
161        let max_dist = 400000.0; // meters
162        #[allow(deprecated)]
163        let i25 = p1.clone().haversine_intermediate(&p2, 0.25);
164        #[allow(deprecated)]
165        let i50 = p1.clone().haversine_intermediate(&p2, 0.5);
166        #[allow(deprecated)]
167        let i75 = p1.clone().haversine_intermediate(&p2, 0.75);
168        #[allow(deprecated)]
169        let route = p1.haversine_intermediate_fill(&p2, max_dist, true);
170        assert_eq!(route, vec![p1, i25, i50, i75, p2]);
171    }
172}