ori_core/layout/
matrix.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use std::ops::Mul;

use super::{Point, Vector};

/// A 2x2 matrix.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Matrix {
    /// The x axis of the matrix.
    pub x: Vector,
    /// The y axis of the matrix.
    pub y: Vector,
}

impl Matrix {
    /// The identity matrix.
    pub const IDENTITY: Self = Self::from_scale(Vector::all(1.0));

    /// Create a new matrix.
    pub const fn new(x: Vector, y: Vector) -> Self {
        Self { x, y }
    }

    /// Create a new matrix from an angle.
    pub fn from_angle(angle: f32) -> Self {
        let (sin, cos) = angle.sin_cos();

        Self::new(Vector::new(cos, sin), Vector::new(-sin, cos))
    }

    /// Create a new matrix from a scale.
    pub const fn from_scale(scale: Vector) -> Self {
        Self::new(Vector::new(scale.x, 0.0), Vector::new(0.0, scale.y))
    }

    /// Compute the determinant of the matrix.
    pub fn determinant(self) -> f32 {
        self.x.x * self.y.y - self.x.y * self.y.x
    }

    /// Compute the inverse of the matrix.
    pub fn inverse(self) -> Self {
        let det = self.determinant();

        if det == 0.0 {
            return Self::IDENTITY;
        }

        let inv_det = 1.0 / det;

        Self::new(
            Vector::new(self.y.y * inv_det, -self.x.y * inv_det),
            Vector::new(-self.y.x * inv_det, self.x.x * inv_det),
        )
    }
}

impl From<Matrix> for [f32; 4] {
    fn from(matrix: Matrix) -> Self {
        [matrix.x.x, matrix.x.y, matrix.y.x, matrix.y.y]
    }
}

impl Mul<Vector> for Matrix {
    type Output = Vector;

    fn mul(self, point: Vector) -> Self::Output {
        Vector::new(
            self.x.x * point.x + self.y.x * point.y,
            self.x.y * point.x + self.y.y * point.y,
        )
    }
}

impl Mul<Point> for Matrix {
    type Output = Point;

    fn mul(self, point: Point) -> Self::Output {
        Vector::to_point(self * point.to_vector())
    }
}

impl Mul<Matrix> for Matrix {
    type Output = Self;

    fn mul(self, other: Self) -> Self::Output {
        Self::new(self * other.x, self * other.y)
    }
}