Skip to main content

stipple_geometry/
point.rs

1use crate::Vec2;
2use core::ops::{Add, Sub};
3
4/// A position in logical-pixel space.
5#[derive(Clone, Copy, Debug, Default, PartialEq)]
6pub struct Point {
7    pub x: f64,
8    pub y: f64,
9}
10
11impl Point {
12    pub const ORIGIN: Self = Self { x: 0.0, y: 0.0 };
13
14    #[inline]
15    pub const fn new(x: f64, y: f64) -> Self {
16        Self { x, y }
17    }
18
19    /// Euclidean distance to `other`.
20    #[inline]
21    pub fn distance_to(self, other: Point) -> f64 {
22        (other - self).length()
23    }
24
25    /// Linear interpolation toward `other` by `t` (0.0 = self, 1.0 = other).
26    #[inline]
27    pub fn lerp(self, other: Point, t: f64) -> Point {
28        Point::new(
29            self.x + (other.x - self.x) * t,
30            self.y + (other.y - self.y) * t,
31        )
32    }
33}
34
35impl Add<Vec2> for Point {
36    type Output = Point;
37    #[inline]
38    fn add(self, rhs: Vec2) -> Point {
39        Point::new(self.x + rhs.dx, self.y + rhs.dy)
40    }
41}
42
43impl Sub<Vec2> for Point {
44    type Output = Point;
45    #[inline]
46    fn sub(self, rhs: Vec2) -> Point {
47        Point::new(self.x - rhs.dx, self.y - rhs.dy)
48    }
49}
50
51/// Subtracting two points yields the displacement between them.
52impl Sub for Point {
53    type Output = Vec2;
54    #[inline]
55    fn sub(self, rhs: Point) -> Vec2 {
56        Vec2::new(self.x - rhs.x, self.y - rhs.y)
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn point_vec_algebra() {
66        let a = Point::new(1.0, 1.0);
67        let b = Point::new(4.0, 5.0);
68        assert_eq!(b - a, Vec2::new(3.0, 4.0));
69        assert_eq!(a.distance_to(b), 5.0);
70        assert_eq!(a + Vec2::new(3.0, 4.0), b);
71        assert_eq!(a.lerp(b, 0.5), Point::new(2.5, 3.0));
72    }
73}