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 reflected: bool,
14 pub rotation: NotNan<f32>,
16 pub translation: (NotNan<f32>, NotNan<f32>),
18}
19
20impl DTransformation {
21 #[must_use]
22 pub fn new(rotation: f32, translation: (f32, f32)) -> Self {
23 Self {
24 reflected: false,
25 rotation: NotNan::new(rotation).expect("rotation is NaN"),
26 translation: (
27 NotNan::new(translation.0).expect("translation.0 is NaN"),
28 NotNan::new(translation.1).expect("translation.1 is NaN"),
29 ),
30 }
31 }
32
33 #[must_use]
34 pub const fn empty() -> Self {
35 const _0: NotNan<f32> = unsafe { NotNan::new_unchecked(0.0) };
36 Self {
37 reflected: false,
38 rotation: _0,
39 translation: (_0, _0),
40 }
41 }
42
43 #[must_use]
45 pub fn with_reflection(mut self, reflected: bool) -> Self {
46 self.reflected = reflected;
47 self
48 }
49
50 #[must_use]
51 pub fn rotation(&self) -> f32 {
52 self.rotation.into()
53 }
54
55 #[must_use]
56 pub fn translation(&self) -> (f32, f32) {
57 (self.translation.0.into(), self.translation.1.into())
58 }
59
60 #[must_use]
61 pub fn compose(&self) -> Transformation {
62 self.into()
63 }
64}
65
66impl<T> From<T> for DTransformation
67where
68 T: Borrow<Transformation>,
69{
70 fn from(t: T) -> Self {
71 t.borrow().decompose()
72 }
73}
74
75impl Display for DTransformation {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 write!(
78 f,
79 "reflected: {}, r: {:.3}°, t: ({:.3}, {:.3})",
80 self.reflected,
81 self.rotation.to_degrees(),
82 self.translation.0.into_inner(),
83 self.translation.1.into_inner()
84 )
85 }
86}
87
88#[must_use]
90pub fn normalize_rotation(r: f32) -> f32 {
91 r.rem_euclid(2.0 * PI) % (2.0 * PI)
93}