@@ -157,6 +157,42 @@ impl<const N: usize, B> Point<[f32; N], Real<N, B>> {
157157 pub fn clamp ( & self , min : & Self , max : & Self ) -> Self {
158158 array:: from_fn ( |i| self . 0 [ i] . clamp ( min. 0 [ i] , max. 0 [ i] ) ) . into ( )
159159 }
160+
161+ /// Returns `self`, moved towards another point by an offset.
162+ ///
163+ /// If the distance to `other` is less than `d`, returns `other`. That is,
164+ /// this method never "overshoots" the target. Negative values of `d` result
165+ /// in moving away from `other`. If `self` equals `other`, returns `other`
166+ /// independent of the value of `d`.
167+ ///
168+ /// To translate by a *relative* offset instead, use [`lerp`][super::Lerp::lerp].
169+ ///
170+ /// # Examples
171+ /// ```
172+ /// use retrofire_core::math::{Point2, pt2};
173+ ///
174+ /// let a: Point2 = pt2(0.0, 0.0);
175+ /// let b: Point2 = pt2(4.0, 3.0);
176+ /// // Move two units along the line y = 3x/4:
177+ /// assert_eq!(a.approach(&b, 2.0), pt2(1.6, 1.2));
178+ /// // Movement is clamped to b:
179+ /// assert_eq!(a.approach(&b, 10.0), b);
180+ /// // Negative values of `d` move away from b:
181+ /// assert_eq!(a.approach(&b, -1.0), pt2(-0.8, -0.6));
182+ /// // Approaching the point itself does nothing:
183+ /// assert_eq!(a.approach(&a, 1.0), a);
184+ /// assert_eq!(a.approach(&a, -1.0), a);
185+ /// ```
186+ #[ must_use]
187+ pub fn approach ( & self , other : & Self , d : f32 ) -> Self {
188+ let v = * other - * self ;
189+ let l = v. len ( ) ;
190+ if d < l && l != 0.0 {
191+ * self + d / l * v
192+ } else {
193+ * other
194+ }
195+ }
160196}
161197
162198impl < Sc : Copy , B > Point < [ Sc ; 2 ] , Real < 2 , B > > {
0 commit comments