mesh_geometry/
vec.rs

1//! Vec2/Vec3 definitions and operations for mesh-geometry.
2
3use core::ops::{Add, Sub, Mul};
4use crate::Float;
5
6/// A 2D vector.
7#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct Vec2<T: Float> {
9    /// X component
10    pub x: T,
11    /// Y component
12    pub y: T,
13}
14
15impl<T: Float> Vec2<T> {
16    /// Create a new Vec2
17    pub fn new(x: T, y: T) -> Self { Self { x, y } }
18
19    /// Dot product
20    pub fn dot(self, other: Vec2<T>) -> T {
21        self.x * other.x + self.y * other.y
22    }
23
24    /// Length (magnitude)
25    pub fn magnitude(self) -> T {
26        self.dot(self).sqrt()
27    }
28
29    /// Cross‐scalar (2D “pseudo‐cross” = scalar)
30    pub fn cross(self, other: Vec2<T>) -> T {
31        self.x * other.y - self.y * other.x
32    }
33}
34// Vector + Vector
35impl<T: Float> Add for Vec2<T> {
36    type Output = Vec2<T>;
37    fn add(self, rhs: Vec2<T>) -> Vec2<T> {
38        Vec2::new(self.x + rhs.x, self.y + rhs.y)
39    }
40}
41// Vector - Vector
42impl<T: Float> Sub for Vec2<T> {
43    type Output = Vec2<T>;
44    fn sub(self, rhs: Vec2<T>) -> Vec2<T> {
45        Vec2::new(self.x - rhs.x, self.y - rhs.y)
46    }
47}
48// Scalar multiplication
49impl<T: Float> Mul<T> for Vec2<T> {
50    type Output = Vec2<T>;
51    fn mul(self, rhs: T) -> Vec2<T> {
52        Vec2::new(self.x * rhs, self.y * rhs)
53    }
54}
55/// A 3D vector.
56#[derive(Debug, Clone, Copy, PartialEq)]
57pub struct Vec3<T: Float> {
58    /// X component
59    pub x: T,
60    /// Y component
61    pub y: T,
62    /// Z component
63    pub z: T,
64}
65
66impl<T: Float> Vec3<T> {
67    /// Create a new Vec3
68    pub fn new(x: T, y: T, z: T) -> Self { Self { x, y, z } }
69
70    /// Dot product
71    pub fn dot(self, other: Vec3<T>) -> T {
72        self.x * other.x + self.y * other.y + self.z * other.z
73    }
74
75    /// Cross product
76    pub fn cross(self, other: Vec3<T>) -> Vec3<T> {
77        Vec3::new(
78            self.y * other.z - self.z * other.y,
79            self.z * other.x - self.x * other.z,
80            self.x * other.y - self.y * other.x,
81        )
82    }
83
84    /// Length (magnitude)
85    pub fn magnitude(self) -> T {
86        self.dot(self).sqrt()
87    }
88}
89impl<T: Float> Add for Vec3<T> {
90    type Output = Vec3<T>;
91    fn add(self, rhs: Vec3<T>) -> Vec3<T> {
92        Vec3::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
93    }
94}
95impl<T: Float> Sub for Vec3<T> {
96    type Output = Vec3<T>;
97    fn sub(self, rhs: Vec3<T>) -> Vec3<T> {
98        Vec3::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
99    }
100}
101impl<T: Float> Mul<T> for Vec3<T> {
102    type Output = Vec3<T>;
103    fn mul(self, rhs: T) -> Vec3<T> {
104        Vec3::new(self.x * rhs, self.y * rhs, self.z * rhs)
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use crate::{Vec2, Vec3};
111
112    #[test]
113    fn vec2_dot_and_cross() {
114        let u = Vec2::new(1.0, 0.0);
115        let v = Vec2::new(0.0, 1.0);
116        assert_eq!(u.dot(v), 0.0);
117        // 2D cross returns +1 for (1,0)x(0,1)
118        assert_eq!(u.cross(v), 1.0);
119    }
120
121    #[test]
122    fn vec3_dot_and_cross() {
123        let i = Vec3::new(1.0, 0.0, 0.0);
124        let j = Vec3::new(0.0, 1.0, 0.0);
125        let k = Vec3::new(0.0, 0.0, 1.0);
126        assert_eq!(i.dot(j), 0.0);
127        assert_eq!(i.cross(j), k);
128    }
129
130    #[test]
131    fn vec_scaling_and_magnitude() {
132        let v = Vec3::new(2.0, -3.0, 6.0);
133        let scaled = v * 2.0;
134        assert_eq!(scaled, Vec3::new(4.0, -6.0, 12.0));
135        let len = (4.0_f64*4.0 + 6.0*6.0 + 12.0*12.0).sqrt();
136        assert!((scaled.magnitude() - len).abs() < 1e-12);
137    }
138}