makepad_vector/geometry/
vector.rs

1use crate::geometry::{Point, Transform, Transformation};
2use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
3
4/// A vector in 2-dimensional Euclidian space.
5///
6/// A point represents a position, whereas a vector represents a displacement. That is, the result
7/// of subtracting two points is a vector. Moreover, the result of adding/subtracting a vector
8/// to/from a point is another point. However, adding two points is not defined. Similarly, whereas
9/// a point can be scaled, rotated, and translated, a vector can only be scaled and rotated.
10#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
11pub struct Vector {
12    pub x: f64,
13    pub y: f64,
14}
15
16impl Vector {
17    /// Creates a new vector with the given coordinates.
18    pub fn new(x: f64, y: f64) -> Vector {
19        Vector { x, y }
20    }
21
22    /// Returns the zero vector.
23    pub fn zero() -> Vector {
24        Vector::new(0.0, 0.0)
25    }
26
27    /// Converts `self` to a point.
28    ///
29    /// This is equivalent to adding `self` to the origin.
30    pub fn to_point(self) -> Point {
31        Point::new(self.x, self.y)
32    }
33
34    /// Returns the length of `self`.
35    pub fn length(self) -> f64 {
36        // `hypot` is more numerically stable than using `sqrt`. See:
37        // https://en.wikipedia.org/wiki/Hypot
38        self.x.hypot(self.y)
39    }
40
41    /// Returns the unit vector in the direction of `self`, or `None` if `self` is the zero vector.
42    pub fn normalize(self) -> Option<Vector> {
43        let length = self.length();
44        if length == 0.0 {
45            None
46        } else {
47            Some(self / length)
48        }
49    }
50
51    /// Returns the dot product of `self` and `other`.
52    pub fn dot(self, other: Vector) -> f64 {
53        self.x * other.x + self.y * other.y
54    }
55
56    /// Returns the cross product of `self` and `other`.
57    pub fn cross(self, other: Vector) -> f64 {
58        self.x * other.y - self.y * other.x
59    }
60
61    /// Non-uniformly scales `self` with the scale vector `v`.
62    pub fn scale(self, v: Vector) -> Vector {
63        Vector::new(self.x * v.x, self.y * v.y)
64    }
65}
66
67impl AddAssign for Vector {
68    fn add_assign(&mut self, other: Vector) {
69        *self = *self + other
70    }
71}
72
73impl SubAssign for Vector {
74    fn sub_assign(&mut self, other: Vector) {
75        *self = *self - other
76    }
77}
78
79impl MulAssign<f64> for Vector {
80    fn mul_assign(&mut self, k: f64) {
81        *self = *self * k
82    }
83}
84
85impl DivAssign<f64> for Vector {
86    fn div_assign(&mut self, k: f64) {
87        *self = *self / k
88    }
89}
90
91impl Add for Vector {
92    type Output = Vector;
93
94    fn add(self, other: Vector) -> Vector {
95        Vector::new(self.x + other.x, self.y + other.y)
96    }
97}
98
99impl Sub for Vector {
100    type Output = Vector;
101
102    fn sub(self, other: Vector) -> Vector {
103        Vector::new(self.x - other.x, self.y - other.y)
104    }
105}
106
107impl Mul<f64> for Vector {
108    type Output = Vector;
109
110    fn mul(self, k: f64) -> Vector {
111        Vector::new(self.x * k, self.y * k)
112    }
113}
114
115impl Div<f64> for Vector {
116    type Output = Vector;
117
118    fn div(self, k: f64) -> Vector {
119        Vector::new(self.x / k, self.y / k)
120    }
121}
122
123impl Neg for Vector {
124    type Output = Vector;
125
126    fn neg(self) -> Vector {
127        Vector::new(-self.x, -self.y)
128    }
129}
130
131impl Transform for Vector {
132    fn transform<T>(self, t: &T) -> Vector
133    where
134        T: Transformation,
135    {
136        t.transform_vector(self)
137    }
138
139    fn transform_mut<T>(&mut self, t: &T)
140    where
141        T: Transformation,
142    {
143        *self = self.transform(t);
144    }
145}