Skip to main content

autd3_rs_core/common/
angle.rs

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