// 2D transformation utilities
///|
/// Identity transformation
pub fn identity() -> Transform {
{ m11: 1.0, m12: 0.0, m21: 0.0, m22: 1.0, m31: 0.0, m32: 0.0 }
}
///|
/// Translation transformation
pub fn make_translate(dx : Double, dy : Double) -> Transform {
{ m11: 1.0, m12: 0.0, m21: 0.0, m22: 1.0, m31: dx, m32: dy }
}
///|
/// Scale transformation
pub fn make_scale(sx : Double, sy : Double) -> Transform {
{ m11: sx, m12: 0.0, m21: 0.0, m22: sy, m31: 0.0, m32: 0.0 }
}
///|
/// Uniform scale transformation
pub fn scale_uniform(s : Double) -> Transform {
make_scale(s, s)
}
///|
/// Rotation transformation (angle in radians)
pub fn make_rotate(angle : Double) -> Transform {
let cos_a = @math.cos(angle)
let sin_a = @math.sin(angle)
{ m11: cos_a, m12: -sin_a, m21: sin_a, m22: cos_a, m31: 0.0, m32: 0.0 }
}
///|
/// Skew X transformation
pub fn skew_x(angle : Double) -> Transform {
{ m11: 1.0, m12: @math.tan(angle), m21: 0.0, m22: 1.0, m31: 0.0, m32: 0.0 }
}
///|
/// Skew Y transformation
pub fn skew_y(angle : Double) -> Transform {
{ m11: 1.0, m12: 0.0, m21: @math.tan(angle), m22: 1.0, m31: 0.0, m32: 0.0 }
}
///|
/// Compose two transformations (multiply matrices)
pub fn compose_transforms(t1 : Transform, t2 : Transform) -> Transform {
{
m11: t1.m11 * t2.m11 + t1.m12 * t2.m21,
m12: t1.m11 * t2.m12 + t1.m12 * t2.m22,
m21: t1.m21 * t2.m11 + t1.m22 * t2.m21,
m22: t1.m21 * t2.m12 + t1.m22 * t2.m22,
m31: t1.m31 * t2.m11 + t1.m32 * t2.m21 + t2.m31,
m32: t1.m31 * t2.m12 + t1.m32 * t2.m22 + t2.m32,
}
}
///|
/// Apply transformation to a point
pub fn apply(t : Transform, p : Point) -> Point {
Point(t.m11 * p.x + t.m12 * p.y + t.m31, t.m21 * p.x + t.m22 * p.y + t.m32)
}
///|
/// Invert a transformation matrix
pub fn invert(t : Transform) -> Transform? {
let det = t.m11 * t.m22 - t.m12 * t.m21
if det == 0.0 {
None
} else {
let inv_det = 1.0 / det
Some({
m11: t.m22 * inv_det,
m12: -t.m12 * inv_det,
m21: -t.m21 * inv_det,
m22: t.m11 * inv_det,
m31: (t.m21 * t.m32 - t.m22 * t.m31) * inv_det,
m32: (t.m12 * t.m31 - t.m11 * t.m32) * inv_det,
})
}
}
///|
/// Get the determinant of the transformation
pub fn determinant(t : Transform) -> Double {
t.m11 * t.m22 - t.m12 * t.m21
}
///|
/// Check if transformation preserves orientation
pub fn preserves_orientation(t : Transform) -> Bool {
determinant(t) > 0.0
}