Skip to content

Commit f7c7a4a

Browse files
committed
Add Point::approach() method
Moves a point towards another point by an offset without overshooting.
1 parent f32427c commit f7c7a4a

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

core/src/math/point.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

162198
impl<Sc: Copy, B> Point<[Sc; 2], Real<2, B>> {

0 commit comments

Comments
 (0)