vg_algebra/vectors/
vector2d.rs

1use std::ops::{Add, Mul, Sub};
2
3use super::{BivectorTrait, VectorTrait};
4
5/// Cartesian Vector in R2
6#[derive(Debug, Clone, Copy, PartialEq)]
7pub struct Vector {
8    pub x: f64,
9    pub y: f64,
10}
11
12impl Vector {
13    /// Creates new 2d vector in R2
14    pub fn new(x: f64, y: f64) -> Vector {
15        return Vector { x, y };
16    }
17}
18
19impl VectorTrait for Vector {
20    fn scale(&self, other: f64) -> Self {
21        Vector {
22            x: self.x * other,
23            y: self.y * other,
24        }
25    }
26
27    fn length(&self) -> f64 {
28        f64::sqrt((self.x * self.x) + (self.y * self.y))
29    }
30
31    fn normalize(&self) -> Vector {
32        let length = self.length();
33        Vector::new(self.x / length, self.y / length)
34    }
35
36    fn is_colinear_to(&self, rhs: Self) -> bool {
37        let factor_x = self.x / rhs.x;
38        let factor_y = self.y / rhs.y;
39
40        let difference = factor_x - factor_y;
41
42        difference.abs() <= f64::EPSILON
43    }
44
45    type WedgeProductOutput = Bivector;
46    fn wedge_product(&self, rhs: Self) -> Self::WedgeProductOutput {
47        Bivector(self.x * rhs.y - self.y * rhs.x)
48    }
49
50    type CrossProductOutput = f64;
51    fn cross_product(&self, rhs: Self) -> Self::CrossProductOutput {
52        self.wedge_product(rhs).0
53    }
54
55    fn dot_product(&self, rhs: Self) -> f64 {
56        (self.x * rhs.x) + (self.y * rhs.y)
57    }
58}
59
60impl Add for Vector {
61    type Output = Vector;
62
63    fn add(self, rhs: Self) -> Vector {
64        Vector {
65            x: self.x + rhs.x,
66            y: self.y + rhs.y,
67        }
68    }
69}
70
71impl Sub for Vector {
72    type Output = Vector;
73
74    fn sub(self, rhs: Self) -> Self::Output {
75        Vector {
76            x: self.x - rhs.x,
77            y: self.y - rhs.y,
78        }
79    }
80}
81
82impl Mul for Vector {
83    type Output = Rotor;
84
85    fn mul(self, rhs: Self) -> Self::Output {
86        let scalar = self.dot_product(rhs);
87        let bivector = self.wedge_product(rhs);
88
89        Rotor { scalar, bivector }
90    }
91}
92
93/// 2d bivector (represents an area in the xy plane)
94#[derive(Debug, PartialEq)]
95pub struct Bivector(pub f64);
96
97impl BivectorTrait for Bivector {
98    fn scale(&self, p: f64) -> Self {
99        Bivector(self.0 * p)
100    }
101
102    fn magnitude(&self) -> f64 {
103        self.0
104    }
105}
106
107#[derive(Debug, PartialEq)]
108pub struct Rotor {
109    pub scalar: f64,
110    pub bivector: Bivector,
111}
112
113#[cfg(test)]
114mod test_vectors {
115    use crate::vectors::{
116        vector2d::{Bivector, Rotor},
117        VectorTrait,
118    };
119
120    use super::Vector;
121
122    #[test]
123    fn test_new() {
124        let expected = Vector { x: 0.1, y: 0.2 };
125        let result = Vector::new(0.1, 0.2);
126        assert_eq!(expected, result)
127    }
128
129    #[test]
130    fn test_scale() {
131        let vector = Vector::new(1.0, 1.0);
132
133        let expected = Vector::new(2.0, 2.0);
134        let result = vector.scale(2.0);
135
136        assert_eq!(expected, result)
137    }
138
139    #[test]
140    fn test_length() {
141        let vector = Vector::new(1.0, 1.0);
142
143        let expected = f64::sqrt(2.0);
144        let result = vector.length();
145
146        assert_eq!(expected, result)
147    }
148
149    #[test]
150    fn test_is_colinear_to() {
151        let a = Vector::new(0.1, 0.3);
152        let b = Vector::new(2.0, 0.3);
153        let c = Vector::new(0.2, 0.6);
154
155        assert_eq!(a.is_colinear_to(b), b.is_colinear_to(c));
156        assert!(a.is_colinear_to(c));
157        assert!(a.is_colinear_to(a))
158    }
159
160    #[test]
161    fn test_addition() {
162        let a = Vector::new(1.0, 2.0);
163        let b = Vector::new(0.5, 1.0);
164
165        let expected = Vector::new(1.5, 3.0);
166        let result = a + b;
167
168        assert_eq!(expected, result)
169    }
170
171    #[test]
172    fn test_subtraction() {
173        let a = Vector::new(1.0, 2.0);
174        let b = Vector::new(0.5, 1.0);
175
176        let expected = Vector::new(0.5, 1.0);
177        let result = a - b;
178
179        assert_eq!(expected, result)
180    }
181
182    #[test]
183    fn test_vector_multiplication() {
184        let a = Vector::new(1.0, 0.5);
185        let b = Vector::new(2.0, 0.0);
186
187        let expected_with_help = Rotor {
188            scalar: a.dot_product(b),
189            bivector: a.wedge_product(b),
190        };
191        let expected_without_help = Rotor {
192            scalar: 2.0,
193            bivector: Bivector(-1.0),
194        };
195
196        let result = a * b;
197        assert_eq!(expected_with_help, expected_without_help);
198        assert_eq!(expected_with_help, result);
199        assert_eq!(expected_without_help, result);
200    }
201}