radiant_utils/math/
angle.rs1use prelude::*;
2use super::Vec2;
3
4#[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))]
6#[derive(Copy, Clone, PartialEq, PartialOrd)]
7pub struct Angle<T = f32>(pub T);
8
9impl<T> Angle<T> where T: Float {
10 pub fn to_radians(self: &Self) -> T {
12 self.0
13 }
14 pub fn to_degrees(self: &Self) -> T {
16 self.0.to_degrees()
17 }
18 #[deprecated(since = "0.2.2", note = "use Vec2::from() instead")]
20 pub fn to_vec2(self: &Self) -> Vec2<T> {
21 Vec2::from(*self)
22 }
23 pub fn from_radians(radians: T) -> Self {
25 Angle::<T>(radians)
26 }
27 pub fn from_degrees(degrees: T) -> Self {
29 Self::from_radians(degrees.to_radians())
30 }
31 #[allow(non_snake_case)]
33 pub fn normalize(self: &Self) -> Self {
34 let PI = NumCast::from(f64::consts::PI).unwrap();
35 if self.0.abs() > PI {
36 let two_PI = NumCast::from(f64::consts::PI * 2.0).unwrap();
37 Angle(self.0 - two_PI * ((self.0 + PI) / two_PI).floor())
38 } else {
39 *self
40 }
41 }
42 pub fn diff(self: &Self, other: Self) -> Self {
44 let mut this = *self;
45 this.align_with(other);
46 this - other
47 }
48 #[allow(non_snake_case)]
50 pub fn align_with(self: &mut Self, target: Self) -> &mut Self {
51
52 let PI = NumCast::from(f64::consts::PI).unwrap();
53 let two_PI = NumCast::from(f64::consts::PI * 2.0).unwrap();
54
55 if self.0.abs() > PI {
58 self.0 = self.0 - two_PI * ((self.0 + PI) / two_PI).floor();
59 }
60
61 let target_radians = if target.0.abs() > PI {
62 target.0 - two_PI * ((target.0 + PI) / two_PI).floor()
63 } else {
64 target.0
65 };
66
67 let diff = self.0 - target_radians;
70
71 if diff.abs() > PI {
72 self.0 = self.0 - diff.signum() * two_PI;
73 }
74
75 self
76 }
77}
78
79impl<T> From<Vec2<T>> for Angle<T> where T: Float {
82 fn from(vec: Vec2<T>) -> Angle<T> {
83 Angle(vec.1.atan2(vec.0))
84 }
85}
86
87impl<T> From<T> for Angle<T> where T: Float {
90 fn from(other: T) -> Angle<T> {
91 Angle(other)
92 }
93}
94
95impl From<Angle<f64>> for f64 {
96 fn from(other: Angle<f64>) -> f64 {
97 other.to_radians() as f64
98 }
99}
100
101impl From<Angle<f32>> for f32 {
102 fn from(other: Angle<f32>) -> f32 {
103 other.to_radians() as f32
104 }
105}
106
107impl<'a> From<&'a Angle<f64>> for f64 {
108 fn from(other: &'a Angle<f64>) -> f64 {
109 other.to_radians() as f64
110 }
111}
112
113impl<'a> From<&'a Angle<f32>> for f32 {
114 fn from(other: &'a Angle<f32>) -> f32 {
115 other.to_radians() as f32
116 }
117}
118
119impl<T> Default for Angle<T> where T: Float {
122 fn default() -> Self {
123 Angle(T::zero())
124 }
125}
126
127impl<T> ToPrimitive for Angle<T> where T: Float {
130 fn to_f64(self: &Self) -> Option<f64> {
131 NumCast::from(self.to_radians())
132 }
133 fn to_f32(self: &Self) -> Option<f32> {
134 NumCast::from(self.to_radians())
135 }
136 fn to_i64(self: &Self) -> Option<i64> {
137 NumCast::from(self.to_radians())
138 }
139 fn to_u64(self: &Self) -> Option<u64> {
140 let value = self.to_radians();
141 if value >= T::zero() { NumCast::from(self.to_radians()) } else { None }
142 }
143}
144
145impl<T> FromPrimitive for Angle<T> where T: Float {
146 fn from_f64(n: f64) -> Option<Angle<T>> {
147 Some(Angle(NumCast::from(n).unwrap()))
148 }
149 fn from_f32(n: f32) -> Option<Angle<T>> {
150 Some(Angle(NumCast::from(n).unwrap()))
151 }
152 fn from_i64(n: i64) -> Option<Angle<T>> {
153 Some(Angle(NumCast::from(n).unwrap()))
154 }
155 fn from_u64(n: u64) -> Option<Angle<T>> {
156 Some(Angle(NumCast::from(n).unwrap()))
157 }
158}
159
160impl<T> Neg for Angle<T> where T: Float {
163 type Output = Angle<T>;
164
165 fn neg(self) -> Angle<T> {
166 Angle::<T>(-self.0)
167 }
168}
169
170impl<T> Add for Angle<T> where T: Float {
171 type Output = Angle<T>;
172 fn add(self, other: Angle<T>) -> Angle<T> {
173 Angle::<T>(self.0 + other.0)
174 }
175}
176
177impl<T> AddAssign for Angle<T> where T: Float {
178 fn add_assign(self: &mut Self, other: Angle<T>) {
179 *self = Angle::<T>(self.0 + other.0)
180 }
181}
182
183impl<T> Sub for Angle<T> where T: Float {
184 type Output = Angle<T>;
185 fn sub(self, other: Angle<T>) -> Angle<T> {
186 Angle::<T>(self.0 - other.0)
187 }
188}
189
190impl<T> SubAssign for Angle<T> where T: Float {
191 fn sub_assign(self: &mut Self, other: Angle<T>) {
192 *self = Angle::<T>(self.0 - other.0)
193 }
194}
195
196impl<T> Mul<Angle<T>> for Angle<T> where T: Float {
197 type Output = Angle<T>;
198 fn mul(self, other: Angle<T>) -> Angle<T> {
199 Angle::<T>(self.0 * other.0)
200 }
201}
202
203impl<T> MulAssign for Angle<T> where T: Float {
204 fn mul_assign(&mut self, other: Angle<T>) {
205 *self = Angle::<T>(self.0 * other.0)
206 }
207}
208
209impl<T> Mul<T> for Angle<T> where T: Float {
210 type Output = Angle<T>;
211 fn mul(self, other: T) -> Angle<T> {
212 Angle::<T>(self.0 * other)
213 }
214}
215
216impl<T> Div<Angle<T>> for Angle<T> where T: Float {
217 type Output = Angle<T>;
218 fn div(self, other: Angle<T>) -> Angle<T> {
219 Angle::<T>(self.0 / other.0)
220 }
221}
222
223impl<T> DivAssign for Angle<T> where T: Float {
224 fn div_assign(&mut self, other: Angle<T>) {
225 *self = Angle::<T>(self.0 / other.0)
226 }
227}
228
229impl<T> Div<T> for Angle<T> where T: Float {
230 type Output = Angle<T>;
231 fn div(self, other: T) -> Angle<T> {
232 Angle::<T>(self.0 / other)
233 }
234}
235
236#[cfg(feature = "uniforms")]
239use radiant_rs::{Uniform, AsUniform};
240
241#[cfg(feature = "uniforms")]
242impl AsUniform for Angle<f32> {
243 fn as_uniform(&self) -> Uniform {
244 Uniform::Float(self.0)
245 }
246}
247
248#[cfg(feature = "uniforms")]
249impl AsUniform for Angle<f64> {
250 fn as_uniform(&self) -> Uniform {
251 Uniform::Double(self.0)
252 }
253}
254
255impl<T> Debug for Angle<T> where T: Debug + Float {
258 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
259 write!(f, "Angle({:?})", self.0)
260 }
261}