polyhedra 0.1.0

Polyhedra is a small library for creating polyhedra.
Documentation
use core::fmt::Debug;
use nalgebra as na;
use serde_derive::Deserialize;
use serde_derive::Serialize;
use std::collections::HashSet;
use std::hash::{Hash, Hasher};

pub(crate) trait CoordinateSpace {
    type Coordinate;
}

impl<T: na::Scalar> CoordinateSpace for na::Point3<T> {
    type Coordinate = na::Point3<T>;
}

impl<T: na::Scalar> CoordinateSpace for na::Vector3<T> {
    type Coordinate = na::Vector3<T>;
}

#[derive(Eq, Copy, Clone, Debug, Serialize, Deserialize)]
pub(crate) struct Boundary<T: PartialEq>(pub T, pub T);

impl<T: PartialEq> PartialEq for Boundary<T> {
    fn eq(&self, other: &Boundary<T>) -> bool {
        (self.0 == other.0 && self.1 == other.1) || (self.0 == other.1 && self.1 == other.0)
    }
}

impl<T: Hash + Eq + PartialOrd> Hash for Boundary<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        if self.0 < self.1 {
            self.0.hash(state);
            self.1.hash(state);
        } else {
            self.1.hash(state);
            self.0.hash(state);
        }
    }
}

/// T represents a discrete surface area / patch
/// V represents an vertex
pub(crate) trait Tiling<T, V, S>
where
    T: Eq + Hash,
    V: Eq + Hash + PartialOrd,
    S: CoordinateSpace,
{
    fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = &T> + 'a>;

    fn adjacent(&self, tile: &T) -> Vec<(Boundary<V>, Option<&T>)>;

    fn vertex_position(&self, vertex: &V) -> S::Coordinate;

    fn tile_position(&self, tile: &T) -> S::Coordinate;

    // Return all external boundaries that are adjacent to the given set of tiles.
    fn adjacent_any(&self, tiles: &[&T]) -> Vec<(Boundary<V>, Option<&T>)> {
        let mut result = HashSet::new();
        // Collect all neighbors of tiles in the given set.
        for node in tiles {
            let adjacent = self.adjacent(node);
            result.extend(adjacent);
        }
        // Remove all boundaries that contain nodes from the given set.
        result
            .into_iter()
            .filter(|(_boundary, node)| match node {
                Some(node) => !tiles.contains(node),
                None => true,
            })
            .collect()
    }
}