Skip to main content

roche/
vec3.rs

1use std::ops;
2use pyo3::prelude::*;
3
4// useful for defining python operators
5#[derive(FromPyObject)]
6enum Vec3OrF64 {
7    Vec3(Vec3),
8    F64(f64)
9}
10
11#[pyclass(from_py_object)]
12#[derive(Debug, Copy, Clone, PartialEq)]
13pub struct Vec3 {
14    #[pyo3(get, set)]
15    pub x: f64,
16    #[pyo3(get, set)]
17    pub y: f64,
18    #[pyo3(get, set)]
19    pub z: f64,
20}
21
22#[pymethods]
23impl Vec3 {
24    #[new]
25    pub fn new(x: f64, y: f64, z: f64) -> Self {
26        Self {
27            x: x,
28            y: y,
29            z: z
30        }
31    }
32    
33    #[staticmethod]
34    pub fn cofm1() -> Self {
35        Self {
36            x: 0.0,
37            y: 0.0,
38            z: 0.0
39        }
40    }
41
42    #[staticmethod]
43    pub fn cofm2() -> Self {
44        Self {
45            x: 1.0,
46            y: 0.0,
47            z: 0.0
48        }
49    }
50
51    pub fn set(&mut self, x: f64, y: f64, z: f64) -> () {
52        self.x = x;
53        self.y = y;
54        self.z = z;
55    }
56
57    // Normalises the vector in place
58    pub fn unit(&mut self) {
59        let norm = self.length();
60        self.x /= norm;
61        self.y /= norm;
62        self.z /= norm;
63    }
64
65    // Returns a normalised version of the vector
66    pub fn norm(&self) -> Self {
67        let norm = self.length();
68        Self {
69            x: self.x / norm,
70            y: self.y / norm,
71            z: self.z / norm
72        }
73    }
74
75    // For `__repr__` we want to return a string that Python code could use to recreate
76    // the `Vec3`, like `Vec3(5, 6, 7)` for example.
77    fn __repr__(&self) -> String {
78        // We use the `format!` macro to create a string. Its first argument is a
79        // format string, followed by any number of parameters which replace the
80        // `{}`'s in the format string.
81        format!("Vec3({}, {}, {})", self.x, self.y, self.z)
82    }
83
84    // Returns the length of the vector
85    pub fn length(&self) -> f64 {
86        (self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt()
87    }
88
89    // Returns the squared length of the vector
90    pub fn sqr(&self) -> f64 {
91        self.x.powi(2) + self.y.powi(2) + self.z.powi(2)
92    }
93
94    // Returns the dot product of two vectors
95    pub fn dot(&self, other: &Vec3) -> f64 {
96        self.x*other.x + self.y*other.y + self.z*other.z
97    }
98
99    // Returns the cross product of two vectors
100    pub fn cross(&self, other: &Vec3) -> Vec3 {
101        let temp_x = self.y*other.z - self.z*other.y;
102        let temp_y = self.z*other.x - self.x*other.z;
103        let temp_z = self.x*other.y - self.y*other.x;
104        Vec3::new(temp_x, temp_y, temp_z)
105    }
106
107    // Python dunder methods for arithmetic
108    fn __add__(&self, other: Vec3OrF64) -> Self {
109        match other {
110            Vec3OrF64::Vec3(v) => self.clone() + v,
111            Vec3OrF64::F64(f) => self.clone() + f
112        }
113    }
114    fn __radd__(&self, other: Vec3OrF64) -> Self {
115        match other {
116            Vec3OrF64::Vec3(v) => v + self.clone(),
117            Vec3OrF64::F64(f) => f + self.clone()
118        }
119    }
120    fn __sub__(&self, other: Vec3OrF64) -> Self {
121        match other {
122            Vec3OrF64::Vec3(v) => self.clone() - v,
123            Vec3OrF64::F64(f) => self.clone() - f
124        }
125    }
126    fn __rsub__(&self, other: Vec3OrF64) -> Self {
127        match other {
128            Vec3OrF64::Vec3(v) => v - self.clone(),
129            Vec3OrF64::F64(f) => f - self.clone()   
130        }
131    }
132    fn __mul__(&self, other: f64) -> Self {
133        self.clone() * other
134    }
135    fn __rmul__(&self, other: f64) -> Self {
136        other * self.clone()
137    }
138    fn __truediv__(&self, other: f64) -> Self {
139        self.clone() / other
140    }
141    fn __rtruediv__(&self, other: f64) -> Self {
142        other / self.clone()
143    }
144    fn __neg__(&self) -> Self {
145        -self.clone()
146    }
147
148}
149
150// in-place multiplication by f64
151impl ops::MulAssign<f64> for Vec3 {
152    fn mul_assign(&mut self, rhs: f64) {
153        self.x *= rhs;
154        self.y *= rhs;
155        self.z *= rhs;
156    }
157}
158
159// in-place division by f64
160impl ops::DivAssign<f64> for Vec3 {
161    fn div_assign(&mut self, rhs: f64) {
162        self.x /= rhs;
163        self.y /= rhs;
164        self.z /= rhs;
165    }
166}
167
168// in-place addition of vector
169impl ops::AddAssign<Vec3> for Vec3 {
170    fn add_assign(&mut self, rhs: Vec3) {
171        self.x += rhs.x;
172        self.y += rhs.y;
173        self.z += rhs.z;
174    }
175}
176
177
178// in-place subtraction of vector
179impl ops::SubAssign<Vec3> for Vec3 {
180    fn sub_assign(&mut self, rhs: Vec3) {
181        self.x -= rhs.x;
182        self.y -= rhs.y;
183        self.z -= rhs.z;
184    }
185}
186
187// Sum of two vectors
188impl ops::Add for Vec3 {
189    type Output = Self;
190    fn add(self, other: Self) -> Self {
191        Self {
192            x: self.x + other.x,
193            y: self.y + other.y,
194            z: self.z + other.z,
195        }
196    }
197}
198
199// Sum of vector and f64
200impl ops::Add<f64> for Vec3 {
201    type Output = Self;
202    fn add(self, other: f64) -> Self {
203        Self {
204            x: self.x + other,
205            y: self.y + other,
206            z: self.z + other,
207        }
208    }
209}
210
211// Sum of f64 and vector
212impl ops::Add<Vec3> for f64 {
213    type Output = Vec3;
214    fn add(self, other: Vec3) -> Vec3 {
215        Vec3 {
216            x: self + other.x,
217            y: self + other.y,
218            z: self + other.z,
219        }
220    }
221}
222
223// Difference between two vectors
224impl ops::Sub for Vec3 {
225    type Output = Self;
226    fn sub(self, other: Self) -> Self {
227        Self {
228            x: self.x - other.x,
229            y: self.y - other.y,
230            z: self.z - other.z,
231        }
232    }
233}
234
235// Difference between vector and f64
236impl ops::Sub<f64> for Vec3 {
237    type Output = Self;
238    fn sub(self, other: f64) -> Self {
239        Self {
240            x: self.x - other,
241            y: self.y - other,
242            z: self.z - other,
243        }
244    }
245}
246
247// Difference between f64 and vector
248impl ops::Sub<Vec3> for f64 {
249    type Output = Vec3;
250    fn sub(self, other: Vec3) -> Vec3 {
251        Vec3 {
252            x: self - other.x,
253            y: self - other.y,
254            z: self - other.z,
255        }
256    }
257}
258
259// Multiplication of Vec3 by f64
260impl ops::Mul<f64> for Vec3 {
261    type Output = Self;
262
263    fn mul(self, rhs: f64) -> Self {
264        Self{
265            x: self.x * rhs,
266            y: self.y * rhs,
267            z: self.z * rhs,
268        }
269    }
270}
271
272// Multiplication of f64 by Vec3
273impl ops::Mul<Vec3> for f64 {
274    type Output = Vec3;
275
276    fn mul(self, rhs: Vec3) -> Vec3 {
277        Vec3{
278            x: self * rhs.x,
279            y: self * rhs.y,
280            z: self * rhs.z,
281        }
282    }
283}
284
285// Division of Vec3 by f64
286impl ops::Div<f64> for Vec3 {
287    type Output = Self;
288
289    fn div(self, rhs: f64) -> Self {
290        Self{
291            x: self.x / rhs,
292            y: self.y / rhs,
293            z: self.z / rhs,
294        }
295    }
296}
297
298// Division of f64 by Vec3
299impl ops::Div<Vec3> for f64 {
300    type Output = Vec3;
301
302    fn div(self, rhs: Vec3) -> Vec3 {
303        Vec3{
304            x: self / rhs.x,
305            y: self / rhs.y,
306            z: self / rhs.z,
307        }
308    }
309}
310
311// Negative of a vector
312impl ops::Neg for Vec3 {
313    type Output = Self;
314
315    fn neg(self) -> Self {
316        Vec3{
317            x: -self.x,
318            y: -self.y,
319            z: -self.z,
320        }
321    }
322}
323