use num::Float;
use std::marker::PhantomData;
use std::ops::{Add, Deref, DerefMut, Mul, Sub};
use graph::geometry::{AsPosition, Cross, Geometry, Normalize};
use graph::mesh::{Face, Mesh};
use graph::storage::{EdgeKey, FaceKey, VertexKey};
use graph::topology::EdgeView;
#[derive(Clone, Copy)]
pub struct FaceView<M, G>
where
M: AsRef<Mesh<G>>,
G: Geometry,
{
mesh: M,
pub key: FaceKey,
phantom: PhantomData<G>,
}
impl<M, G> FaceView<M, G>
where
M: AsRef<Mesh<G>>,
G: Geometry,
{
pub(crate) fn new(mesh: M, face: FaceKey) -> Self {
FaceView {
mesh: mesh,
key: face,
phantom: PhantomData,
}
}
pub fn edges(&self) -> EdgeCirculator<&Mesh<G>, G> {
EdgeCirculator::new(self.with_mesh_ref())
}
pub fn faces(&self) -> FaceCirculator<&Mesh<G>, G> {
FaceCirculator::new(self.with_mesh_ref())
}
fn with_mesh_ref(&self) -> FaceView<&Mesh<G>, G> {
FaceView::new(self.mesh.as_ref(), self.key)
}
}
impl<M, G> FaceView<M, G>
where
M: AsRef<Mesh<G>> + AsMut<Mesh<G>>,
G: Geometry,
{
pub fn faces_mut(&mut self) -> FaceCirculator<&mut Mesh<G>, G> {
FaceCirculator::new(self.with_mesh_mut())
}
fn with_mesh_mut(&mut self) -> FaceView<&mut Mesh<G>, G> {
FaceView::new(self.mesh.as_mut(), self.key)
}
}
#[cfg_attr(rustfmt, rustfmt_skip)]
impl<M, G> FaceView<M, G>
where
M: AsRef<Mesh<G>> + AsMut<Mesh<G>>,
G: Geometry,
G::Vertex: AsPosition + Clone,
G::Edge: Clone,
G::Face: Clone,
<G::Vertex as AsPosition>::Target: Clone + Sub,
<<G::Vertex as AsPosition>::Target as Sub>::Output: Cross,
<<<G::Vertex as AsPosition>::Target as Sub>::Output as Cross>::Output: Normalize,
{
pub fn extrude<F>(self, distance: F) -> Result<Self, ()>
where
F: Float,
<G::Vertex as AsPosition>::Target: Add<<<<<G::Vertex as AsPosition>::Target as Sub>::Output as Cross>::Output as Mul<F>>::Output, Output = <G::Vertex as AsPosition>::Target>,
<<<G::Vertex as AsPosition>::Target as Sub>::Output as Cross>::Output: Mul<F>,
<<<<G::Vertex as AsPosition>::Target as Sub>::Output as Cross>::Output as Mul<F>>::Output: Clone,
{
self.extrude_with_geometry(distance, G::Edge::default(), G::Face::default())
}
pub fn extrude_with_geometry<F>(
self,
distance: F,
edge: G::Edge,
face: G::Face,
) -> Result<Self, ()>
where
F: Float,
<G::Vertex as AsPosition>::Target: Add<<<<<G::Vertex as AsPosition>::Target as Sub>::Output as Cross>::Output as Mul<F>>::Output, Output = <G::Vertex as AsPosition>::Target>,
<<<G::Vertex as AsPosition>::Target as Sub>::Output as Cross>::Output: Mul<F>,
<<<<G::Vertex as AsPosition>::Target as Sub>::Output as Cross>::Output as Mul<F>>::Output: Clone,
{
let geometry = self.extrude_vertex_geometry(distance)?;
let FaceView { mut mesh, key, .. } = self;
mesh.as_mut().remove_face(key).unwrap();
let extrusion = {
let mesh = mesh.as_mut();
let vertices = geometry.into_iter()
.map(|vertex| (vertex.0, mesh.insert_vertex(vertex.1))).collect::<Vec<_>>();
let edges = vertices.iter().enumerate().map(|(index, &(_, a))| {
let b = vertices[(index + 1) % vertices.len()].1;
mesh.insert_edge((a, b), edge.clone()).unwrap()
}).collect::<Vec<_>>();
let extrusion = mesh.insert_face(&edges, face.clone()).unwrap();
for index in 0..vertices.len() {
let (d, c) = vertices[index];
let (a, b) = vertices[(index + 1) % vertices.len()];
let ab = mesh.insert_edge((a, b), edge.clone()).unwrap();
let bc = mesh.insert_edge((b, c), edge.clone()).unwrap();
let cd = mesh.insert_edge((c, d), edge.clone()).unwrap();
let da = mesh.insert_edge((d, a), edge.clone()).unwrap();
let ca = mesh.insert_edge((c, a), edge.clone()).unwrap(); let ac = mesh.insert_edge((a, c), edge.clone()).unwrap(); mesh.insert_face(&[ab, bc, ca], face.clone()).unwrap();
mesh.insert_face(&[ac, cd, da], face.clone()).unwrap();
}
extrusion
};
Ok(FaceView::new(mesh, extrusion))
}
fn extrude_vertex_geometry<F>(&self, distance: F) -> Result<Vec<(VertexKey, G::Vertex)>, ()>
where
F: Float,
<G::Vertex as AsPosition>::Target: Add<<<<<G::Vertex as AsPosition>::Target as Sub>::Output as Cross>::Output as Mul<F>>::Output, Output = <G::Vertex as AsPosition>::Target>,
<<<G::Vertex as AsPosition>::Target as Sub>::Output as Cross>::Output: Mul<F>,
<<<<G::Vertex as AsPosition>::Target as Sub>::Output as Cross>::Output as Mul<F>>::Output: Clone,
{
let mesh = self.mesh.as_ref();
let edges = self.edges().collect::<Vec<_>>();
if edges.len() < 3 {
return Err(());
}
let (a, b, c) = (
mesh.vertices.get(&edges[0].vertex).unwrap(),
mesh.vertices.get(&edges[1].vertex).unwrap(),
mesh.vertices.get(&edges[2].vertex).unwrap(),
);
let ab = a.geometry.as_position().clone() - b.geometry.as_position().clone();
let bc = b.geometry.as_position().clone() - c.geometry.as_position().clone();
let translation = ab.cross(bc).normalize() * distance;
Ok(edges.into_iter().map(|edge| {
let mut geometry = mesh.vertices.get(&edge.vertex).unwrap().geometry.clone();
*geometry.as_position_mut() = geometry.as_position().clone() + translation.clone();
(edge.vertex, geometry)
}).collect())
}
}
impl<M, G> AsRef<FaceView<M, G>> for FaceView<M, G>
where
M: AsRef<Mesh<G>>,
G: Geometry,
{
fn as_ref(&self) -> &FaceView<M, G> {
self
}
}
impl<M, G> AsMut<FaceView<M, G>> for FaceView<M, G>
where
M: AsRef<Mesh<G>> + AsMut<Mesh<G>>,
G: Geometry,
{
fn as_mut(&mut self) -> &mut FaceView<M, G> {
self
}
}
impl<M, G> Deref for FaceView<M, G>
where
M: AsRef<Mesh<G>>,
G: Geometry,
{
type Target = Face<G>;
fn deref(&self) -> &Self::Target {
self.mesh.as_ref().faces.get(&self.key).unwrap()
}
}
impl<M, G> DerefMut for FaceView<M, G>
where
M: AsRef<Mesh<G>> + AsMut<Mesh<G>>,
G: Geometry,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.mesh.as_mut().faces.get_mut(&self.key).unwrap()
}
}
pub struct OrphanFaceView<'a, G>
where
G: 'a + Geometry,
{
pub key: FaceKey,
pub geometry: &'a mut G::Face,
}
impl<'a, G> OrphanFaceView<'a, G>
where
G: 'a + Geometry,
{
pub(crate) fn new(geometry: &'a mut G::Face, face: FaceKey) -> Self {
OrphanFaceView {
key: face,
geometry: geometry,
}
}
}
pub struct EdgeCirculator<M, G>
where
M: AsRef<Mesh<G>>,
G: Geometry,
{
face: FaceView<M, G>,
edge: Option<EdgeKey>,
breadcrumb: Option<EdgeKey>,
}
impl<M, G> EdgeCirculator<M, G>
where
M: AsRef<Mesh<G>>,
G: Geometry,
{
fn new(face: FaceView<M, G>) -> Self {
let edge = face.edge;
EdgeCirculator {
face: face,
edge: Some(edge),
breadcrumb: Some(edge),
}
}
fn next(&mut self) -> Option<EdgeKey> {
self.edge.and_then(|edge| {
let next = self.face.mesh.as_ref().edges.get(&edge).unwrap().next;
self.breadcrumb.map(|_| {
if self.breadcrumb == next {
self.breadcrumb = None;
}
else {
self.edge = next;
}
edge
})
})
}
}
impl<'a, G> Iterator for EdgeCirculator<&'a Mesh<G>, G>
where
G: Geometry,
{
type Item = EdgeView<&'a Mesh<G>, G>;
fn next(&mut self) -> Option<Self::Item> {
<EdgeCirculator<_, _>>::next(self).map(|edge| EdgeView::new(self.face.mesh, edge))
}
}
pub struct FaceCirculator<M, G>
where
M: AsRef<Mesh<G>>,
G: Geometry,
{
face: FaceView<M, G>,
edge: Option<EdgeKey>,
breadcrumb: Option<EdgeKey>,
}
impl<M, G> FaceCirculator<M, G>
where
M: AsRef<Mesh<G>>,
G: Geometry,
{
fn new(face: FaceView<M, G>) -> Self {
let edge = face.edge;
FaceCirculator {
face: face,
edge: Some(edge),
breadcrumb: Some(edge),
}
}
fn next(&mut self) -> Option<FaceKey> {
let mesh = self.face.mesh.as_ref();
while let Some(edge) = self.edge.map(|edge| mesh.edges.get(&edge).unwrap()) {
self.edge = edge.next;
if let Some(face) = edge.opposite
.map(|opposite| mesh.edges.get(&opposite).unwrap())
.and_then(|opposite| opposite.face)
{
return if let Some(_) = self.breadcrumb {
if self.breadcrumb == edge.next {
self.breadcrumb = None;
}
Some(face)
}
else {
None
};
}
else {
continue;
}
}
None
}
}
impl<'a, G> Iterator for FaceCirculator<&'a Mesh<G>, G>
where
G: Geometry,
{
type Item = FaceView<&'a Mesh<G>, G>;
fn next(&mut self) -> Option<Self::Item> {
<FaceCirculator<_, _>>::next(self).map(|face| FaceView::new(self.face.mesh, face))
}
}
impl<'a, G> Iterator for FaceCirculator<&'a mut Mesh<G>, G>
where
G: 'a + Geometry,
{
type Item = OrphanFaceView<'a, G>;
fn next(&mut self) -> Option<Self::Item> {
<FaceCirculator<_, _>>::next(self).map(|face| {
let geometry = {
unsafe {
use std::mem;
let face = mem::transmute::<_, &'a mut Face<G>>(
self.face.mesh.faces.get_mut(&face).unwrap(),
);
&mut face.geometry
}
};
OrphanFaceView::new(geometry, face)
})
}
}
#[cfg(test)]
mod tests {
use r32;
use generate::*;
use graph::*;
#[test]
fn circulate_over_edges() {
let mesh = sphere::UVSphere::<f32>::with_unit_radius(3, 2)
.polygons_with_position() .map_vertices(|vertex| vertex.into_hash())
.triangulate()
.collect::<Mesh<(r32, r32, r32)>>();
let face = mesh.face(FaceKey::default()).unwrap();
assert_eq!(3, face.edges().count());
}
#[test]
fn circulate_over_faces() {
let mesh = sphere::UVSphere::<f32>::with_unit_radius(3, 2)
.polygons_with_position() .map_vertices(|vertex| vertex.into_hash())
.triangulate()
.collect::<Mesh<(r32, r32, r32)>>();
let face = mesh.face(FaceKey::default()).unwrap();
assert_eq!(3, face.faces().count());
}
#[test]
fn extrude_face() {
use nalgebra::Point3;
let mut mesh: Mesh<Point3<f32>> = sphere::UVSphere::<f32>::with_unit_radius(3, 2)
.polygons_with_position() .map_vertices(|vertex| vertex.into_hash())
.triangulate()
.collect::<Mesh<(r32, r32, r32)>>()
.into_geometry();
{
let face = mesh.face_mut(FaceKey::default()).unwrap();
let face = face.extrude(1.0).unwrap();
assert_eq!(3, face.faces().count());
}
assert_eq!(8, mesh.vertex_count());
assert_eq!(36, mesh.edge_count());
assert_eq!(12, mesh.face_count());
}
}