jagua_rs/geometry/
d_transformation.rs1use std::borrow::Borrow;
2use std::f32::consts::PI;
3use std::fmt::Display;
4
5use crate::geometry::Transformation;
6use ordered_float::NotNan;
7
8#[derive(Clone, Debug, PartialEq, Eq, Hash, Copy, Default)]
9pub struct DTransformation {
12 pub rotation: NotNan<f32>,
14 pub translation: (NotNan<f32>, NotNan<f32>),
16}
17
18impl DTransformation {
19 #[must_use]
20 pub fn new(rotation: f32, translation: (f32, f32)) -> Self {
21 Self {
22 rotation: NotNan::new(rotation).expect("rotation is NaN"),
23 translation: (
24 NotNan::new(translation.0).expect("translation.0 is NaN"),
25 NotNan::new(translation.1).expect("translation.1 is NaN"),
26 ),
27 }
28 }
29
30 #[must_use]
31 pub const fn empty() -> Self {
32 const _0: NotNan<f32> = unsafe { NotNan::new_unchecked(0.0) };
33 Self {
34 rotation: _0,
35 translation: (_0, _0),
36 }
37 }
38
39 #[must_use]
40 pub fn rotation(&self) -> f32 {
41 self.rotation.into()
42 }
43
44 #[must_use]
45 pub fn translation(&self) -> (f32, f32) {
46 (self.translation.0.into(), self.translation.1.into())
47 }
48
49 #[must_use]
50 pub fn compose(&self) -> Transformation {
51 self.into()
52 }
53}
54
55impl<T> From<T> for DTransformation
56where
57 T: Borrow<Transformation>,
58{
59 fn from(t: T) -> Self {
60 t.borrow().decompose()
61 }
62}
63
64impl Display for DTransformation {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 write!(
67 f,
68 "r: {:.3}°, t: ({:.3}, {:.3})",
69 self.rotation.to_degrees(),
70 self.translation.0.into_inner(),
71 self.translation.1.into_inner()
72 )
73 }
74}
75
76#[must_use]
78pub fn normalize_rotation(r: f32) -> f32 {
79 let normalized = r % (2.0 * PI);
80 if normalized < 0.0 {
81 normalized + 2.0 * PI
82 } else {
83 normalized
84 }
85}