offroad 0.0.1-alpha

2D offsetting for arc polylines.
Documentation
#![allow(dead_code)]

use crate::{line::Line, point::Point};

#[derive(Debug, PartialEq)]
pub enum LineConfig {
    ParallelDistinct(),
    ParallelTheSame(),
    OnePoint(Point, f64, f64),
}

const ZERO: f64 = 0f64;
pub fn int_line_line(line0: &Line, line1: &Line) -> LineConfig {
    let q = line1.origin - line0.origin;
    let dot_d0_perp_d1 = line0.dir.perp(line1.dir);
    if dot_d0_perp_d1 != ZERO {
        let dot_qperp_d0 = q.perp(line0.dir);
        let dot_qperp_d1 = q.perp(line1.dir);
        let s0 = dot_qperp_d1 / dot_d0_perp_d1;
        let s1 = dot_qperp_d0 / dot_d0_perp_d1;
        let p = line0.origin + line0.dir * s0;
        return LineConfig::OnePoint(p, s0, s1);
    } else {
        let dot_qperp_d1 = q.perp(line1.dir);
        if dot_qperp_d1.abs() != ZERO {
            return LineConfig::ParallelDistinct();
        } else {
            return LineConfig::ParallelTheSame();
        }
    }
}

#[cfg(test)]
mod test_intersect_line_line {
    use super::*;
    use crate::line::line;
    use crate::point::{almost_equal_as_int, point};

    #[test]
    fn test_parallel_distinct() {
        let sgrt_2_2 = std::f64::consts::SQRT_2 / 2.0;
        let l0 = line(point(0.0, 0.0), point(sgrt_2_2, sgrt_2_2));
        let l1 = line(point(f64::EPSILON, 0.0), point(sgrt_2_2, sgrt_2_2));
        assert_eq!(int_line_line(&l0, &l1), LineConfig::ParallelDistinct());
    }

    #[test]
    fn test_parallel_the_same() {
        let sgrt_2_2 = std::f64::consts::SQRT_2 / 2.0;
        let l0 = line(point(0.0, 0.0), point(sgrt_2_2, sgrt_2_2));
        let l1 = line(point(1.0, 1.0), point(sgrt_2_2, sgrt_2_2));
        assert_eq!(int_line_line(&l0, &l1), LineConfig::ParallelTheSame());
    }

    #[test]
    fn test_one_point() {
        let sgrt_2_2 = std::f64::consts::SQRT_2 / 2.0;
        let sgrt_2 = std::f64::consts::SQRT_2;
        let l0 = line(point(0.0, 0.0), point(sgrt_2_2, sgrt_2_2));
        let l1 = line(point(0.0, 2.0), point(sgrt_2_2, -sgrt_2_2));
        let res = int_line_line(&l0, &l1);
        match res {
            LineConfig::OnePoint(p, s0, s1) => {
                assert_eq!(p, point(1.0, 1.0));
                assert!(almost_equal_as_int(s0, sgrt_2, 1));
                assert!(almost_equal_as_int(s1, sgrt_2, 1));
            }
            _ => assert!(false),
        }
    }
}