use crate::geometry::rect::Rect;
#[derive(Clone, Copy, Debug)]
pub struct Matrix {
pub a: f64,
pub b: f64,
pub c: f64,
pub d: f64,
pub e: f64,
pub f: f64,
}
impl Matrix {
pub fn identity() -> Self {
Matrix {
a: 1.0,
b: 0.0,
c: 0.0,
d: 1.0,
e: 0.0,
f: 0.0,
}
}
pub fn from_values(a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) -> Self {
Matrix { a, b, c, d, e, f }
}
pub fn concat(&self, other: &Matrix) -> Matrix {
Matrix {
a: self.a * other.a + self.b * other.c,
b: self.a * other.b + self.b * other.d,
c: self.c * other.a + self.d * other.c,
d: self.c * other.b + self.d * other.d,
e: self.e * other.a + self.f * other.c + other.e,
f: self.e * other.b + self.f * other.d + other.f,
}
}
pub fn transform_point(&self, x: f64, y: f64) -> (f64, f64) {
(
self.a * x + self.c * y + self.e,
self.b * x + self.d * y + self.f,
)
}
pub fn transform_rect(&self, rect: &Rect) -> Rect {
let corners = [
self.transform_point(rect.x, rect.y),
self.transform_point(rect.x + rect.width, rect.y),
self.transform_point(rect.x, rect.y + rect.height),
self.transform_point(rect.x + rect.width, rect.y + rect.height),
];
let min_x = corners
.iter()
.map(|(x, _)| *x)
.fold(f64::INFINITY, f64::min);
let max_x = corners
.iter()
.map(|(x, _)| *x)
.fold(f64::NEG_INFINITY, f64::max);
let min_y = corners
.iter()
.map(|(_, y)| *y)
.fold(f64::INFINITY, f64::min);
let max_y = corners
.iter()
.map(|(_, y)| *y)
.fold(f64::NEG_INFINITY, f64::max);
Rect {
x: min_x,
y: min_y,
width: max_x - min_x,
height: max_y - min_y,
}
}
}