homography 0.2.0

Homography estimation using point and line correspondences
Documentation
use crate::{
    geo::{Line, Point},
    interface::{Matrix2x9, WithRestriction},
};

use nalgebra::{ArrayStorage, Matrix, Scalar, U1, U9};
use num_traits::Float;

#[derive(Debug, Clone)]
pub struct PointPair<T = f32> {
    pub p1: Point<T>,
    pub p2: Point<T>,
}

#[derive(Debug, Clone)]
pub struct LinePair<T = f32> {
    pub l1: Line<T>,
    pub l2: Line<T>,
}

type RowVector9<T> = Matrix<T, U1, U9, ArrayStorage<T, 1, 9>>;

impl<T: Float + Scalar> WithRestriction<T> for PointPair<T> {
    fn generate_restriction(&self) -> Matrix2x9<T> {
        let p1 = &self.p1;
        let p2 = &self.p2;

        let first_row = RowVector9::from_vec(vec![
            T::zero(),
            T::zero(),
            T::zero(),
            -p1.x,
            -p1.y,
            -T::one(),
            p1.x * p2.y,
            p1.y * p2.y,
            p2.y,
        ]);

        let second_row = RowVector9::from_vec(vec![
            p1.x,
            p1.y,
            T::one(),
            T::zero(),
            T::zero(),
            T::zero(),
            -p1.x * p2.x,
            -p1.y * p2.x,
            -p2.x,
        ]);

        Matrix2x9::from_rows(&vec![first_row, second_row])
    }
}

impl<T: Float + Scalar> WithRestriction<T> for LinePair<T> {
    fn generate_restriction(&self) -> Matrix2x9<T> {
        let l1 = &self.l1;
        let l2 = &self.l2;

        let first_row = RowVector9::from_vec(vec![
            T::zero(),
            -l1.c * l2.a,
            l1.b * l2.a,
            T::zero(),
            -l1.c * l2.b,
            l1.b * l2.b,
            T::zero(),
            -l1.c * l2.c,
            l1.b * l2.c,
        ]);

        let second_row = RowVector9::from_vec(vec![
            l1.c * l2.a,
            T::zero(),
            -l1.a * l2.a,
            l1.c * l2.b,
            T::zero(),
            -l1.a * l2.b,
            l1.c * l2.c,
            T::zero(),
            -l1.a * l2.c,
        ]);

        return Matrix2x9::from_rows(&vec![first_row, second_row]);
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generate_restriction_point_pair() {
        let p1 = Point::new(1., 2.);
        let p2 = Point::new(3., 4.);
        let pair = PointPair { p1, p2 };

        let _restriction = pair.generate_restriction();
    }

    #[test]
    fn test_generate_restriction_line_pair() {
        let l1 = Line::new(1., 2., 3.);
        let l2 = Line::new(4., 5., 6.);
        let pair = LinePair { l1, l2 };

        let _restriction = pair.generate_restriction();
    }
}