use crate::mesh::connectivity_info::{ConnectivityInfo, HalfEdge};
use crate::mesh::*;
impl Mesh {
pub(super) fn walker(&self) -> Walker {
Walker::new(&self.connectivity_info)
}
pub fn walker_from_vertex(&self, vertex_id: VertexID) -> Walker {
self.walker().into_vertex_halfedge_walker(vertex_id)
}
pub fn walker_from_halfedge(&self, halfedge_id: HalfEdgeID) -> Walker {
self.walker().into_halfedge_walker(halfedge_id)
}
pub fn walker_from_face(&self, face_id: FaceID) -> Walker {
self.walker().into_face_halfedge_walker(face_id)
}
}
#[derive(Clone, Debug)]
pub struct Walker<'a> {
connectivity_info: &'a ConnectivityInfo,
current: Option<HalfEdgeID>,
current_info: Option<HalfEdge>,
}
impl<'a> Walker<'a> {
pub(super) fn new(connectivity_info: &'a ConnectivityInfo) -> Self {
Walker {
current: None,
current_info: None,
connectivity_info: connectivity_info,
}
}
pub(super) fn into_vertex_halfedge_walker(mut self, vertex_id: VertexID) -> Self {
self.as_vertex_halfedge_walker(vertex_id);
self
}
pub(super) fn into_halfedge_walker(mut self, halfedge_id: HalfEdgeID) -> Self {
self.as_halfedge_walker(halfedge_id);
self
}
pub(super) fn into_face_halfedge_walker(mut self, face_id: FaceID) -> Self {
self.as_face_halfedge_walker(face_id);
self
}
pub(super) fn as_vertex_halfedge_walker(&mut self, vertex_id: VertexID) -> &mut Self {
let halfedge_id = self.connectivity_info.vertex_halfedge(vertex_id);
self.set_current(halfedge_id);
self
}
pub(super) fn as_halfedge_walker(&mut self, halfedge_id: HalfEdgeID) -> &mut Self {
let halfedge_id = Some(halfedge_id);
self.set_current(halfedge_id);
self
}
pub(super) fn as_face_halfedge_walker(&mut self, face_id: FaceID) -> &mut Self {
let halfedge_id = self.connectivity_info.face_halfedge(face_id);
self.set_current(halfedge_id);
self
}
pub fn into_next(mut self) -> Self {
self.as_next();
self
}
pub fn into_previous(mut self) -> Self {
self.as_next().as_next();
self
}
pub fn into_twin(mut self) -> Self {
self.as_twin();
self
}
pub fn as_next(&mut self) -> &mut Self {
let halfedge_id = match self.current_info {
Some(ref current_info) => current_info.next,
None => None,
};
self.set_current(halfedge_id);
self
}
pub fn as_previous(&mut self) -> &mut Self {
self.as_next().as_next()
}
pub fn as_twin(&mut self) -> &mut Self {
let halfedge_id = match self.current_info {
Some(ref current_info) => current_info.twin,
None => None,
};
self.set_current(halfedge_id);
self
}
pub fn vertex_id(&self) -> Option<VertexID> {
if let Some(ref halfedge) = self.current_info {
halfedge.vertex
} else {
None
}
}
pub fn next_id(&self) -> Option<HalfEdgeID> {
if let Some(ref halfedge) = self.current_info {
halfedge.next
} else {
None
}
}
pub fn previous_id(&self) -> Option<HalfEdgeID> {
if let Some(next_id) = self.next_id() {
Walker::new(&self.connectivity_info)
.into_halfedge_walker(next_id)
.next_id()
} else {
None
}
}
pub fn twin_id(&self) -> Option<HalfEdgeID> {
if let Some(ref halfedge) = self.current_info {
halfedge.twin
} else {
None
}
}
pub fn halfedge_id(&self) -> Option<HalfEdgeID> {
self.current
}
pub fn face_id(&self) -> Option<FaceID> {
if let Some(ref halfedge) = self.current_info {
halfedge.face
} else {
None
}
}
fn set_current(&mut self, halfedge_id: Option<HalfEdgeID>) {
self.current_info = if let Some(id) = halfedge_id {
self.connectivity_info.halfedge(id)
} else {
None
};
self.current = halfedge_id;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_one_face_connectivity() {
let mesh: Mesh = crate::test_utility::triangle();
let f1 = mesh.face_iter().next().unwrap();
let v1 = mesh.walker_from_face(f1).vertex_id().unwrap();
let v2 = mesh.walker_from_face(f1).as_next().vertex_id().unwrap();
let v3 = mesh.walker_from_face(f1).as_previous().vertex_id().unwrap();
let t1 = mesh.walker_from_vertex(v1).vertex_id();
assert_eq!(t1, Some(v2));
let t2 = mesh.walker_from_vertex(v1).as_twin().vertex_id();
assert_eq!(t2, Some(v1));
let t3 = mesh.walker_from_vertex(v2).as_next().as_next().vertex_id();
assert_eq!(t3, Some(v2));
let t4 = mesh.walker_from_face(f1).as_twin().face_id();
assert!(t4.is_none());
let t5 = mesh.walker_from_face(f1).as_twin().next_id();
assert!(t5.is_none());
let t6 = mesh
.walker_from_face(f1)
.as_previous()
.as_previous()
.as_twin()
.as_twin()
.face_id();
assert_eq!(t6, Some(f1));
let t7 = mesh.walker_from_vertex(v2).as_next().as_next().next_id();
assert_eq!(t7, mesh.walker_from_vertex(v2).halfedge_id());
let t8 = mesh.walker_from_vertex(v3).face_id();
assert_eq!(t8, Some(f1));
mesh.is_valid().unwrap();
}
#[test]
fn test_three_face_connectivity() {
let mesh = crate::test_utility::subdivided_triangle();
let mut id = None;
for vertex_id in mesh.vertex_iter() {
let mut round = true;
for halfedge_id in mesh.vertex_halfedge_iter(vertex_id) {
if mesh.walker_from_halfedge(halfedge_id).face_id().is_none() {
round = false;
break;
}
}
if round {
id = Some(vertex_id);
break;
}
}
let mut walker = mesh.walker_from_vertex(id.unwrap());
let start_edge = walker.halfedge_id().unwrap();
let one_round_edge = walker
.as_previous()
.as_twin()
.as_previous()
.as_twin()
.as_previous()
.twin_id()
.unwrap();
assert_eq!(start_edge, one_round_edge);
}
}