use crate::mesh::connectivity_info::ConnectivityInfo;
use crate::mesh::*;
pub type VertexIter = Box<dyn Iterator<Item = VertexID>>;
pub type HalfEdgeIter = Box<dyn Iterator<Item = HalfEdgeID>>;
pub type FaceIter = Box<dyn Iterator<Item = FaceID>>;
pub struct VertexHalfedgeIter<'a> {
walker: Walker<'a>,
start: Option<HalfEdgeID>,
is_done: bool,
}
impl<'a> VertexHalfedgeIter<'a> {
fn new(vertex_id: VertexID, connectivity_info: &'a ConnectivityInfo) -> VertexHalfedgeIter<'a> {
let walker = Walker::new(connectivity_info).into_vertex_halfedge_walker(vertex_id);
let start = walker.halfedge_id();
VertexHalfedgeIter {
walker,
start,
is_done: start.is_none(),
}
}
}
impl<'a> Iterator for VertexHalfedgeIter<'a> {
type Item = HalfEdgeID;
fn next(&mut self) -> Option<HalfEdgeID> {
if self.is_done {
return None;
}
let curr = self.walker.halfedge_id().unwrap();
match self.walker.face_id() {
Some(_) => {
self.walker.as_previous().as_twin();
}
None => {
self.walker.as_twin();
while let Some(_) = self.walker.face_id() {
self.walker.as_next().as_twin();
}
self.walker.as_twin();
}
}
self.is_done = self
.start
.map(|start| self.walker.halfedge_id().unwrap() == start)
.unwrap_or(true);
Some(curr)
}
}
pub struct FaceHalfedgeIter<'a> {
walker: Walker<'a>,
count: usize,
}
impl<'a> FaceHalfedgeIter<'a> {
fn new(face_id: FaceID, connectivity_info: &'a ConnectivityInfo) -> FaceHalfedgeIter<'a> {
FaceHalfedgeIter {
walker: Walker::new(connectivity_info).into_face_halfedge_walker(face_id),
count: 0,
}
}
}
impl<'a> Iterator for FaceHalfedgeIter<'a> {
type Item = HalfEdgeID;
fn next(&mut self) -> Option<HalfEdgeID> {
if self.count == 3 {
return None;
}
self.walker.as_next();
self.count += 1;
Some(self.walker.halfedge_id().unwrap())
}
}
pub struct EdgeIter<'a> {
walker: Walker<'a>,
iter: HalfEdgeIter,
}
impl<'a> EdgeIter<'a> {
fn new(connectivity_info: &'a ConnectivityInfo) -> EdgeIter<'a> {
EdgeIter {
walker: Walker::new(connectivity_info),
iter: connectivity_info.halfedge_iterator(),
}
}
}
impl<'a> Iterator for EdgeIter<'a> {
type Item = HalfEdgeID;
fn next(&mut self) -> Option<HalfEdgeID> {
if let Some(next_id) = self.iter.next() {
if self.walker.as_halfedge_walker(next_id).twin_id().unwrap() < next_id {
self.next()
} else {
Some(next_id)
}
} else {
None
}
}
}
impl Mesh {
pub fn vertex_iter(&self) -> VertexIter {
self.connectivity_info.vertex_iterator()
}
pub fn halfedge_iter(&self) -> HalfEdgeIter {
self.connectivity_info.halfedge_iterator()
}
pub fn edge_iter(&self) -> EdgeIter {
EdgeIter::new(&self.connectivity_info)
}
pub fn face_iter(&self) -> FaceIter {
self.connectivity_info.face_iterator()
}
pub fn vertex_halfedge_iter(&self, vertex_id: VertexID) -> VertexHalfedgeIter {
VertexHalfedgeIter::new(vertex_id, &self.connectivity_info)
}
pub fn face_halfedge_iter(&self, face_id: FaceID) -> FaceHalfedgeIter {
FaceHalfedgeIter::new(face_id, &self.connectivity_info)
}
}
#[cfg(test)]
mod tests {
use super::*;
use three_d_asset::{Indices, Positions, TriMesh};
#[test]
fn test_vertex_iterator() {
let mesh = crate::test_utility::subdivided_triangle();
let mut i = 0;
for _ in mesh.vertex_iter() {
i = i + 1;
}
assert_eq!(4, i);
let vec: Vec<VertexID> = mesh.vertex_iter().collect();
i = 0;
for vertex_id in mesh.vertex_iter() {
assert_eq!(vertex_id, vec[i]);
i = i + 1;
}
}
#[test]
fn test_halfedge_iterator() {
let mesh = crate::test_utility::subdivided_triangle();
let mut i = 0;
for _ in mesh.halfedge_iter() {
i = i + 1;
}
assert_eq!(12, i);
let vec: Vec<HalfEdgeID> = mesh.halfedge_iter().collect();
i = 0;
for halfedge_id in mesh.halfedge_iter() {
assert_eq!(halfedge_id, vec[i]);
i = i + 1;
}
}
#[test]
fn test_edge_iterator() {
let mesh = crate::test_utility::subdivided_triangle();
let mut i = 0;
for _ in mesh.edge_iter() {
i = i + 1;
}
assert_eq!(6, i);
let vec: Vec<HalfEdgeID> = mesh.edge_iter().collect();
i = 0;
for halfedge_id in mesh.edge_iter() {
assert_eq!(halfedge_id, vec[i]);
i = i + 1;
}
for halfedge_id in mesh.edge_iter() {
let twin_id = mesh.walker_from_halfedge(halfedge_id).twin_id().unwrap();
assert!(halfedge_id < twin_id);
assert!(vec.iter().find(|edge_id| *edge_id == &twin_id).is_none());
}
}
#[test]
fn test_face_iterator() {
let mesh = crate::test_utility::subdivided_triangle();
let mut i = 0;
for _ in mesh.face_iter() {
i = i + 1;
}
assert_eq!(3, i);
let vec: Vec<FaceID> = mesh.face_iter().collect();
i = 0;
for face_id in mesh.face_iter() {
assert_eq!(face_id, vec[i]);
i = i + 1;
}
}
#[test]
fn test_vertex_halfedge_iterator() {
let mesh = crate::test_utility::subdivided_triangle();
let mut i = 0;
let vertex_id = mesh.vertex_iter().last().unwrap();
for halfedge_id in mesh.vertex_halfedge_iter(vertex_id) {
assert!(mesh.walker_from_halfedge(halfedge_id).vertex_id().is_some());
i = i + 1;
}
assert_eq!(i, 3, "All edges of a one-ring are not visited");
}
#[test]
fn test_vertex_halfedge_iterator_with_holes() {
let mesh: Mesh = TriMesh {
indices: Indices::U8(vec![0, 2, 3, 0, 4, 1, 0, 1, 2]),
positions: Positions::F64(vec![vec3(0.0, 0.0, 0.0); 5]),
..Default::default()
}
.into();
let mut i = 0;
for halfedge_id in mesh.vertex_halfedge_iter(unsafe { VertexID::new(0) }) {
assert!(mesh.walker_from_halfedge(halfedge_id).vertex_id().is_some());
i = i + 1;
}
assert_eq!(i, 4, "All edges of a one-ring are not visited");
}
#[test]
fn test_face_halfedge_iterator() {
let mesh = crate::test_utility::triangle();
let mut i = 0;
for halfedge_id in mesh.face_halfedge_iter(unsafe { FaceID::new(0) }) {
let walker = mesh.walker_from_halfedge(halfedge_id);
assert!(walker.halfedge_id().is_some());
assert!(walker.face_id().is_some());
i = i + 1;
}
assert_eq!(i, 3, "All edges of a face are not visited");
}
}