1use std::borrow::Borrow;
2use std::ops::{Add, Div, Mul, Sub};
3
4use ordered_float::NotNan;
5
6use crate::geometry::DTransformation;
7
8#[derive(Clone, Debug)]
9pub struct Transformation {
12 matrix: [[NotNan<f32>; 3]; 3],
13}
14
15impl Transformation {
16 pub const fn empty() -> Self {
18 Self {
19 matrix: EMPTY_MATRIX,
20 }
21 }
22
23 pub fn from_translation((tx, ty): (f32, f32)) -> Self {
24 Self {
25 matrix: transl_m((tx, ty)),
26 }
27 }
28
29 pub fn from_rotation(angle: f32) -> Self {
30 Self {
31 matrix: rot_m(angle),
32 }
33 }
34
35 pub fn rotate(mut self, angle: f32) -> Self {
37 self.matrix = dot_prod(&rot_m(angle), &self.matrix);
38 self
39 }
40
41 pub fn translate(mut self, (tx, ty): (f32, f32)) -> Self {
43 self.matrix = dot_prod(&transl_m((tx, ty)), &self.matrix);
44 self
45 }
46
47 pub fn rotate_translate(mut self, angle: f32, (tx, ty): (f32, f32)) -> Self {
49 self.matrix = dot_prod(&rot_transl_m(angle, (tx, ty)), &self.matrix);
50 self
51 }
52
53 pub fn translate_rotate(mut self, (tx, ty): (f32, f32), angle: f32) -> Self {
55 self.matrix = dot_prod(&transl_rot_m((tx, ty), angle), &self.matrix);
56 self
57 }
58
59 pub fn transform(mut self, other: &Self) -> Self {
61 self.matrix = dot_prod(&other.matrix, &self.matrix);
62 self
63 }
64
65 pub fn transform_from_decomposed(self, other: &DTransformation) -> Self {
66 self.rotate_translate(other.rotation(), other.translation())
67 }
68
69 pub fn inverse(mut self) -> Self {
71 self.matrix = inverse(&self.matrix);
72 self
73 }
74
75 pub fn is_empty(&self) -> bool {
76 self.matrix == EMPTY_MATRIX
77 }
78
79 pub fn matrix(&self) -> &[[NotNan<f32>; 3]; 3] {
80 &self.matrix
81 }
82
83 pub fn decompose(&self) -> DTransformation {
84 let m = self.matrix();
85 let angle = m[1][0].atan2(m[0][0].into_inner());
86 let (tx, ty) = (m[0][2].into_inner(), m[1][2].into_inner());
87 DTransformation::new(angle, (tx, ty))
88 }
89}
90
91impl<T> From<T> for Transformation
92where
93 T: Borrow<DTransformation>,
94{
95 fn from(dt: T) -> Self {
96 let rot = dt.borrow().rotation();
97 let transl = dt.borrow().translation();
98 Self {
99 matrix: rot_transl_m(rot, transl),
100 }
101 }
102}
103
104impl Default for Transformation {
105 fn default() -> Self {
106 Self::empty()
107 }
108}
109
110const _0: NotNan<f32> = unsafe { NotNan::new_unchecked(0.0) };
111const _1: NotNan<f32> = unsafe { NotNan::new_unchecked(1.0) };
112
113const EMPTY_MATRIX: [[NotNan<f32>; 3]; 3] = [[_1, _0, _0], [_0, _1, _0], [_0, _0, _1]];
114
115fn rot_m(angle: f32) -> [[NotNan<f32>; 3]; 3] {
116 let (sin, cos) = angle.sin_cos();
117 let cos = NotNan::new(cos).expect("cos is NaN");
118 let sin = NotNan::new(sin).expect("sin is NaN");
119
120 [[cos, -sin, _0], [sin, cos, _0], [_0, _0, _1]]
121}
122
123fn transl_m((tx, ty): (f32, f32)) -> [[NotNan<f32>; 3]; 3] {
124 let h = NotNan::new(tx).expect("tx is NaN");
125 let k = NotNan::new(ty).expect("ty is NaN");
126
127 [[_1, _0, h], [_0, _1, k], [_0, _0, _1]]
128}
129
130fn rot_transl_m(angle: f32, (tx, ty): (f32, f32)) -> [[NotNan<f32>; 3]; 3] {
132 let (sin, cos) = angle.sin_cos();
133 let cos = NotNan::new(cos).expect("cos is NaN");
134 let sin = NotNan::new(sin).expect("sin is NaN");
135 let h = NotNan::new(tx).expect("tx is NaN");
136 let k = NotNan::new(ty).expect("ty is NaN");
137
138 [[cos, -sin, h], [sin, cos, k], [_0, _0, _1]]
139}
140
141fn transl_rot_m((tx, ty): (f32, f32), angle: f32) -> [[NotNan<f32>; 3]; 3] {
143 let (sin, cos) = angle.sin_cos();
144 let cos = NotNan::new(cos).expect("cos is NaN");
145 let sin = NotNan::new(sin).expect("sin is NaN");
146 let h = NotNan::new(tx).expect("tx is NaN");
147 let k = NotNan::new(ty).expect("ty is NaN");
148
149 [
150 [cos, -sin, h * cos - k * sin],
151 [sin, cos, h * sin + k * cos],
152 [_0, _0, _1],
153 ]
154}
155
156#[inline(always)]
157fn dot_prod<T>(l: &[[T; 3]; 3], r: &[[T; 3]; 3]) -> [[T; 3]; 3]
158where
159 T: Add<Output = T> + Mul<Output = T> + Copy + Default,
160{
161 [
162 [
163 l[0][0] * r[0][0] + l[0][1] * r[1][0] + l[0][2] * r[2][0],
164 l[0][0] * r[0][1] + l[0][1] * r[1][1] + l[0][2] * r[2][1],
165 l[0][0] * r[0][2] + l[0][1] * r[1][2] + l[0][2] * r[2][2],
166 ],
167 [
168 l[1][0] * r[0][0] + l[1][1] * r[1][0] + l[1][2] * r[2][0],
169 l[1][0] * r[0][1] + l[1][1] * r[1][1] + l[1][2] * r[2][1],
170 l[1][0] * r[0][2] + l[1][1] * r[1][2] + l[1][2] * r[2][2],
171 ],
172 [
173 l[2][0] * r[0][0] + l[2][1] * r[1][0] + l[2][2] * r[2][0],
174 l[2][0] * r[0][1] + l[2][1] * r[1][1] + l[2][2] * r[2][1],
175 l[2][0] * r[0][2] + l[2][1] * r[1][2] + l[2][2] * r[2][2],
176 ],
177 ]
178}
179
180#[inline(always)]
181fn inverse<T>(m: &[[T; 3]; 3]) -> [[T; 3]; 3]
182where
183 T: Add<Output = T> + Mul<Output = T> + Sub<Output = T> + Div<Output = T> + Copy,
184{
185 let det =
186 m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0] + m[0][2] * m[1][0] * m[2][1]
187 - m[0][2] * m[1][1] * m[2][0]
188 - m[0][1] * m[1][0] * m[2][2]
189 - m[0][0] * m[1][2] * m[2][1];
190
191 [
192 [
193 (m[1][1] * m[2][2] - m[1][2] * m[2][1]) / det,
194 (m[0][2] * m[2][1] - m[0][1] * m[2][2]) / det,
195 (m[0][1] * m[1][2] - m[0][2] * m[1][1]) / det,
196 ],
197 [
198 (m[1][2] * m[2][0] - m[1][0] * m[2][2]) / det,
199 (m[0][0] * m[2][2] - m[0][2] * m[2][0]) / det,
200 (m[0][2] * m[1][0] - m[0][0] * m[1][2]) / det,
201 ],
202 [
203 (m[1][0] * m[2][1] - m[1][1] * m[2][0]) / det,
204 (m[0][1] * m[2][0] - m[0][0] * m[2][1]) / det,
205 (m[0][0] * m[1][1] - m[0][1] * m[1][0]) / det,
206 ],
207 ]
208}