polyhedra 0.1.0

Polyhedra is a small library for creating polyhedra.
Documentation
use core::fmt::Debug;
use nalgebra as na;
use petgraph;

use petgraph::graph::NodeIndex;
use petgraph::stable_graph::StableGraph;

pub(crate) type Point = na::Point3<f32>;
/// Graph representation of a `Polyhedron`
pub type VertexGraph = StableGraph<Point, (), petgraph::Undirected>;

/// Handle to a vertex in a polyhedron.
/// Must only be used with the polyhedron it was received from.
#[derive(PartialEq, Eq, Copy, Clone, Debug, PartialOrd, Hash)]
pub struct VertexHandle {
    pub(crate) ix: NodeIndex,
}

impl VertexHandle {
    pub(crate) fn new(ix: NodeIndex) -> Self {
        Self { ix }
    }
}

pub(crate) struct WeightedValue<T> {
    pub value: T,
    pub weight: f32,
}

// The weights represent relative weights and will be scaled by the overall sum of weights.
// points and weights need to be of the same length.
pub(crate) fn weighted_centroid(weighted_points: &[WeightedValue<&Point>]) -> Point {
    let (mut x, mut y, mut z) = (0.0_f32, 0.0_f32, 0.0_f32);
    let mut w_sum = 0.0;
    for wp in weighted_points.iter() {
        let weight = wp.weight;
        let p = wp.value;
        w_sum += weight;
        x += p.x * weight;
        y += p.y * weight;
        z += p.z * weight;
    }
    x /= w_sum;
    y /= w_sum;
    z /= w_sum;

    Point::new(x, y, z)
}

/// Represents the face of a polyhedron.
/// Faces can be arbitrary polygons.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Face {
    pub(crate) nodes: Vec<VertexHandle>,
}

impl Face {
    /// Create a new `Face` from the given `VertexHandle`s.
    pub fn new(nodes: &[VertexHandle]) -> Face {
        Face {
            nodes: Vec::from(nodes),
        }
    }

    /// Create a new face form the given `NodeIndex` structs.
    /// For internal use when working with the graph component of a `Polyhedron` directly.
    pub(crate) fn from_node_index(nodes: &[NodeIndex]) -> Face {
        Face {
            nodes: nodes.iter().map(|n_ix| VertexHandle::new(*n_ix)).collect(),
        }
    }

    /// Create a new face form three `VertexHandle`s.
    pub(crate) fn new_triangle(nodes: &[VertexHandle; 3]) -> Face {
        Face {
            nodes: vec![nodes[0], nodes[1], nodes[2]],
        }
    }

    /// Returns a slice to the `VertexHandle`s that make up this face.
    pub fn nodes(&self) -> &[VertexHandle] {
        &self.nodes
    }

    /// Return the edges that bound this polygon.
    pub fn edges(&self) -> Vec<(VertexHandle, VertexHandle)> {
        let mut edges = Vec::new();
        let node_count = self.nodes.len();
        for i in 0..node_count {
            let node_a = self.nodes[i % node_count];
            let node_b = self.nodes[(i + 1) % node_count];
            edges.push((node_a, node_b));
        }

        edges
    }

    /// Compute the center of the `Face` in its polygon's graph.
    pub(crate) fn center(&self, graph: &VertexGraph) -> Point {
        let sum: Point = self
            .nodes
            .iter()
            .map(|node| graph.node_weight(node.ix).expect("Illegal node access"))
            .fold(Point::new(0., 0., 0.), |acc, p| {
                Point::from(acc.coords + p.coords)
            });
        sum / (self.nodes.len() as f32)
    }
}