Skip to main content

ga2/
rotor.rs

1use crate::*;
2
3use std::ops::{Div, DivAssign, Mul, MulAssign};
4
5use derive_more::{Add, AddAssign, Neg, Sub, SubAssign};
6use inner_space::{DotProduct, InnerSpace, Transform, VectorSpace};
7use scalars::{Inv, One, Real, Zero};
8
9/// The 2D rotor type.
10#[derive(Copy, Clone, Debug, PartialEq, Eq, Add, AddAssign, Sub, SubAssign, Neg)]
11pub struct Rotor<T> {
12    /// The scalar component.
13    pub scalar: T,
14    /// The component representing the xy plane.
15    pub xy: T,
16}
17
18impl<T> Rotor<T> {
19    /// Creates a new rotor from its components.
20    pub fn new(scalar: T, xy: T) -> Self {
21        Self { scalar, xy }
22    }
23}
24
25impl<T: Real> Rotor<T> {
26    /// Rotates a vector by the rotor.
27    pub fn rotate(self, vector: Vector<T>) -> Vector<T> {
28        self.normalize().rotate_normalized(vector)
29    }
30
31    /// Rotates a vector by the rotor.
32    /// The rotor has to be normalized already.
33    pub fn rotate_normalized(self, vector: Vector<T>) -> Vector<T> {
34        let Self { scalar, xy } = self * self;
35
36        Vector {
37            x: scalar * vector.x + xy * vector.y,
38            y: scalar * vector.y - xy * vector.x,
39        }
40    }
41
42    /// The reverse of the rotor.
43    pub fn reverse(self) -> Self {
44        Self {
45            scalar: self.scalar,
46            xy: -self.xy,
47        }
48    }
49}
50
51impl<T: Zero> Rotor<T> {
52    /// Creates a new scalar rotor.
53    pub fn scalar(scalar: T) -> Self {
54        Self {
55            scalar,
56            xy: T::zero(),
57        }
58    }
59
60    /// Creates a new rotor along the xy plane.
61    pub fn xy(xy: T) -> Self {
62        Self {
63            scalar: T::zero(),
64            xy,
65        }
66    }
67}
68
69impl<T: Zero> Zero for Rotor<T> {
70    fn zero() -> Self {
71        Self {
72            scalar: T::zero(),
73            xy: T::zero(),
74        }
75    }
76
77    fn is_zero(&self) -> bool {
78        self.scalar.is_zero() && self.xy.is_zero()
79    }
80}
81
82impl<T: Real> One for Rotor<T> {
83    fn one() -> Self {
84        Self {
85            scalar: T::one(),
86            xy: T::zero(),
87        }
88    }
89
90    fn is_one(&self) -> bool {
91        self.scalar.is_one() && self.xy.is_zero()
92    }
93}
94
95impl<T: Real> Inv for Rotor<T> {
96    type Output = Self;
97
98    fn inv(self) -> Self {
99        self.reverse() / self.magnitude2()
100    }
101}
102
103impl<T: Real> From<T> for Rotor<T> {
104    fn from(scalar: T) -> Self {
105        Self::scalar(scalar)
106    }
107}
108
109impl<T> Mul<T> for Rotor<T>
110where
111    T: Mul<Output = T> + Copy,
112{
113    type Output = Self;
114    fn mul(self, other: T) -> Self {
115        Self {
116            scalar: self.scalar * other,
117            xy: self.xy * other,
118        }
119    }
120}
121
122impl<T> MulAssign<T> for Rotor<T>
123where
124    T: MulAssign + Copy,
125{
126    fn mul_assign(&mut self, other: T) {
127        self.scalar *= other;
128        self.xy *= other;
129    }
130}
131
132impl<T> Div<T> for Rotor<T>
133where
134    T: Div<Output = T> + Copy,
135{
136    type Output = Self;
137    fn div(self, other: T) -> Self {
138        Self {
139            scalar: self.scalar / other,
140            xy: self.xy / other,
141        }
142    }
143}
144
145impl<T> DivAssign<T> for Rotor<T>
146where
147    T: DivAssign + Copy,
148{
149    fn div_assign(&mut self, other: T) {
150        self.scalar /= other;
151        self.xy /= other;
152    }
153}
154
155impl<T: Real> VectorSpace for Rotor<T> {
156    type Scalar = T;
157}
158
159impl<T: Real> DotProduct for Rotor<T> {
160    type Output = Self::Scalar;
161
162    fn dot(&self, other: &Self) -> T {
163        self.scalar * other.scalar - self.xy * other.xy
164    }
165
166    fn scalar(&self, other: &Self) -> T {
167        self.scalar * other.scalar + self.xy * other.xy
168    }
169}
170
171impl<T: Real> DotProduct<Vector<T>> for Rotor<T> {
172    type Output = Vector<T>;
173    #[inline]
174    fn dot(&self, other: &Vector<T>) -> Vector<T> {
175        other.dot(self)
176    }
177}
178
179impl<T: Real> DotProduct<Bivector<T>> for Rotor<T> {
180    type Output = Self;
181    #[inline]
182    fn dot(&self, other: &Bivector<T>) -> Self {
183        other.dot(self)
184    }
185}
186
187impl<T: Real> Mul for Rotor<T> {
188    type Output = Self;
189    fn mul(self, other: Self) -> Self {
190        Self {
191            scalar: self.dot(&other),
192            xy: self.scalar * other.xy + other.scalar * self.xy,
193        }
194    }
195}
196
197impl<T: Real> MulAssign for Rotor<T> {
198    fn mul_assign(&mut self, other: Self) {
199        *self = *self * other;
200    }
201}
202
203impl<T: Real> Div for Rotor<T> {
204    type Output = Self;
205    fn div(self, other: Self) -> Self {
206        self * other.inv()
207    }
208}
209
210impl<T: Real> DivAssign for Rotor<T> {
211    fn div_assign(&mut self, other: Self) {
212        *self = *self / other;
213    }
214}
215
216impl<T: Real> Transform<Vector<T>> for Rotor<T> {
217    fn apply_point(&self, point: Vector<T>) -> Vector<T> {
218        self.rotate(point)
219    }
220}
221
222impl<T: Real + std::fmt::Display> std::fmt::Display for Rotor<T> {
223    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
224        write!(formatter, "({}, {})", self.scalar, self.xy)
225    }
226}
227
228impl<T: Real + std::str::FromStr> std::str::FromStr for Rotor<T> {
229    type Err = String;
230
231    fn from_str(source: &str) -> Result<Self, Self::Err> {
232        let trimmed = source
233            .strip_prefix('(')
234            .and_then(|s| s.strip_suffix(')'))
235            .ok_or_else(|| format!("expected format (scalar, xy), got {source}"))?;
236        let mut parts = trimmed.split(',');
237        let scalar = parts
238            .next()
239            .ok_or_else(|| "missing scalar component".to_string())?
240            .trim()
241            .parse::<T>()
242            .map_err(|_| "failed to parse scalar component".to_string())?;
243        let xy = parts
244            .next()
245            .ok_or_else(|| "missing xy component".to_string())?
246            .trim()
247            .parse::<T>()
248            .map_err(|_| "failed to parse xy component".to_string())?;
249        if parts.next().is_some() {
250            return Err("too many components".to_string());
251        }
252        Ok(Self { scalar, xy })
253    }
254}