autd3_core/common/
angle.rs

1/// \[°\]
2#[allow(non_camel_case_types)]
3pub struct deg;
4
5/// \[rad\]
6#[allow(non_camel_case_types)]
7pub struct rad;
8
9/// Angle
10#[repr(C)]
11#[derive(Clone, Copy, PartialEq)]
12pub struct Angle {
13    radian: f32,
14}
15
16impl core::fmt::Debug for Angle {
17    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
18        write!(f, "{} rad", self.radian)
19    }
20}
21
22impl Angle {
23    /// An angle of zero
24    pub const ZERO: Self = Self { radian: 0.0 };
25
26    /// An angle of π
27    pub const PI: Self = Self {
28        radian: core::f32::consts::PI,
29    };
30
31    /// Creates a new [`Angle`] from radian
32    #[must_use]
33    pub const fn from_radian(radian: f32) -> Self {
34        Self { radian }
35    }
36
37    /// Creates a new [`Angle`] from degree
38    #[must_use]
39    pub const fn from_degree(degree: f32) -> Self {
40        Self {
41            radian: degree.to_radians(),
42        }
43    }
44
45    /// Returns the angle in radian
46    #[must_use]
47    pub const fn radian(self) -> f32 {
48        self.radian
49    }
50
51    /// Returns the angle in degree
52    #[must_use]
53    pub const fn degree(self) -> f32 {
54        self.radian.to_degrees()
55    }
56}
57
58impl core::ops::Mul<deg> for f32 {
59    type Output = Angle;
60
61    fn mul(self, _rhs: deg) -> Self::Output {
62        Self::Output::from_degree(self)
63    }
64}
65
66impl core::ops::Mul<rad> for f32 {
67    type Output = Angle;
68
69    fn mul(self, _rhs: rad) -> Self::Output {
70        Self::Output::from_radian(self)
71    }
72}
73
74impl core::ops::Neg for Angle {
75    type Output = Angle;
76
77    fn neg(self) -> Self::Output {
78        Angle {
79            radian: -self.radian,
80        }
81    }
82}
83
84impl core::ops::Add<Angle> for Angle {
85    type Output = Angle;
86
87    fn add(self, rhs: Angle) -> Self::Output {
88        Angle {
89            radian: self.radian + rhs.radian,
90        }
91    }
92}
93
94impl core::ops::Sub<Angle> for Angle {
95    type Output = Angle;
96
97    fn sub(self, rhs: Angle) -> Self::Output {
98        Angle {
99            radian: self.radian - rhs.radian,
100        }
101    }
102}
103
104impl core::ops::Mul<f32> for Angle {
105    type Output = Angle;
106
107    fn mul(self, rhs: f32) -> Self::Output {
108        Angle {
109            radian: self.radian * rhs,
110        }
111    }
112}
113
114impl core::ops::Div<f32> for Angle {
115    type Output = Angle;
116
117    fn div(self, rhs: f32) -> Self::Output {
118        Angle {
119            radian: self.radian / rhs,
120        }
121    }
122}
123
124impl core::ops::Mul<Angle> for f32 {
125    type Output = Angle;
126
127    fn mul(self, rhs: Angle) -> Self::Output {
128        Angle {
129            radian: rhs.radian * self,
130        }
131    }
132}
133
134impl core::ops::AddAssign for Angle {
135    fn add_assign(&mut self, rhs: Angle) {
136        self.radian += rhs.radian;
137    }
138}
139
140impl core::ops::SubAssign for Angle {
141    fn sub_assign(&mut self, rhs: Angle) {
142        self.radian -= rhs.radian;
143    }
144}
145
146impl core::ops::MulAssign<f32> for Angle {
147    fn mul_assign(&mut self, rhs: f32) {
148        self.radian *= rhs;
149    }
150}
151
152impl core::ops::DivAssign<f32> for Angle {
153    fn div_assign(&mut self, rhs: f32) {
154        self.radian /= rhs;
155    }
156}
157
158#[cfg(test)]
159mod tests {
160    use super::*;
161
162    #[test]
163    fn dbg() {
164        assert_eq!(format!("{:?}", 1.0 * rad), "1 rad");
165    }
166
167    #[test]
168    fn ops() {
169        let mut a = 1.0 * rad;
170        let b = 2.0 * rad;
171
172        assert_eq!((-a).radian(), -1.0);
173        assert_eq!((a + b).radian(), 3.0);
174        assert_eq!((a - b).radian(), -1.0);
175        assert_eq!((a * 2.0).radian(), 2.0);
176        assert_eq!((a / 2.0).radian(), 0.5);
177        assert_eq!((2.0 * a).radian(), 2.0);
178
179        a += b;
180        assert_eq!(a.radian(), 3.0);
181
182        a -= b;
183        assert_eq!(a.radian(), 1.0);
184
185        a *= 2.0;
186        assert_eq!(a.radian(), 2.0);
187
188        a /= 2.0;
189        assert_eq!(a.radian(), 1.0);
190    }
191}