1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
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)
    }
}