Skip to main content

glam/f64/
daffine2.rs

1// Generated from affine.rs.tera template. Edit the template, not the generated file.
2
3use crate::{DMat2, DMat3, DVec2};
4use core::ops::{Deref, DerefMut, Mul, MulAssign};
5
6#[cfg(feature = "zerocopy-08")]
7use zerocopy_derive_08::*;
8
9/// A 2D affine transform, which can represent translation, rotation, scaling and shear.
10#[derive(Copy, Clone)]
11#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
12#[cfg_attr(
13    feature = "zerocopy-08",
14    derive(FromBytes, Immutable, IntoBytes, KnownLayout)
15)]
16#[repr(C)]
17pub struct DAffine2 {
18    pub matrix2: DMat2,
19    pub translation: DVec2,
20}
21
22impl DAffine2 {
23    /// The degenerate zero transform.
24    ///
25    /// This transforms any finite vector and point to zero.
26    /// The zero transform is non-invertible.
27    pub const ZERO: Self = Self {
28        matrix2: DMat2::ZERO,
29        translation: DVec2::ZERO,
30    };
31
32    /// The identity transform.
33    ///
34    /// Multiplying a vector with this returns the same vector.
35    pub const IDENTITY: Self = Self {
36        matrix2: DMat2::IDENTITY,
37        translation: DVec2::ZERO,
38    };
39
40    /// All NAN:s.
41    pub const NAN: Self = Self {
42        matrix2: DMat2::NAN,
43        translation: DVec2::NAN,
44    };
45
46    /// Creates an affine transform from three column vectors.
47    #[inline(always)]
48    #[must_use]
49    pub const fn from_cols(x_axis: DVec2, y_axis: DVec2, z_axis: DVec2) -> Self {
50        Self {
51            matrix2: DMat2::from_cols(x_axis, y_axis),
52            translation: z_axis,
53        }
54    }
55
56    /// Creates an affine transform from a `[f64; 6]` array stored in column major order.
57    #[inline]
58    #[must_use]
59    pub fn from_cols_array(m: &[f64; 6]) -> Self {
60        Self {
61            matrix2: DMat2::from_cols_array(&[m[0], m[1], m[2], m[3]]),
62            translation: DVec2::from_array([m[4], m[5]]),
63        }
64    }
65
66    /// Creates a `[f64; 6]` array storing data in column major order.
67    #[inline]
68    #[must_use]
69    pub fn to_cols_array(&self) -> [f64; 6] {
70        let x = &self.matrix2.x_axis;
71        let y = &self.matrix2.y_axis;
72        let z = &self.translation;
73        [x.x, x.y, y.x, y.y, z.x, z.y]
74    }
75
76    /// Creates an affine transform from a `[[f64; 2]; 3]`
77    /// 2D array stored in column major order.
78    /// If your data is in row major order you will need to `transpose` the returned
79    /// matrix.
80    #[inline]
81    #[must_use]
82    pub fn from_cols_array_2d(m: &[[f64; 2]; 3]) -> Self {
83        Self {
84            matrix2: DMat2::from_cols(m[0].into(), m[1].into()),
85            translation: m[2].into(),
86        }
87    }
88
89    /// Creates a `[[f64; 2]; 3]` 2D array storing data in
90    /// column major order.
91    /// If you require data in row major order `transpose` the matrix first.
92    #[inline]
93    #[must_use]
94    pub fn to_cols_array_2d(&self) -> [[f64; 2]; 3] {
95        [
96            self.matrix2.x_axis.into(),
97            self.matrix2.y_axis.into(),
98            self.translation.into(),
99        ]
100    }
101
102    /// Creates an affine transform from the first 6 values in `slice`.
103    ///
104    /// # Panics
105    ///
106    /// Panics if `slice` is less than 6 elements long.
107    #[inline]
108    #[must_use]
109    pub fn from_cols_slice(slice: &[f64]) -> Self {
110        Self {
111            matrix2: DMat2::from_cols_slice(&slice[0..4]),
112            translation: DVec2::from_slice(&slice[4..6]),
113        }
114    }
115
116    /// Writes the columns of `self` to the first 6 elements in `slice`.
117    ///
118    /// # Panics
119    ///
120    /// Panics if `slice` is less than 6 elements long.
121    #[inline]
122    pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
123        self.matrix2.write_cols_to_slice(&mut slice[0..4]);
124        self.translation.write_to_slice(&mut slice[4..6]);
125    }
126
127    /// Creates an affine transform that changes scale.
128    /// Note that if any scale is zero the transform will be non-invertible.
129    #[inline]
130    #[must_use]
131    pub fn from_scale(scale: DVec2) -> Self {
132        Self {
133            matrix2: DMat2::from_diagonal(scale),
134            translation: DVec2::ZERO,
135        }
136    }
137
138    /// Creates an affine transform from the given rotation `angle`.
139    #[inline]
140    #[must_use]
141    pub fn from_angle(angle: f64) -> Self {
142        Self {
143            matrix2: DMat2::from_angle(angle),
144            translation: DVec2::ZERO,
145        }
146    }
147
148    /// Creates an affine transformation from the given 2D `translation`.
149    #[inline]
150    #[must_use]
151    pub fn from_translation(translation: DVec2) -> Self {
152        Self {
153            matrix2: DMat2::IDENTITY,
154            translation,
155        }
156    }
157
158    /// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation)
159    #[inline]
160    #[must_use]
161    pub fn from_mat2(matrix2: DMat2) -> Self {
162        Self {
163            matrix2,
164            translation: DVec2::ZERO,
165        }
166    }
167
168    /// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation) and a
169    /// translation vector.
170    ///
171    /// Equivalent to
172    /// `DAffine2::from_translation(translation) * DAffine2::from_mat2(mat2)`
173    #[inline]
174    #[must_use]
175    pub fn from_mat2_translation(matrix2: DMat2, translation: DVec2) -> Self {
176        Self {
177            matrix2,
178            translation,
179        }
180    }
181
182    /// Creates an affine transform from the given 2D `scale`, rotation `angle` (in radians) and
183    /// `translation`.
184    ///
185    /// Equivalent to `DAffine2::from_translation(translation) *
186    /// DAffine2::from_angle(angle) * DAffine2::from_scale(scale)`
187    #[inline]
188    #[must_use]
189    pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
190        let rotation = DMat2::from_angle(angle);
191        Self {
192            matrix2: DMat2::from_cols(rotation.x_axis * scale.x, rotation.y_axis * scale.y),
193            translation,
194        }
195    }
196
197    /// Creates an affine transform from the given 2D rotation `angle` (in radians) and
198    /// `translation`.
199    ///
200    /// Equivalent to `DAffine2::from_translation(translation) * DAffine2::from_angle(angle)`
201    #[inline]
202    #[must_use]
203    pub fn from_angle_translation(angle: f64, translation: DVec2) -> Self {
204        Self {
205            matrix2: DMat2::from_angle(angle),
206            translation,
207        }
208    }
209
210    /// The given `DMat3` must be an affine transform,
211    #[inline]
212    #[must_use]
213    pub fn from_mat3(m: DMat3) -> Self {
214        use crate::swizzles::Vec3Swizzles;
215        Self {
216            matrix2: DMat2::from_cols(m.x_axis.xy(), m.y_axis.xy()),
217            translation: m.z_axis.xy(),
218        }
219    }
220
221    /// Extracts `scale`, `angle` and `translation` from `self`.
222    ///
223    /// The transform is expected to be non-degenerate and without shearing, or the output
224    /// will be invalid.
225    ///
226    /// # Panics
227    ///
228    /// Will panic if the determinant `self.matrix2` is zero or if the resulting scale
229    /// vector contains any zero elements when `glam_assert` is enabled.
230    #[inline]
231    #[must_use]
232    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
233    pub fn to_scale_angle_translation(&self) -> (DVec2, f64, DVec2) {
234        use crate::f64::math;
235        let det = self.matrix2.determinant();
236        glam_assert!(det != 0.0);
237
238        let scale = DVec2::new(
239            self.matrix2.x_axis.length() * math::signum(det),
240            self.matrix2.y_axis.length(),
241        );
242
243        glam_assert!(scale.cmpne(DVec2::ZERO).all());
244
245        let angle = math::atan2(-self.matrix2.y_axis.x, self.matrix2.y_axis.y);
246
247        (scale, angle, self.translation)
248    }
249
250    /// Transforms the given 2D point, applying shear, scale, rotation and translation.
251    #[inline]
252    #[must_use]
253    pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
254        self.matrix2 * rhs + self.translation
255    }
256
257    /// Transforms the given 2D vector, applying shear, scale and rotation (but NOT
258    /// translation).
259    ///
260    /// To also apply translation, use [`Self::transform_point2()`] instead.
261    #[inline]
262    pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
263        self.matrix2 * rhs
264    }
265
266    /// Returns `true` if, and only if, all elements are finite.
267    ///
268    /// If any element is either `NaN`, positive or negative infinity, this will return
269    /// `false`.
270    #[inline]
271    #[must_use]
272    pub fn is_finite(&self) -> bool {
273        self.matrix2.is_finite() && self.translation.is_finite()
274    }
275
276    /// Returns `true` if any elements are `NaN`.
277    #[inline]
278    #[must_use]
279    pub fn is_nan(&self) -> bool {
280        self.matrix2.is_nan() || self.translation.is_nan()
281    }
282
283    /// Returns true if the absolute difference of all elements between `self` and `rhs`
284    /// is less than or equal to `max_abs_diff`.
285    ///
286    /// This can be used to compare if two 3x4 matrices contain similar elements. It works
287    /// best when comparing with a known value. The `max_abs_diff` that should be used used
288    /// depends on the values being compared against.
289    ///
290    /// For more see
291    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
292    #[inline]
293    #[must_use]
294    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
295        self.matrix2.abs_diff_eq(rhs.matrix2, max_abs_diff)
296            && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
297    }
298
299    /// Return the inverse of this transform.
300    ///
301    /// Note that if the transform is not invertible the result will be invalid.
302    ///
303    /// # Panics
304    ///
305    /// Will panic if the resulting inverted matrix is not finite when `glam_assert` is enabled.
306    #[inline]
307    #[must_use]
308    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
309    pub fn inverse(&self) -> Self {
310        let matrix2 = self.matrix2.inverse();
311        // transform negative translation by the matrix inverse:
312        let translation = -(matrix2 * self.translation);
313
314        Self {
315            matrix2,
316            translation,
317        }
318    }
319
320    /// Casts all elements of `self` to `f32`.
321    #[inline]
322    #[must_use]
323    pub fn as_affine2(&self) -> crate::Affine2 {
324        crate::Affine2::from_mat2_translation(self.matrix2.as_mat2(), self.translation.as_vec2())
325    }
326}
327
328impl Default for DAffine2 {
329    #[inline(always)]
330    fn default() -> Self {
331        Self::IDENTITY
332    }
333}
334
335impl Deref for DAffine2 {
336    type Target = crate::deref::Cols3<DVec2>;
337    #[inline(always)]
338    fn deref(&self) -> &Self::Target {
339        unsafe { &*(self as *const Self as *const Self::Target) }
340    }
341}
342
343impl DerefMut for DAffine2 {
344    #[inline(always)]
345    fn deref_mut(&mut self) -> &mut Self::Target {
346        unsafe { &mut *(self as *mut Self as *mut Self::Target) }
347    }
348}
349
350impl PartialEq for DAffine2 {
351    #[inline]
352    fn eq(&self, rhs: &Self) -> bool {
353        self.matrix2.eq(&rhs.matrix2) && self.translation.eq(&rhs.translation)
354    }
355}
356
357impl core::fmt::Debug for DAffine2 {
358    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
359        fmt.debug_struct(stringify!(DAffine2))
360            .field("matrix2", &self.matrix2)
361            .field("translation", &self.translation)
362            .finish()
363    }
364}
365
366impl core::fmt::Display for DAffine2 {
367    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
368        if let Some(p) = f.precision() {
369            write!(
370                f,
371                "[{:.*}, {:.*}, {:.*}]",
372                p, self.matrix2.x_axis, p, self.matrix2.y_axis, p, self.translation
373            )
374        } else {
375            write!(
376                f,
377                "[{}, {}, {}]",
378                self.matrix2.x_axis, self.matrix2.y_axis, self.translation
379            )
380        }
381    }
382}
383
384impl<'a> core::iter::Product<&'a Self> for DAffine2 {
385    fn product<I>(iter: I) -> Self
386    where
387        I: Iterator<Item = &'a Self>,
388    {
389        iter.fold(Self::IDENTITY, |a, &b| a * b)
390    }
391}
392
393impl Mul for DAffine2 {
394    type Output = Self;
395
396    #[inline]
397    fn mul(self, rhs: Self) -> Self {
398        Self {
399            matrix2: self.matrix2 * rhs.matrix2,
400            translation: self.matrix2 * rhs.translation + self.translation,
401        }
402    }
403}
404
405impl Mul<&Self> for DAffine2 {
406    type Output = Self;
407    #[inline]
408    fn mul(self, rhs: &Self) -> Self {
409        self.mul(*rhs)
410    }
411}
412
413impl Mul<&DAffine2> for &DAffine2 {
414    type Output = DAffine2;
415    #[inline]
416    fn mul(self, rhs: &DAffine2) -> DAffine2 {
417        (*self).mul(*rhs)
418    }
419}
420
421impl Mul<DAffine2> for &DAffine2 {
422    type Output = DAffine2;
423    #[inline]
424    fn mul(self, rhs: DAffine2) -> DAffine2 {
425        (*self).mul(rhs)
426    }
427}
428
429impl MulAssign for DAffine2 {
430    #[inline]
431    fn mul_assign(&mut self, rhs: Self) {
432        *self = self.mul(rhs);
433    }
434}
435
436impl MulAssign<&Self> for DAffine2 {
437    #[inline]
438    fn mul_assign(&mut self, rhs: &Self) {
439        self.mul_assign(*rhs);
440    }
441}
442
443impl From<DAffine2> for DMat3 {
444    #[inline]
445    fn from(m: DAffine2) -> Self {
446        Self::from_cols(
447            m.matrix2.x_axis.extend(0.0),
448            m.matrix2.y_axis.extend(0.0),
449            m.translation.extend(1.0),
450        )
451    }
452}
453
454impl Mul<DMat3> for DAffine2 {
455    type Output = DMat3;
456
457    #[inline]
458    fn mul(self, rhs: DMat3) -> Self::Output {
459        DMat3::from(self) * rhs
460    }
461}
462
463impl Mul<&DMat3> for DAffine2 {
464    type Output = DMat3;
465    #[inline]
466    fn mul(self, rhs: &DMat3) -> DMat3 {
467        self.mul(*rhs)
468    }
469}
470
471impl Mul<&DMat3> for &DAffine2 {
472    type Output = DMat3;
473    #[inline]
474    fn mul(self, rhs: &DMat3) -> DMat3 {
475        (*self).mul(*rhs)
476    }
477}
478
479impl Mul<DMat3> for &DAffine2 {
480    type Output = DMat3;
481    #[inline]
482    fn mul(self, rhs: DMat3) -> DMat3 {
483        (*self).mul(rhs)
484    }
485}
486
487impl Mul<DAffine2> for DMat3 {
488    type Output = Self;
489
490    #[inline]
491    fn mul(self, rhs: DAffine2) -> Self {
492        self * Self::from(rhs)
493    }
494}
495
496impl Mul<&DAffine2> for DMat3 {
497    type Output = Self;
498    #[inline]
499    fn mul(self, rhs: &DAffine2) -> Self {
500        self.mul(*rhs)
501    }
502}
503
504impl Mul<&DAffine2> for &DMat3 {
505    type Output = DMat3;
506    #[inline]
507    fn mul(self, rhs: &DAffine2) -> DMat3 {
508        (*self).mul(*rhs)
509    }
510}
511
512impl Mul<DAffine2> for &DMat3 {
513    type Output = DMat3;
514    #[inline]
515    fn mul(self, rhs: DAffine2) -> DMat3 {
516        (*self).mul(rhs)
517    }
518}
519
520impl MulAssign<DAffine2> for DMat3 {
521    #[inline]
522    fn mul_assign(&mut self, rhs: DAffine2) {
523        *self = self.mul(rhs);
524    }
525}
526
527impl MulAssign<&DAffine2> for DMat3 {
528    #[inline]
529    fn mul_assign(&mut self, rhs: &DAffine2) {
530        self.mul_assign(*rhs);
531    }
532}