del-geo 0.1.4

2D/3D geometry utility coddes
Documentation
use num_traits::AsPrimitive;

pub fn culling_intersection_<T>(
    po_s0: &[T],
    po_e0: &[T],
    po_s1: &[T],
    po_e1: &[T]) -> bool
    where T: num_traits::Float + 'static + Copy,
          f64: num_traits::AsPrimitive<T>
{
    let min0x = if po_s0[0] < po_e0[0] { po_s0[0] } else { po_e0[0] };
    let max0x = if po_s0[0] > po_e0[0] { po_s0[0] } else { po_e0[0] };
    let max1x = if po_s1[0] > po_e1[0] { po_s1[0] } else { po_e1[0] };
    let min1x = if po_s1[0] < po_e1[0] { po_s1[0] } else { po_e1[0] };
    let min0y = if po_s0[1] < po_e0[1] { po_s0[1] } else { po_e0[1] };
    let max0y = if po_s0[1] > po_e0[1] { po_s0[1] } else { po_e0[1] };
    let max1y = if po_s1[1] > po_e1[1] { po_s1[1] } else { po_e1[1] };
    let min1y = if po_s1[1] < po_e1[1] { po_s1[1] } else { po_e1[1] };
    let len = ((max0x - min0x) + (max0y - min0y) + (max1x - min1x) + (max1y - min1y)) * 0.0001_f64.as_();
    if max1x + len < min0x { return false; }
    if max0x + len < min1x { return false; }
    if max1y + len < min0y { return false; }
    if max0y + len < min1y { return false; }
    true
}


pub fn intersection_edge2_<T>(
    po_s0: &[T],
    po_e0: &[T],
    po_s1: &[T],
    po_e1: &[T]) -> Option<(T, T)>
    where T: num_traits::Float + 'static + Copy,
          f64: num_traits::AsPrimitive<T>
{
    let area1 = crate::tri2::area(po_s0, po_e0, po_s1);
    let area2 = crate::tri2::area(po_s0, po_e0, po_e1);
    let area3 = crate::tri2::area(po_s1, po_e1, po_s0);
    let area4 = crate::tri2::area(po_s1, po_e1, po_e0);
    if area1 * area2 > 0_f64.as_() { return None; }
    if area3 * area4 > 0_f64.as_() { return None; }
    let r1 = area1 / (area1 - area2);
    let r0 = area3 / (area3 - area4);
    return Some((r0, r1));
}

///////////////
// use nalgebra

pub fn intersect_edge2(
    po_s0: &nalgebra::Vector2<f32>,
    po_e0: &nalgebra::Vector2<f32>,
    po_s1: &nalgebra::Vector2<f32>,
    po_e1: &nalgebra::Vector2<f32>) -> bool {
    let area1 = crate::tri2::area(po_s0.as_slice(), po_e0.as_slice(), po_s1.as_slice());
    let area2 = crate::tri2::area(po_s0.as_slice(), po_e0.as_slice(), po_e1.as_slice());
    let area3 = crate::tri2::area(po_s1.as_slice(), po_e1.as_slice(), po_s0.as_slice());
    let area4 = crate::tri2::area(po_s1.as_slice(), po_e1.as_slice(), po_e0.as_slice());
    //  std::cout << area1 << " " << area2 << " " << area3 << " " << area4 << std::endl;
    let a12 = area1 * area2;
    if a12 > 0_f32 {
        return false;
    }
    let a34 = area3 * area4;
    if a34 > 0_f32 {
        return false;
    }
    return true;
}

pub fn distance_to_edge2<T>(
    po_s0: &nalgebra::Vector2<T>,
    po_e0: &nalgebra::Vector2<T>,
    po_s1: &nalgebra::Vector2<T>,
    po_e1: &nalgebra::Vector2<T>) -> T
    where T: num_traits::Float + nalgebra::RealField + 'static + Copy + std::fmt::Debug,
          f64: num_traits::AsPrimitive<T>
{
    if intersection_edge2_(po_s0.into(), po_e0.into(), po_s1.into(), po_e1.into()).is_some() {
        return -1_f64.as_();
    }
    let ds1 = crate::edge::distance_to_point(po_s0, po_s1, po_e1);
    let de1 = crate::edge::distance_to_point(po_e0, po_s1, po_e1);
    let ds0 = crate::edge::distance_to_point(po_s1, po_s0, po_e0);
    let de0 = crate::edge::distance_to_point(po_e1, po_s0, po_e0);
    let mut min_dist = ds1;
    min_dist = if de1 < min_dist { de1 } else { min_dist };
    min_dist = if ds0 < min_dist { ds0 } else { min_dist };
    min_dist = if de0 < min_dist { de0 } else { min_dist };
    min_dist
}

pub fn winding_number<T>(
    ps: &nalgebra::Vector2<T>,
    pe: &nalgebra::Vector2<T>,
    po: &nalgebra::Vector2<T>) -> T
    where T: nalgebra::RealField + Copy,
          f64: AsPrimitive<T>
{
    let p0 = ps - po;
    let p1 = pe - po;
    let y: T = p1[1] * p0[0] - p1[0] * p0[1];
    let x: T = p0[0] * p1[0] + p0[1] * p1[1];
    y.atan2(x) * std::f64::consts::FRAC_1_PI.as_() * 0.5.as_()
}