use crate::Float;
use nalgebra::{Matrix2, Point2, Vector2};
#[derive(Clone, Copy, Debug)]
pub struct AffineTransform2D<F: Float = f32> {
pub linear: Matrix2<F>,
pub translation: Vector2<F>,
}
impl<F: Float> AffineTransform2D<F> {
pub fn from_triangle_correspondence(src: [Point2<F>; 3], dst: [Point2<F>; 3]) -> Option<Self> {
let ds1 = src[1] - src[0];
let ds2 = src[2] - src[0];
let dd1 = dst[1] - dst[0];
let dd2 = dst[2] - dst[0];
let src_mat = Matrix2::new(ds1.x, ds2.x, ds1.y, ds2.y);
let src_inv = src_mat.try_inverse()?;
let dst_mat = Matrix2::new(dd1.x, dd2.x, dd1.y, dd2.y);
let linear = dst_mat * src_inv;
let t = dst[0] - linear * Vector2::new(src[0].x, src[0].y);
let translation = Vector2::new(t.x, t.y);
Some(Self {
linear,
translation,
})
}
pub fn apply(&self, p: Point2<F>) -> Point2<F> {
let v = self.linear * Vector2::new(p.x, p.y) + self.translation;
Point2::new(v.x, v.y)
}
}