geo/algorithm/rhumb/
intermediate.rs

1use crate::{CoordFloat, InterpolatePoint, Point, Rhumb};
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 rhumb line between two existing points
9pub trait RhumbIntermediate<T: CoordFloat> {
10    #[deprecated(
11        since = "0.29.0",
12        note = "Please use `Rhumb.point_at_ratio_between` from the `InterpolatePoint` trait instead"
13    )]
14    /// Returns a new Point along a [rhumb line] between two existing points.
15    ///
16    /// # Examples
17    ///
18    /// ```rust
19    /// # use approx::assert_relative_eq;
20    /// # #[allow(deprecated)]
21    /// use geo::RhumbIntermediate;
22    /// use geo::Point;
23    ///
24    /// let p1 = Point::new(10.0, 20.0);
25    /// let p2 = Point::new(125.0, 25.0);
26    /// # #[allow(deprecated)]
27    /// let i20 = p1.rhumb_intermediate(&p2, 0.2);
28    /// # #[allow(deprecated)]
29    /// let i50 = p1.rhumb_intermediate(&p2, 0.5);
30    /// # #[allow(deprecated)]
31    /// let i80 = p1.rhumb_intermediate(&p2, 0.8);
32    /// let i20_should = Point::new(32.7, 21.0);
33    /// let i50_should = Point::new(67.0, 22.5);
34    /// let i80_should = Point::new(101.7, 24.0);
35    /// assert_relative_eq!(i20.x(), i20_should.x(), epsilon = 0.2);
36    /// assert_relative_eq!(i20.y(), i20_should.y(), epsilon = 0.2);
37    /// assert_relative_eq!(i50.x(), i50_should.x(), epsilon = 0.2);
38    /// assert_relative_eq!(i50.y(), i50_should.y(), epsilon = 0.2);
39    /// assert_relative_eq!(i80.x(), i80_should.x(), epsilon = 0.2);
40    /// assert_relative_eq!(i80.y(), i80_should.y(), epsilon = 0.2);
41    /// ```
42    /// [rhumb line]: https://en.wikipedia.org/wiki/Rhumb_line
43    fn rhumb_intermediate(&self, other: &Point<T>, f: T) -> Point<T>;
44
45    #[deprecated(
46        since = "0.29.0",
47        note = "Please use `Rhumb.points_along_line` from the `InterpolatePoint` trait instead"
48    )]
49    fn rhumb_intermediate_fill(
50        &self,
51        other: &Point<T>,
52        max_dist: T,
53        include_ends: bool,
54    ) -> Vec<Point<T>>;
55}
56
57#[allow(deprecated)]
58impl<T> RhumbIntermediate<T> for Point<T>
59where
60    T: CoordFloat + FromPrimitive,
61{
62    fn rhumb_intermediate(&self, other: &Point<T>, f: T) -> Point<T> {
63        Rhumb.point_at_ratio_between(*self, *other, f)
64    }
65
66    fn rhumb_intermediate_fill(
67        &self,
68        other: &Point<T>,
69        max_dist: T,
70        include_ends: bool,
71    ) -> Vec<Point<T>> {
72        Rhumb
73            .points_along_line(*self, *other, max_dist, include_ends)
74            .collect()
75    }
76}
77
78#[cfg(test)]
79mod test {
80    use super::*;
81    #[allow(deprecated)]
82    use crate::RhumbIntermediate;
83
84    #[test]
85    fn f_is_zero_or_one_test() {
86        let p1 = Point::new(10.0, 20.0);
87        let p2 = Point::new(15.0, 25.0);
88        #[allow(deprecated)]
89        let i0 = p1.rhumb_intermediate(&p2, 0.0);
90        #[allow(deprecated)]
91        let i100 = p1.rhumb_intermediate(&p2, 1.0);
92        assert_relative_eq!(i0.x(), p1.x(), epsilon = 1.0e-6);
93        assert_relative_eq!(i0.y(), p1.y(), epsilon = 1.0e-6);
94        assert_relative_eq!(i100.x(), p2.x(), epsilon = 1.0e-6);
95        assert_relative_eq!(i100.y(), p2.y(), epsilon = 1.0e-6);
96    }
97
98    #[test]
99    fn various_f_values_test() {
100        let p1 = Point::new(10.0, 20.0);
101        let p2 = Point::new(125.0, 25.0);
102        #[allow(deprecated)]
103        let i20 = p1.rhumb_intermediate(&p2, 0.2);
104        #[allow(deprecated)]
105        let i50 = p1.rhumb_intermediate(&p2, 0.5);
106        #[allow(deprecated)]
107        let i80 = p1.rhumb_intermediate(&p2, 0.8);
108        let i20_should = Point::new(32.6766, 21.0);
109        let i50_should = Point::new(66.9801, 22.5);
110        let i80_should = Point::new(101.6577, 24.0);
111        assert_relative_eq!(i20.x(), i20_should.x(), epsilon = 0.2);
112        assert_relative_eq!(i20.y(), i20_should.y(), epsilon = 0.2);
113        assert_relative_eq!(i50.x(), i50_should.x(), epsilon = 0.2);
114        assert_relative_eq!(i50.y(), i50_should.y(), epsilon = 0.2);
115        assert_relative_eq!(i80.x(), i80_should.x(), epsilon = 0.2);
116        assert_relative_eq!(i80.y(), i80_should.y(), epsilon = 0.2);
117    }
118
119    #[test]
120    fn should_be_straight_across_test() {
121        let p1 = Point::new(0.0, 10.0);
122        let p2 = Point::new(180.0, 10.0);
123        #[allow(deprecated)]
124        let i50 = p1.rhumb_intermediate(&p2, 0.5);
125        let i50_should = Point::new(90.0, 10.0);
126        assert_relative_eq!(i50.x(), i50_should.x(), epsilon = 1.0e-6);
127        assert_relative_eq!(i50.y(), i50_should.y(), epsilon = 1.0e-6);
128    }
129
130    #[test]
131    fn should_be_start_end_test() {
132        let p1 = Point::new(30.0, 40.0);
133        let p2 = Point::new(40.0, 50.0);
134        let max_dist = 1500000.0; // meters
135        let include_ends = true;
136        #[allow(deprecated)]
137        let route = p1.rhumb_intermediate_fill(&p2, max_dist, include_ends);
138        assert_eq!(route, vec![p1, p2]);
139    }
140
141    #[test]
142    fn should_add_i50_test() {
143        let p1 = Point::new(30.0, 40.0);
144        let p2 = Point::new(40.0, 50.0);
145        let max_dist = 1000000.0; // meters
146        let include_ends = true;
147        #[allow(deprecated)]
148        let i50 = p1.clone().rhumb_intermediate(&p2, 0.5);
149        #[allow(deprecated)]
150        let route = p1.rhumb_intermediate_fill(&p2, max_dist, include_ends);
151        assert_eq!(route, vec![p1, i50, p2]);
152    }
153
154    #[test]
155    fn should_add_i25_i50_i75_test() {
156        let p1 = Point::new(30.0, 40.0);
157        let p2 = Point::new(40.0, 50.0);
158        let max_dist = 400000.0; // meters
159        let include_ends = true;
160        #[allow(deprecated)]
161        let i25 = p1.clone().rhumb_intermediate(&p2, 0.25);
162        #[allow(deprecated)]
163        let i50 = p1.clone().rhumb_intermediate(&p2, 0.5);
164        #[allow(deprecated)]
165        let i75 = p1.clone().rhumb_intermediate(&p2, 0.75);
166        #[allow(deprecated)]
167        let route = p1.rhumb_intermediate_fill(&p2, max_dist, include_ends);
168        assert_eq!(route, vec![p1, i25, i50, i75, p2]);
169    }
170}