strange_loop/
vector3d.rs

1//! Custom Vector3D implementation for strange-loop examples
2
3use serde::{Deserialize, Serialize};
4use std::ops::{Add, AddAssign, Index, IndexMut, Mul, Sub};
5
6/// Simple 3D vector for examples that don't require heavy math
7#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
8pub struct Vector3D {
9    pub x: f64,
10    pub y: f64,
11    pub z: f64,
12}
13
14impl Vector3D {
15    pub fn new(x: f64, y: f64, z: f64) -> Self {
16        Self { x, y, z }
17    }
18
19    pub fn zero() -> Self {
20        Self { x: 0.0, y: 0.0, z: 0.0 }
21    }
22
23    pub fn distance(&self, other: &Vector3D) -> f64 {
24        ((self.x - other.x).powi(2) +
25         (self.y - other.y).powi(2) +
26         (self.z - other.z).powi(2)).sqrt()
27    }
28
29    pub fn magnitude(&self) -> f64 {
30        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
31    }
32
33    pub fn norm(&self) -> f64 {
34        self.magnitude()
35    }
36
37    pub fn zeros() -> Self {
38        Self { x: 0.0, y: 0.0, z: 0.0 }
39    }
40
41    pub fn dot(&self, other: &Vector3D) -> f64 {
42        self.x * other.x + self.y * other.y + self.z * other.z
43    }
44
45    pub fn iter(&self) -> impl Iterator<Item = f64> {
46        [self.x, self.y, self.z].into_iter()
47    }
48}
49
50impl std::ops::Add for Vector3D {
51    type Output = Vector3D;
52
53    fn add(self, other: Vector3D) -> Vector3D {
54        Vector3D {
55            x: self.x + other.x,
56            y: self.y + other.y,
57            z: self.z + other.z,
58        }
59    }
60}
61
62impl std::ops::Sub for Vector3D {
63    type Output = Vector3D;
64
65    fn sub(self, other: Vector3D) -> Vector3D {
66        Vector3D {
67            x: self.x - other.x,
68            y: self.y - other.y,
69            z: self.z - other.z,
70        }
71    }
72}
73
74impl std::ops::Mul<f64> for Vector3D {
75    type Output = Vector3D;
76
77    fn mul(self, scalar: f64) -> Vector3D {
78        Vector3D {
79            x: self.x * scalar,
80            y: self.y * scalar,
81            z: self.z * scalar,
82        }
83    }
84}
85
86impl std::ops::Mul<Vector3D> for f64 {
87    type Output = Vector3D;
88
89    fn mul(self, vector: Vector3D) -> Vector3D {
90        Vector3D {
91            x: self * vector.x,
92            y: self * vector.y,
93            z: self * vector.z,
94        }
95    }
96}
97
98impl std::ops::Neg for Vector3D {
99    type Output = Vector3D;
100
101    fn neg(self) -> Vector3D {
102        Vector3D {
103            x: -self.x,
104            y: -self.y,
105            z: -self.z,
106        }
107    }
108}
109
110impl std::ops::Div<f64> for Vector3D {
111    type Output = Vector3D;
112
113    fn div(self, scalar: f64) -> Vector3D {
114        Vector3D {
115            x: self.x / scalar,
116            y: self.y / scalar,
117            z: self.z / scalar,
118        }
119    }
120}
121
122impl Index<usize> for Vector3D {
123    type Output = f64;
124
125    fn index(&self, index: usize) -> &Self::Output {
126        match index {
127            0 => &self.x,
128            1 => &self.y,
129            2 => &self.z,
130            _ => panic!("Vector3D index out of bounds: {}", index),
131        }
132    }
133}
134
135impl IndexMut<usize> for Vector3D {
136    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
137        match index {
138            0 => &mut self.x,
139            1 => &mut self.y,
140            2 => &mut self.z,
141            _ => panic!("Vector3D index out of bounds: {}", index),
142        }
143    }
144}
145
146impl AddAssign for Vector3D {
147    fn add_assign(&mut self, other: Vector3D) {
148        self.x += other.x;
149        self.y += other.y;
150        self.z += other.z;
151    }
152}