1use super::{EQ_EPSILON, EQ_EPSILON_100, Factor, about_eq};
2
3use std::{
4 f32::consts::{PI, TAU},
5 fmt, ops,
6};
7
8#[derive(Copy, Clone, serde::Serialize, serde::Deserialize)]
16#[serde(transparent)]
17pub struct AngleRadian(pub f32);
18impl ops::Add for AngleRadian {
19 type Output = Self;
20
21 fn add(self, rhs: Self) -> Self::Output {
22 Self(self.0 + rhs.0)
23 }
24}
25impl ops::AddAssign for AngleRadian {
26 fn add_assign(&mut self, rhs: Self) {
27 self.0 += rhs.0;
28 }
29}
30impl ops::Sub for AngleRadian {
31 type Output = Self;
32
33 fn sub(self, rhs: Self) -> Self::Output {
34 Self(self.0 - rhs.0)
35 }
36}
37impl ops::SubAssign for AngleRadian {
38 fn sub_assign(&mut self, rhs: Self) {
39 self.0 -= rhs.0;
40 }
41}
42impl ops::Neg for AngleRadian {
43 type Output = Self;
44
45 fn neg(self) -> Self::Output {
46 Self(-self.0)
47 }
48}
49impl AngleRadian {
50 pub fn modulo(self) -> Self {
52 AngleRadian(self.0.rem_euclid(TAU))
53 }
54
55 pub fn lerp(self, to: Self, factor: Factor) -> Self {
57 Self(lerp(self.0, to.0, factor))
58 }
59
60 pub fn slerp(self, to: Self, factor: Factor) -> Self {
70 Self(slerp(self.0, to.0, TAU, factor))
71 }
72}
73
74impl PartialEq for AngleRadian {
75 fn eq(&self, other: &Self) -> bool {
76 about_eq(self.0, other.0, EQ_EPSILON)
77 }
78}
79
80impl From<AngleGradian> for AngleRadian {
81 fn from(grad: AngleGradian) -> Self {
82 AngleRadian(grad.0 * PI / 200.0)
83 }
84}
85impl From<AngleDegree> for AngleRadian {
86 fn from(deg: AngleDegree) -> Self {
87 AngleRadian(deg.0.to_radians())
88 }
89}
90impl From<AngleTurn> for AngleRadian {
91 fn from(turn: AngleTurn) -> Self {
92 AngleRadian(turn.0 * TAU)
93 }
94}
95impl From<AngleRadian> for euclid::Angle<f32> {
96 fn from(rad: AngleRadian) -> Self {
97 euclid::Angle::radians(rad.0)
98 }
99}
100
101impl fmt::Debug for AngleRadian {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 if f.alternate() {
104 f.debug_tuple("AngleRadian").field(&self.0).finish()
105 } else {
106 write!(f, "{}.rad()", self.0)
107 }
108 }
109}
110impl fmt::Display for AngleRadian {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 write!(f, "{} rad", self.0)
113 }
114}
115
116#[derive(Copy, Clone, serde::Serialize, serde::Deserialize)]
124#[serde(transparent)]
125pub struct AngleGradian(pub f32);
126impl AngleGradian {
127 pub fn modulo(self) -> Self {
129 AngleGradian(self.0.rem_euclid(400.0))
130 }
131
132 pub fn lerp(self, to: Self, factor: Factor) -> Self {
134 Self(lerp(self.0, to.0, factor))
135 }
136
137 pub fn slerp(self, to: Self, factor: Factor) -> Self {
147 Self(slerp(self.0, to.0, 400.0, factor))
148 }
149}
150impl ops::Add for AngleGradian {
151 type Output = Self;
152
153 fn add(self, rhs: Self) -> Self::Output {
154 Self(self.0 + rhs.0)
155 }
156}
157impl ops::AddAssign for AngleGradian {
158 fn add_assign(&mut self, rhs: Self) {
159 self.0 += rhs.0;
160 }
161}
162impl ops::Sub for AngleGradian {
163 type Output = Self;
164
165 fn sub(self, rhs: Self) -> Self::Output {
166 Self(self.0 - rhs.0)
167 }
168}
169impl ops::SubAssign for AngleGradian {
170 fn sub_assign(&mut self, rhs: Self) {
171 self.0 -= rhs.0;
172 }
173}
174impl ops::Neg for AngleGradian {
175 type Output = Self;
176
177 fn neg(self) -> Self::Output {
178 Self(-self.0)
179 }
180}
181
182impl PartialEq for AngleGradian {
183 fn eq(&self, other: &Self) -> bool {
184 about_eq(self.0, other.0, EQ_EPSILON_100)
185 }
186}
187impl From<AngleRadian> for AngleGradian {
188 fn from(rad: AngleRadian) -> Self {
189 AngleGradian(rad.0 * 200.0 / PI)
190 }
191}
192impl From<AngleDegree> for AngleGradian {
193 fn from(deg: AngleDegree) -> Self {
194 AngleGradian(deg.0 * 10.0 / 9.0)
195 }
196}
197impl From<AngleTurn> for AngleGradian {
198 fn from(turn: AngleTurn) -> Self {
199 AngleGradian(turn.0 * 400.0)
200 }
201}
202impl fmt::Debug for AngleGradian {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 if f.alternate() {
205 f.debug_tuple("AngleGradian").field(&self.0).finish()
206 } else {
207 write!(f, "{}.grad()", self.0)
208 }
209 }
210}
211impl fmt::Display for AngleGradian {
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 write!(f, "{} gon", self.0)
214 }
215}
216
217#[derive(Copy, Clone, serde::Serialize, serde::Deserialize)]
225#[serde(transparent)]
226pub struct AngleDegree(pub f32);
227impl AngleDegree {
228 pub fn modulo(self) -> Self {
230 AngleDegree(self.0.rem_euclid(360.0))
231 }
232
233 pub fn lerp(self, to: Self, factor: Factor) -> Self {
235 Self(lerp(self.0, to.0, factor))
236 }
237
238 pub fn slerp(self, to: Self, factor: Factor) -> Self {
248 Self(slerp(self.0, to.0, 360.0, factor))
249 }
250}
251impl ops::Add for AngleDegree {
252 type Output = Self;
253
254 fn add(self, rhs: Self) -> Self::Output {
255 Self(self.0 + rhs.0)
256 }
257}
258impl ops::AddAssign for AngleDegree {
259 fn add_assign(&mut self, rhs: Self) {
260 self.0 += rhs.0;
261 }
262}
263impl ops::Sub for AngleDegree {
264 type Output = Self;
265
266 fn sub(self, rhs: Self) -> Self::Output {
267 Self(self.0 - rhs.0)
268 }
269}
270impl ops::SubAssign for AngleDegree {
271 fn sub_assign(&mut self, rhs: Self) {
272 self.0 -= rhs.0;
273 }
274}
275impl ops::Neg for AngleDegree {
276 type Output = Self;
277
278 fn neg(self) -> Self::Output {
279 Self(-self.0)
280 }
281}
282
283impl PartialEq for AngleDegree {
284 fn eq(&self, other: &Self) -> bool {
285 about_eq(self.0, other.0, EQ_EPSILON_100)
286 }
287}
288impl From<AngleRadian> for AngleDegree {
289 fn from(rad: AngleRadian) -> Self {
290 AngleDegree(rad.0.to_degrees())
291 }
292}
293impl From<AngleGradian> for AngleDegree {
294 fn from(grad: AngleGradian) -> Self {
295 AngleDegree(grad.0 * 9.0 / 10.0)
296 }
297}
298impl From<AngleTurn> for AngleDegree {
299 fn from(turn: AngleTurn) -> Self {
300 AngleDegree(turn.0 * 360.0)
301 }
302}
303impl fmt::Debug for AngleDegree {
304 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305 if f.alternate() {
306 f.debug_tuple("AngleDegree").field(&self.0).finish()
307 } else {
308 write!(f, "{}.deg()", self.0)
309 }
310 }
311}
312impl fmt::Display for AngleDegree {
313 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314 write!(f, "{}º", self.0)
315 }
316}
317
318#[derive(Copy, Clone, serde::Serialize, serde::Deserialize)]
326#[serde(transparent)]
327pub struct AngleTurn(pub f32);
328impl AngleTurn {
329 pub fn modulo(self) -> Self {
331 AngleTurn(self.0.rem_euclid(1.0))
332 }
333
334 pub fn lerp(self, to: Self, factor: Factor) -> Self {
336 Self(lerp(self.0, to.0, factor))
337 }
338
339 pub fn slerp(self, to: Self, factor: Factor) -> Self {
349 Self(slerp(self.0, to.0, 1.0, factor))
350 }
351}
352impl ops::Add for AngleTurn {
353 type Output = Self;
354
355 fn add(self, rhs: Self) -> Self::Output {
356 Self(self.0 + rhs.0)
357 }
358}
359impl ops::AddAssign for AngleTurn {
360 fn add_assign(&mut self, rhs: Self) {
361 self.0 += rhs.0;
362 }
363}
364impl ops::Sub for AngleTurn {
365 type Output = Self;
366
367 fn sub(self, rhs: Self) -> Self::Output {
368 Self(self.0 - rhs.0)
369 }
370}
371impl ops::SubAssign for AngleTurn {
372 fn sub_assign(&mut self, rhs: Self) {
373 self.0 -= rhs.0;
374 }
375}
376impl ops::Neg for AngleTurn {
377 type Output = Self;
378
379 fn neg(self) -> Self::Output {
380 Self(-self.0)
381 }
382}
383
384impl fmt::Debug for AngleTurn {
385 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
386 if f.alternate() {
387 f.debug_tuple("AngleTurn").field(&self.0).finish()
388 } else {
389 write!(f, "{}.turn()", self.0)
390 }
391 }
392}
393impl fmt::Display for AngleTurn {
394 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395 if (self.0 - 1.0).abs() < 0.0001 {
396 write!(f, "1 turn")
397 } else {
398 write!(f, "{} turns", self.0)
399 }
400 }
401}
402impl PartialEq for AngleTurn {
403 fn eq(&self, other: &Self) -> bool {
404 about_eq(self.0, other.0, EQ_EPSILON)
405 }
406}
407
408impl From<AngleRadian> for AngleTurn {
409 fn from(rad: AngleRadian) -> Self {
410 AngleTurn(rad.0 / TAU)
411 }
412}
413impl From<AngleGradian> for AngleTurn {
414 fn from(grad: AngleGradian) -> Self {
415 AngleTurn(grad.0 / 400.0)
416 }
417}
418impl From<AngleDegree> for AngleTurn {
419 fn from(deg: AngleDegree) -> Self {
420 AngleTurn(deg.0 / 360.0)
421 }
422}
423
424pub trait AngleUnits {
438 fn rad(self) -> AngleRadian;
440 fn grad(self) -> AngleGradian;
442 fn deg(self) -> AngleDegree;
444 fn turn(self) -> AngleTurn;
446}
447impl AngleUnits for f32 {
448 fn rad(self) -> AngleRadian {
449 AngleRadian(self)
450 }
451
452 fn grad(self) -> AngleGradian {
453 AngleGradian(self)
454 }
455
456 fn deg(self) -> AngleDegree {
457 AngleDegree(self)
458 }
459
460 fn turn(self) -> AngleTurn {
461 AngleTurn(self)
462 }
463}
464impl AngleUnits for i32 {
465 fn rad(self) -> AngleRadian {
466 AngleRadian(self as f32)
467 }
468
469 fn grad(self) -> AngleGradian {
470 AngleGradian(self as f32)
471 }
472
473 fn deg(self) -> AngleDegree {
474 AngleDegree(self as f32)
475 }
476
477 fn turn(self) -> AngleTurn {
478 AngleTurn(self as f32)
479 }
480}
481
482fn lerp(from: f32, to: f32, factor: Factor) -> f32 {
483 from + (to - from) * factor.0
484}
485
486fn slerp(from: f32, to: f32, turn: f32, factor: Factor) -> f32 {
487 let angle_to = {
488 let d = (to - from) % turn;
489 2.0 * d % turn - d
490 };
491 from + angle_to * factor.0
492}