avila_math/geometry/
vector.rs

1/// Vector types for 2D, 3D, and 4D mathematics
2///
3/// Provides fundamental vector operations for graphics, physics, and scientific computing.
4use std::ops::{Add, Div, Mul, Neg, Sub};
5
6/// 2D Vector
7#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct Vector2 {
9    pub x: f64,
10    pub y: f64,
11}
12
13/// 3D Vector
14#[derive(Debug, Clone, Copy, PartialEq)]
15pub struct Vector3 {
16    pub x: f64,
17    pub y: f64,
18    pub z: f64,
19}
20
21/// 4D Vector (homogeneous coordinates)
22#[derive(Debug, Clone, Copy, PartialEq)]
23pub struct Vector4 {
24    pub x: f64,
25    pub y: f64,
26    pub z: f64,
27    pub w: f64,
28}
29
30// ============================================================================
31// Vector3 Implementation
32// ============================================================================
33
34impl Vector3 {
35    /// Create a new Vector3
36    #[inline]
37    pub const fn new(x: f64, y: f64, z: f64) -> Self {
38        Self { x, y, z }
39    }
40
41    /// Zero vector
42    #[inline]
43    pub const fn zero() -> Self {
44        Self::new(0.0, 0.0, 0.0)
45    }
46
47    /// One vector (all components = 1)
48    #[inline]
49    pub const fn one() -> Self {
50        Self::new(1.0, 1.0, 1.0)
51    }
52
53    /// Unit vectors
54    #[inline]
55    pub const fn unit_x() -> Self {
56        Self::new(1.0, 0.0, 0.0)
57    }
58    #[inline]
59    pub const fn unit_y() -> Self {
60        Self::new(0.0, 1.0, 0.0)
61    }
62    #[inline]
63    pub const fn unit_z() -> Self {
64        Self::new(0.0, 0.0, 1.0)
65    }
66
67    /// Common direction vectors
68    #[inline]
69    pub const fn up() -> Self {
70        Self::unit_y()
71    }
72    #[inline]
73    pub const fn down() -> Self {
74        Self::new(0.0, -1.0, 0.0)
75    }
76    #[inline]
77    pub const fn left() -> Self {
78        Self::new(-1.0, 0.0, 0.0)
79    }
80    #[inline]
81    pub const fn right() -> Self {
82        Self::unit_x()
83    }
84    #[inline]
85    pub const fn forward() -> Self {
86        Self::new(0.0, 0.0, -1.0)
87    }
88    #[inline]
89    pub const fn back() -> Self {
90        Self::unit_z()
91    }
92
93    /// Dot product
94    #[inline]
95    pub fn dot(self, other: Self) -> f64 {
96        self.x * other.x + self.y * other.y + self.z * other.z
97    }
98
99    /// Cross product
100    #[inline]
101    pub fn cross(self, other: Self) -> Self {
102        Self {
103            x: self.y * other.z - self.z * other.y,
104            y: self.z * other.x - self.x * other.z,
105            z: self.x * other.y - self.y * other.x,
106        }
107    }
108
109    /// Magnitude (length) of the vector
110    #[inline]
111    pub fn length(self) -> f64 {
112        self.dot(self).sqrt()
113    }
114
115    /// Squared magnitude (avoids sqrt)
116    #[inline]
117    pub fn length_squared(self) -> f64 {
118        self.dot(self)
119    }
120
121    /// Normalize the vector (return unit vector)
122    #[inline]
123    pub fn normalize(self) -> Self {
124        let len = self.length();
125        if len > 0.0 {
126            self / len
127        } else {
128            Self::zero()
129        }
130    }
131
132    /// Distance between two points
133    #[inline]
134    pub fn distance(self, other: Self) -> f64 {
135        (self - other).length()
136    }
137
138    /// Squared distance (avoids sqrt)
139    #[inline]
140    pub fn distance_squared(self, other: Self) -> f64 {
141        (self - other).length_squared()
142    }
143
144    /// Linear interpolation
145    #[inline]
146    pub fn lerp(self, other: Self, t: f64) -> Self {
147        self * (1.0 - t) + other * t
148    }
149
150    /// Reflect vector across normal
151    #[inline]
152    pub fn reflect(self, normal: Self) -> Self {
153        self - normal * (2.0 * self.dot(normal))
154    }
155
156    /// Project vector onto another
157    #[inline]
158    pub fn project_onto(self, onto: Self) -> Self {
159        onto * (self.dot(onto) / onto.dot(onto))
160    }
161
162    /// Component-wise minimum
163    #[inline]
164    pub fn min(self, other: Self) -> Self {
165        Self {
166            x: self.x.min(other.x),
167            y: self.y.min(other.y),
168            z: self.z.min(other.z),
169        }
170    }
171
172    /// Component-wise maximum
173    #[inline]
174    pub fn max(self, other: Self) -> Self {
175        Self {
176            x: self.x.max(other.x),
177            y: self.y.max(other.y),
178            z: self.z.max(other.z),
179        }
180    }
181
182    /// Convert to Vector4 with w=0 (direction)
183    #[inline]
184    pub fn to_vector4_dir(self) -> Vector4 {
185        Vector4::new(self.x, self.y, self.z, 0.0)
186    }
187
188    /// Convert to Vector4 with w=1 (point)
189    #[inline]
190    pub fn to_vector4_point(self) -> Vector4 {
191        Vector4::new(self.x, self.y, self.z, 1.0)
192    }
193}
194
195// Operator implementations for Vector3
196impl Add for Vector3 {
197    type Output = Self;
198    fn add(self, rhs: Self) -> Self {
199        Self::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
200    }
201}
202
203impl Sub for Vector3 {
204    type Output = Self;
205    fn sub(self, rhs: Self) -> Self {
206        Self::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
207    }
208}
209
210impl Mul<f64> for Vector3 {
211    type Output = Self;
212    fn mul(self, rhs: f64) -> Self {
213        Self::new(self.x * rhs, self.y * rhs, self.z * rhs)
214    }
215}
216
217impl Div<f64> for Vector3 {
218    type Output = Self;
219    fn div(self, rhs: f64) -> Self {
220        Self::new(self.x / rhs, self.y / rhs, self.z / rhs)
221    }
222}
223
224impl Neg for Vector3 {
225    type Output = Self;
226    fn neg(self) -> Self {
227        Self::new(-self.x, -self.y, -self.z)
228    }
229}
230
231// ============================================================================
232// Vector4 Implementation
233// ============================================================================
234
235impl Vector4 {
236    /// Create a new Vector4
237    #[inline]
238    pub const fn new(x: f64, y: f64, z: f64, w: f64) -> Self {
239        Self { x, y, z, w }
240    }
241
242    /// Zero vector
243    #[inline]
244    pub const fn zero() -> Self {
245        Self::new(0.0, 0.0, 0.0, 0.0)
246    }
247
248    /// Convert to Vector3 (discard w)
249    #[inline]
250    pub fn to_vector3(self) -> Vector3 {
251        Vector3::new(self.x, self.y, self.z)
252    }
253
254    /// Dot product
255    #[inline]
256    pub fn dot(self, other: Self) -> f64 {
257        self.x * other.x + self.y * other.y + self.z * other.z + self.w * other.w
258    }
259
260    /// Magnitude
261    #[inline]
262    pub fn length(self) -> f64 {
263        self.dot(self).sqrt()
264    }
265
266    /// Normalize
267    #[inline]
268    pub fn normalize(self) -> Self {
269        let len = self.length();
270        if len > 0.0 {
271            self / len
272        } else {
273            Self::zero()
274        }
275    }
276}
277
278// Operator implementations for Vector4
279impl Add for Vector4 {
280    type Output = Self;
281    fn add(self, rhs: Self) -> Self {
282        Self::new(
283            self.x + rhs.x,
284            self.y + rhs.y,
285            self.z + rhs.z,
286            self.w + rhs.w,
287        )
288    }
289}
290
291impl Sub for Vector4 {
292    type Output = Self;
293    fn sub(self, rhs: Self) -> Self {
294        Self::new(
295            self.x - rhs.x,
296            self.y - rhs.y,
297            self.z - rhs.z,
298            self.w - rhs.w,
299        )
300    }
301}
302
303impl Mul<f64> for Vector4 {
304    type Output = Self;
305    fn mul(self, rhs: f64) -> Self {
306        Self::new(self.x * rhs, self.y * rhs, self.z * rhs, self.w * rhs)
307    }
308}
309
310impl Div<f64> for Vector4 {
311    type Output = Self;
312    fn div(self, rhs: f64) -> Self {
313        Self::new(self.x / rhs, self.y / rhs, self.z / rhs, self.w / rhs)
314    }
315}
316
317#[cfg(test)]
318mod tests {
319    use super::*;
320
321    #[test]
322    fn test_vector3_basic() {
323        let v = Vector3::new(1.0, 2.0, 3.0);
324        assert_eq!(v.x, 1.0);
325        assert_eq!(v.y, 2.0);
326        assert_eq!(v.z, 3.0);
327    }
328
329    #[test]
330    fn test_vector3_arithmetic() {
331        let v1 = Vector3::new(1.0, 2.0, 3.0);
332        let v2 = Vector3::new(4.0, 5.0, 6.0);
333        let sum = v1 + v2;
334        assert_eq!(sum, Vector3::new(5.0, 7.0, 9.0));
335    }
336
337    #[test]
338    fn test_vector3_dot() {
339        let v1 = Vector3::new(1.0, 2.0, 3.0);
340        let v2 = Vector3::new(4.0, 5.0, 6.0);
341        assert_eq!(v1.dot(v2), 32.0);
342    }
343
344    #[test]
345    fn test_vector3_cross() {
346        let v1 = Vector3::unit_x();
347        let v2 = Vector3::unit_y();
348        let cross = v1.cross(v2);
349        assert!((cross.x - 0.0).abs() < 1e-10);
350        assert!((cross.y - 0.0).abs() < 1e-10);
351        assert!((cross.z - 1.0).abs() < 1e-10);
352    }
353
354    #[test]
355    fn test_vector3_normalize() {
356        let v = Vector3::new(3.0, 4.0, 0.0);
357        let normalized = v.normalize();
358        assert!((normalized.length() - 1.0).abs() < 1e-10);
359    }
360}