1use std::ops::{Add, AddAssign, Mul, Sub};
2
3use super::{BivectorTrait, VectorTrait};
4
5#[derive(Debug, Clone, Copy, PartialEq)]
7pub struct Vector {
8 pub x: f64,
9 pub y: f64,
10 pub z: f64,
11}
12
13impl Vector {
14 pub fn new(x: f64, y: f64, z: f64) -> Vector {
15 return Vector { x, y, z };
16 }
17}
18
19impl super::VectorTrait for Vector {
20 fn scale(&self, scale: f64) -> Vector {
21 return Vector {
22 x: scale * self.x,
23 y: scale * self.y,
24 z: scale * self.z,
25 };
26 }
27
28 fn length(&self) -> f64 {
29 f64::sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
30 }
31
32 fn normalize(&self) -> Vector {
33 let length = self.length();
34 Vector::new(self.x / length, self.y / length, self.z / length)
35 }
36
37 fn is_colinear_to(&self, rhs: Self) -> bool {
38 let factor_x = self.x / rhs.x;
39 let factor_y = self.y / rhs.y;
40 let factor_z = self.z / rhs.z;
41
42 let differences = vec![
43 factor_x - factor_y,
44 factor_x - factor_z,
45 factor_z - factor_y,
46 ];
47
48 for difference in differences {
49 if difference >= f64::EPSILON {
50 return false;
51 }
52 }
53 return true;
54 }
55
56 type WedgeProductOutput = Bivector;
57 fn wedge_product(&self, rhs: Self) -> Self::WedgeProductOutput {
58 Bivector {
59 yz: self.y * rhs.z - self.z * rhs.y,
60 zx: self.z * rhs.x - self.x * rhs.z,
61 xy: self.x * rhs.y - self.y * rhs.x,
62 }
63 }
64
65 type CrossProductOutput = Vector;
66 fn cross_product(&self, rhs: Self) -> Self::CrossProductOutput {
67 self.wedge_product(rhs).as_vector()
68 }
69
70 fn dot_product(&self, rhs: Self) -> f64 {
71 (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
72 }
73}
74
75impl Add for Vector {
76 type Output = Vector;
77
78 fn add(self, rhs: Self) -> Vector {
79 Self {
80 x: self.x + rhs.x,
81 y: self.y + rhs.y,
82 z: self.z + rhs.z,
83 }
84 }
85}
86
87impl AddAssign for Vector {
88 fn add_assign(&mut self, rhs: Self) {
89 *self = *self + rhs
90 }
91}
92
93impl Sub for Vector {
94 type Output = Self;
95
96 fn sub(self, other: Self) -> Self::Output {
97 Self {
98 x: self.x - other.x,
99 y: self.y - other.y,
100 z: self.z - other.z,
101 }
102 }
103}
104
105impl Mul for Vector {
106 type Output = Rotor;
107
108 fn mul(self, rhs: Self) -> Self::Output {
109 let scalar = self.dot_product(rhs);
110 let bivector = self.wedge_product(rhs);
111
112 Rotor { scalar, bivector }
113 }
114}
115
116#[derive(Debug, PartialEq)]
118pub struct Bivector {
119 pub yz: f64,
120 pub zx: f64,
121 pub xy: f64,
122}
123
124impl Bivector {
125 pub fn new(yz: f64, zx: f64, xy: f64) -> Self {
127 Bivector { yz, zx, xy }
128 }
129
130 fn as_vector(&self) -> Vector {
132 Vector::new(self.yz, self.zx, self.xy)
133 }
134}
135
136impl BivectorTrait for Bivector {
137 fn scale(&self, p: f64) -> Self {
138 Bivector::new(self.yz * p, self.zx * p, self.xy * p)
139 }
140
141 fn magnitude(&self) -> f64 {
142 self.as_vector().length()
143 }
144}
145
146#[derive(Debug, PartialEq)]
148pub struct Rotor {
149 scalar: f64,
150 bivector: Bivector,
151}
152
153impl Rotor {
154 pub fn as_quaternion(self) -> Quaternion {
156 Quaternion {
157 real: self.scalar,
158 i: self.bivector.yz,
159 j: self.bivector.zx,
160 k: self.bivector.xy,
161 }
162 }
163}
164
165#[derive(Debug, PartialEq)]
167pub struct Quaternion {
168 real: f64,
169 i: f64,
170 j: f64,
171 k: f64,
172}
173
174impl Quaternion {
175 pub fn as_rotor(&self) -> Rotor {
177 let bivector = Bivector {
178 yz: self.i,
179 zx: self.j,
180 xy: self.k,
181 };
182 Rotor {
183 scalar: self.real,
184 bivector: bivector,
185 }
186 }
187}
188
189#[cfg(test)]
190mod test_vectors {
191 use super::{Bivector, Quaternion, Rotor, Vector};
192 use crate::vectors::VectorTrait;
193
194 #[test]
195 fn test_new_vector() {
196 let vector = Vector::new(0.1, 0.3, 0.6);
197 let expected_result = Vector {
198 x: 0.1,
199 y: 0.3,
200 z: 0.6,
201 };
202
203 assert_eq!(vector, expected_result);
204 }
205
206 #[test]
207
208 fn test_scale_vector() {
209 let vector = Vector::new(0.1, 0.3, 0.6);
210 let result = vector.scale(2.0);
211 let expected_result = Vector {
212 x: 0.2,
213 y: 0.6,
214 z: 1.2,
215 };
216
217 assert_eq!(result, expected_result);
218 }
219
220 #[test]
221 fn test_vector_length() {
222 let a = Vector::new(0.0, 3.0, 0.0);
223 let b = Vector::new(1.0, 1.0, -1.0);
224
225 assert_eq!(a.length(), 3.0);
226 assert_eq!(b.length(), f64::sqrt(3.0));
227 }
228
229 #[test]
230 fn test_vector_normalize() {
231 let a = Vector::new(0.0, 3.0, 0.0).normalize();
232 let b = Vector::new(1.0, 1.0, -1.0).normalize();
233
234 assert_eq!(a, Vector::new(0.0, 1.0, 0.0));
235 assert!(b.length() - 1.0 <= f64::EPSILON);
236 }
237
238 #[test]
239 fn test_vector_addition() {
240 let a = Vector::new(0.1, 0.3, 0.6);
241 let b = Vector::new(0.1, 0.3, 0.4);
242
243 let expected_result = Vector::new(0.2, 0.6, 1.0);
244
245 assert_eq!(a + b, expected_result);
246 }
247
248 #[test]
249 fn test_is_colinear_to() {
250 let a = Vector::new(0.1, 0.3, 0.6);
251 let b = Vector::new(2.0, 0.3, 0.0);
252 let c = Vector::new(0.2, 0.6, 1.2);
253
254 assert_eq!(a.is_colinear_to(b), b.is_colinear_to(c));
255 assert!(a.is_colinear_to(c));
256 assert!(a.is_colinear_to(a))
257 }
258
259 #[test]
260 fn test_vector_subtraction() {
261 let a = Vector::new(0.1, 0.3, 0.6);
262 let b = Vector::new(0.1, 0.3, 0.4);
263
264 let expected_result = Vector::new(0.0, 0.0, 0.2);
265 let result = a - b;
266
267 let difference = result - expected_result;
268 assert!(difference.x <= f64::EPSILON);
269 assert!(difference.y <= f64::EPSILON);
270 assert!(difference.z <= f64::EPSILON);
271 }
272
273 #[test]
274 fn test_vector_multiplication() {
275 let a = Vector::new(1.0, 0.5, 0.5);
276 let b = Vector::new(2.0, 0.0, 1.0);
277
278 let expected_with_help = Rotor {
279 scalar: a.dot_product(b),
280 bivector: a.wedge_product(b),
281 };
282 let expected_without_help = Rotor {
283 scalar: 2.5,
284 bivector: Bivector {
285 yz: 0.5,
286 zx: 0.0,
287 xy: -1.0,
288 },
289 };
290
291 let result = a * b;
292 assert_eq!(expected_with_help, expected_without_help);
293 assert_eq!(expected_with_help, result);
294 assert_eq!(expected_without_help, result);
295 }
296
297 #[test]
298 fn test_rotor_as_quaternion() {
299 let bivector = Bivector {
300 yz: 1.0,
301 zx: 0.2,
302 xy: -0.3,
303 };
304 let rotor = Rotor {
305 scalar: 0.3,
306 bivector,
307 };
308
309 let expected = Quaternion {
310 real: 0.3,
311 i: 1.0,
312 j: 0.2,
313 k: -0.3,
314 };
315 let result = rotor.as_quaternion();
316
317 assert_eq!(expected, result)
318 }
319
320 #[test]
321 fn test_quaternion_as_rotor() {
322 let quaternion = Quaternion {
323 real: 0.3,
324 i: 1.0,
325 j: 0.2,
326 k: -0.3,
327 };
328
329 let bivector = Bivector {
330 yz: 1.0,
331 zx: 0.2,
332 xy: -0.3,
333 };
334 let expected = Rotor {
335 scalar: 0.3,
336 bivector,
337 };
338 let result = quaternion.as_rotor();
339
340 assert_eq!(expected, result)
341 }
342}