///|
/// 2×3 affine transform matrix.
/// Maps `(x, y)` -> `(a*x + c*y + e, b*x + d*y + f)`.
/// Storage follows the Canvas2D convention `setTransform(a, b, c, d, e, f)`.
pub struct Matrix2D {
a : Double
b : Double
c : Double
d : Double
e : Double
f : Double
} derive(Eq, @debug.Debug)
///|
pub impl Show for Matrix2D with fn output(self, logger) {
logger.write_string("Matrix2D { a: ")
logger.write_object(self.a)
logger.write_string(", b: ")
logger.write_object(self.b)
logger.write_string(", c: ")
logger.write_object(self.c)
logger.write_string(", d: ")
logger.write_object(self.d)
logger.write_string(", e: ")
logger.write_object(self.e)
logger.write_string(", f: ")
logger.write_object(self.f)
logger.write_string(" }")
}
///|
pub fn Matrix2D::identity() -> Matrix2D {
{ a: 1.0, b: 0.0, c: 0.0, d: 1.0, e: 0.0, f: 0.0 }
}
///|
pub fn Matrix2D::of(
a : Double,
b : Double,
c : Double,
d : Double,
e : Double,
f : Double,
) -> Matrix2D {
{ a, b, c, d, e, f }
}
///|
pub fn Matrix2D::multiply(self : Matrix2D, o : Matrix2D) -> Matrix2D {
{
a: self.a * o.a + self.c * o.b,
b: self.b * o.a + self.d * o.b,
c: self.a * o.c + self.c * o.d,
d: self.b * o.c + self.d * o.d,
e: self.a * o.e + self.c * o.f + self.e,
f: self.b * o.e + self.d * o.f + self.f,
}
}
///|
pub fn Matrix2D::translate(self : Matrix2D, x : Double, y : Double) -> Matrix2D {
self.multiply(Matrix2D::of(1.0, 0.0, 0.0, 1.0, x, y))
}
///|
pub fn Matrix2D::scale(self : Matrix2D, sx : Double, sy : Double) -> Matrix2D {
self.multiply(Matrix2D::of(sx, 0.0, 0.0, sy, 0.0, 0.0))
}
///|
pub fn Matrix2D::rotate(self : Matrix2D, angle : Double) -> Matrix2D {
let c = @math.cos(angle)
let s = @math.sin(angle)
self.multiply(Matrix2D::of(c, s, -s, c, 0.0, 0.0))
}
///|
pub fn Matrix2D::transform_point(
self : Matrix2D,
x : Double,
y : Double,
) -> (Double, Double) {
(self.a * x + self.c * y + self.e, self.b * x + self.d * y + self.f)
}
///|
/// Returns the affine inverse of this matrix, or `None` if the matrix is
/// singular (determinant is zero).
pub fn Matrix2D::invert(self : Matrix2D) -> Matrix2D? {
let det = self.a * self.d - self.b * self.c
if det == 0.0 {
None
} else {
let inv_det = 1.0 / det
Some({
a: self.d * inv_det,
b: -self.b * inv_det,
c: -self.c * inv_det,
d: self.a * inv_det,
e: (self.c * self.f - self.d * self.e) * inv_det,
f: (self.b * self.e - self.a * self.f) * inv_det,
})
}
}