polyhedron 0.1.0

A half edge and radial edge implementation.
Documentation
use itertools::Itertools;
use linear_isomorphic::{InnerSpace, RealField};

/// Approximates a vertex normals given an iterator over the faces of the
/// model.
pub fn approx_normals<S, M, F, V>(vert_count: usize, face_iter: M) -> Vec<V>
where
    M: Iterator<Item = F>,
    F: Iterator<Item = (V, usize)>,
    V: InnerSpace<S> + std::fmt::Debug,
    S: RealField,
{
    let mut res = vec![V::default(); vert_count];
    let mut weights = vec![S::from(0.).unwrap(); vert_count];
    for face in face_iter
    {
        let (verts, ids): (Vec<_>, Vec<_>) = face.unzip();

        let mut id = 0;
        for (&ref prev, &ref current, &ref next) in verts.iter().circular_tuple_windows()
        {
            let d1 = (prev.clone() - current.clone()).normalized();
            let d2 = (next.clone() - current.clone()).normalized();
            let mut n = d1.cross(&d2);
            let mut weight = (d1.dot(&d2)).acos();

            if !weight.is_finite()
            {
                weight = S::from(1).unwrap();
                n[0] = S::from(1).unwrap();
                n[1] = S::from(0).unwrap();
                n[2] = S::from(0).unwrap();
            }

            res[ids[id]] = res[ids[id]].clone() + n;
            weights[ids[id]] += weight;
            id += 1;
        }
    }

    for (i, w) in weights.iter().enumerate()
    {
        res[i] = res[i].clone() * (S::from(1.0).unwrap() / *w);
    }

    res
}