Skip to main content

ferroui_base/numerics/
vector2.rs

1//! A vector with two single-precision components.
2
3use std::fmt;
4use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
5
6use super::single::{self, InvariantF32};
7use super::{Matrix3x2, Matrix4x4, Quaternion};
8use crate::Vector;
9
10/// A vector with two single-precision components.
11#[derive(Clone, Copy, Debug, PartialEq, Default)]
12pub struct Vector2 {
13    /// The X component of the vector.
14    pub x: f32,
15    /// The Y component of the vector.
16    pub y: f32,
17}
18
19impl Vector2 {
20    /// The vector `(0, 0)`.
21    pub const ZERO: Vector2 = Vector2::new(0.0, 0.0);
22    /// The vector `(1, 1)`.
23    pub const ONE: Vector2 = Vector2::new(1.0, 1.0);
24    /// The vector `(1, 0)`.
25    pub const UNIT_X: Vector2 = Vector2::new(1.0, 0.0);
26    /// The vector `(0, 1)`.
27    pub const UNIT_Y: Vector2 = Vector2::new(0.0, 1.0);
28
29    /// Creates a vector from its components.
30    #[inline]
31    pub const fn new(x: f32, y: f32) -> Self {
32        Self { x, y }
33    }
34
35    /// Creates a vector whose components all have the same value.
36    #[inline]
37    pub const fn from_value(value: f32) -> Self {
38        Self::new(value, value)
39    }
40
41    /// Returns a vector whose elements are the absolute values of each of the
42    /// specified vector's elements.
43    #[inline]
44    pub fn abs(value: Vector2) -> Vector2 {
45        Vector2::new(value.x.abs(), value.y.abs())
46    }
47
48    /// Restricts a vector between a minimum and a maximum value
49    /// (`min(max(value, min), max)`, so `max` wins when the bounds are inverted).
50    #[inline]
51    pub fn clamp(value1: Vector2, min: Vector2, max: Vector2) -> Vector2 {
52        Vector2::min(Vector2::max(value1, min), max)
53    }
54
55    /// Computes the Euclidean distance between the two given points.
56    #[inline]
57    pub fn distance(value1: Vector2, value2: Vector2) -> f32 {
58        Vector2::distance_squared(value1, value2).sqrt()
59    }
60
61    /// Returns the Euclidean distance squared between two specified points.
62    #[inline]
63    pub fn distance_squared(value1: Vector2, value2: Vector2) -> f32 {
64        (value1 - value2).length_squared()
65    }
66
67    /// Returns the dot product of two vectors.
68    #[inline]
69    pub fn dot(value1: Vector2, value2: Vector2) -> f32 {
70        (value1.x * value2.x) + (value1.y * value2.y)
71    }
72
73    /// Returns the length of the vector.
74    #[inline]
75    pub fn length(&self) -> f32 {
76        self.length_squared().sqrt()
77    }
78
79    /// Returns the length of the vector squared.
80    #[inline]
81    pub fn length_squared(&self) -> f32 {
82        Vector2::dot(*self, *self)
83    }
84
85    /// Performs a linear interpolation between two vectors based on the given weighting.
86    #[inline]
87    pub fn lerp(value1: Vector2, value2: Vector2, amount: f32) -> Vector2 {
88        (value1 * (1.0 - amount)) + (value2 * amount)
89    }
90
91    /// Returns a vector whose elements are the maximum of each of the pairs of
92    /// elements in two specified vectors.
93    #[inline]
94    pub fn max(value1: Vector2, value2: Vector2) -> Vector2 {
95        Vector2::new(single::max(value1.x, value2.x), single::max(value1.y, value2.y))
96    }
97
98    /// Returns a vector whose elements are the minimum of each of the pairs of
99    /// elements in two specified vectors.
100    #[inline]
101    pub fn min(value1: Vector2, value2: Vector2) -> Vector2 {
102        Vector2::new(single::min(value1.x, value2.x), single::min(value1.y, value2.y))
103    }
104
105    /// Returns a vector with the same direction as the specified vector, but
106    /// with a length of one (NaN components for a zero-length vector).
107    #[inline]
108    pub fn normalize(value: Vector2) -> Vector2 {
109        value / value.length()
110    }
111
112    /// Returns a vector whose elements are the square root of each of a
113    /// specified vector's elements.
114    #[inline]
115    pub fn square_root(value: Vector2) -> Vector2 {
116        Vector2::new(value.x.sqrt(), value.y.sqrt())
117    }
118
119    /// Transforms a vector by a specified 3x2 matrix.
120    #[inline]
121    pub fn transform(position: Vector2, matrix: Matrix3x2) -> Vector2 {
122        Vector2::new(
123            (position.x * matrix.m11) + (position.y * matrix.m21) + matrix.m31,
124            (position.x * matrix.m12) + (position.y * matrix.m22) + matrix.m32,
125        )
126    }
127
128    /// Transforms a vector by a specified 4x4 matrix.
129    #[inline]
130    pub fn transform_matrix4x4(position: Vector2, matrix: Matrix4x4) -> Vector2 {
131        Vector2::new(
132            (position.x * matrix.m11) + (position.y * matrix.m21) + matrix.m41,
133            (position.x * matrix.m12) + (position.y * matrix.m22) + matrix.m42,
134        )
135    }
136
137    /// Transforms a vector by the specified rotation.
138    pub fn transform_quaternion(value: Vector2, rotation: Quaternion) -> Vector2 {
139        let x2 = rotation.x + rotation.x;
140        let y2 = rotation.y + rotation.y;
141        let z2 = rotation.z + rotation.z;
142
143        let wz2 = rotation.w * z2;
144        let xx2 = rotation.x * x2;
145        let xy2 = rotation.x * y2;
146        let yy2 = rotation.y * y2;
147        let zz2 = rotation.z * z2;
148
149        Vector2::new(
150            value.x * (1.0 - yy2 - zz2) + value.y * (xy2 - wz2),
151            value.x * (xy2 + wz2) + value.y * (1.0 - xx2 - zz2),
152        )
153    }
154
155    /// Transforms a vector normal by the given 3x2 matrix.
156    #[inline]
157    pub fn transform_normal(normal: Vector2, matrix: Matrix3x2) -> Vector2 {
158        Vector2::new(
159            (normal.x * matrix.m11) + (normal.y * matrix.m21),
160            (normal.x * matrix.m12) + (normal.y * matrix.m22),
161        )
162    }
163}
164
165/// The narrowing conversion of the double-precision vector.
166impl From<Vector> for Vector2 {
167    #[inline]
168    fn from(value: Vector) -> Vector2 {
169        Vector2::new(value.x as f32, value.y as f32)
170    }
171}
172
173/// The widening conversion to the double-precision vector.
174impl From<Vector2> for Vector {
175    #[inline]
176    fn from(value: Vector2) -> Vector {
177        Vector::new(value.x as f64, value.y as f64)
178    }
179}
180
181impl Add for Vector2 {
182    type Output = Vector2;
183    #[inline]
184    fn add(self, right: Vector2) -> Vector2 {
185        Vector2::new(self.x + right.x, self.y + right.y)
186    }
187}
188
189impl Sub for Vector2 {
190    type Output = Vector2;
191    #[inline]
192    fn sub(self, right: Vector2) -> Vector2 {
193        Vector2::new(self.x - right.x, self.y - right.y)
194    }
195}
196
197impl Mul for Vector2 {
198    type Output = Vector2;
199    #[inline]
200    fn mul(self, right: Vector2) -> Vector2 {
201        Vector2::new(self.x * right.x, self.y * right.y)
202    }
203}
204
205impl Mul<f32> for Vector2 {
206    type Output = Vector2;
207    #[inline]
208    fn mul(self, right: f32) -> Vector2 {
209        Vector2::new(self.x * right, self.y * right)
210    }
211}
212
213impl Mul<Vector2> for f32 {
214    type Output = Vector2;
215    #[inline]
216    fn mul(self, right: Vector2) -> Vector2 {
217        right * self
218    }
219}
220
221impl Div for Vector2 {
222    type Output = Vector2;
223    #[inline]
224    fn div(self, right: Vector2) -> Vector2 {
225        Vector2::new(self.x / right.x, self.y / right.y)
226    }
227}
228
229impl Div<f32> for Vector2 {
230    type Output = Vector2;
231    #[inline]
232    fn div(self, right: f32) -> Vector2 {
233        Vector2::new(self.x / right, self.y / right)
234    }
235}
236
237impl Neg for Vector2 {
238    type Output = Vector2;
239    #[inline]
240    fn neg(self) -> Vector2 {
241        Vector2::new(-self.x, -self.y)
242    }
243}
244
245impl AddAssign for Vector2 {
246    #[inline]
247    fn add_assign(&mut self, right: Vector2) {
248        *self = *self + right;
249    }
250}
251
252impl SubAssign for Vector2 {
253    #[inline]
254    fn sub_assign(&mut self, right: Vector2) {
255        *self = *self - right;
256    }
257}
258
259impl MulAssign for Vector2 {
260    #[inline]
261    fn mul_assign(&mut self, right: Vector2) {
262        *self = *self * right;
263    }
264}
265
266impl MulAssign<f32> for Vector2 {
267    #[inline]
268    fn mul_assign(&mut self, right: f32) {
269        *self = *self * right;
270    }
271}
272
273impl DivAssign for Vector2 {
274    #[inline]
275    fn div_assign(&mut self, right: Vector2) {
276        *self = *self / right;
277    }
278}
279
280impl DivAssign<f32> for Vector2 {
281    #[inline]
282    fn div_assign(&mut self, right: f32) {
283        *self = *self / right;
284    }
285}
286
287impl fmt::Display for Vector2 {
288    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
289        write!(f, "<{}, {}>", InvariantF32(self.x), InvariantF32(self.y))
290    }
291}