use core::fmt::Debug;
use petgraph;
use petgraph::graph::EdgeIndex;
use crate::geometry::*;
use crate::topology::{Boundary, Tiling};
#[derive(Debug)]
pub struct Polyhedron {
pub(crate) graph: VertexGraph,
pub(crate) faces: Vec<Face>,
}
impl Polyhedron {
pub fn faces(&self) -> impl IntoIterator<Item = &Face> {
&self.faces
}
pub fn vertices<'a>(&'a self) -> impl IntoIterator<Item = VertexHandle> + 'a {
self.graph.node_indices().map(VertexHandle::new)
}
pub fn adjacent_faces(&self, face: &Face) -> Vec<&Face> {
let mut faces = Vec::new();
for (node_a, node_b) in face.edges() {
let edge = self.graph.find_edge(node_a.ix, node_b.ix);
let edge = edge.expect("Illegal edge access");
let (face_a, face_b) = self.edge_adjacent_faces(edge);
if face_a == face {
faces.push(face_b);
} else {
faces.push(face_a);
}
}
faces
}
pub(crate) fn edge_adjacent_faces(&self, edge: EdgeIndex) -> (&Face, &Face) {
let (node_a, node_b) = self
.graph
.edge_endpoints(edge)
.expect("Illegal edge access");
let mut faces = self
.faces
.iter()
.filter(|face| {
face.nodes.contains(&VertexHandle::new(node_a))
&& face.nodes.contains(&VertexHandle::new(node_b))
})
.collect::<Vec<&Face>>();
match faces.len() {
2 => (
faces.pop().expect("Illegal Face removal"),
faces.pop().expect("Illegal Face removal"),
),
_ => panic!("Illegal number of faces {}", faces.len()),
}
}
pub(crate) fn assert_consistency(&self) -> Result<(), String> {
for face in self.faces() {
for (v1, v2) in face.edges() {
if self.graph.find_edge_undirected(v1.ix, v2.ix).is_none() {
return Err(format!(
"Found invalid edge present in face, \
but not in graph: ({:?}, {:?}) in in polyhedron {:?}",
v1, v2, self
));
}
}
}
Ok(())
}
}
impl Into<VertexGraph> for Polyhedron {
fn into(self) -> VertexGraph {
self.graph
}
}
impl Tiling<Face, VertexHandle, Point> for Polyhedron {
fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = &Face> + 'a> {
Box::new(self.faces.iter())
}
fn adjacent(&self, node: &Face) -> Vec<(Boundary<VertexHandle>, Option<&Face>)> {
node.edges()
.into_iter()
.map(|(node_a, node_b)| {
let edge = self.graph.find_edge_undirected(node_a.ix, node_b.ix);
let face_r = {
match edge {
Some((edge, _dir)) => {
let (face_a, face_b) = self.edge_adjacent_faces(edge);
let face = if node == face_a { face_b } else { face_a };
Some(face)
}
None => None,
}
};
debug_assert_ne!(
edge, None,
"Found invalid edge ({:?},{:?}) in polyhedron {:?} ",
node_a, node_b, self
);
debug_assert_ne!(face_r, None, "Found invalid face in polyhedron");
let boundary = Boundary(node_a, node_b);
(boundary, face_r)
})
.collect()
}
fn vertex_position(&self, vertex: &VertexHandle) -> Point {
*(self.graph.node_weight(vertex.ix).unwrap())
}
fn tile_position(&self, tile: &Face) -> Point {
tile.center(&self.graph)
}
}