draco_oxide_core/codec/attribute/
sequence.rs1use crate::corner_table::GenericCornerTable;
2use crate::types::{CornerIdx, VertexIdx};
3
4#[derive(Debug, Clone)]
5pub struct Traverser<'ct, CornerTableType>
6where
7 CornerTableType: GenericCornerTable,
8{
9 corner_table: &'ct CornerTableType,
10 visited_vertices: Vec<bool>,
11 visited_faces: Vec<bool>,
12 corner_traversal_stack: Vec<CornerIdx>,
13 out: Vec<CornerIdx>,
14}
15
16impl<'ct, T> Traverser<'ct, T>
17where
18 T: GenericCornerTable,
19{
20 pub fn new(corner_table: &'ct T, corners_of_edgebreaker_traversal: Vec<CornerIdx>) -> Self {
26 Self {
27 visited_vertices: vec![false; corner_table.num_vertices()],
28 visited_faces: vec![false; corner_table.num_faces()],
29 corner_table,
30 corner_traversal_stack: corners_of_edgebreaker_traversal, out: Vec::with_capacity(corner_table.num_corners()),
32 }
33 }
34
35 pub fn is_vertex_visited(&self, v: VertexIdx) -> bool {
36 self.visited_vertices[usize::from(v)]
37 }
38
39 pub fn visit(&mut self, v: VertexIdx, c: CornerIdx) {
40 if !self.visited_vertices[usize::from(v)] {
41 self.out.push(c);
42 }
43 self.visited_vertices[usize::from(v)] = true;
44 }
45
46 pub fn compute_seqeunce(mut self) -> Vec<CornerIdx> {
47 while let Some(curr_corner) = self.corner_traversal_stack.pop() {
48 let v = self.corner_table.vertex_idx(curr_corner);
52 if self.visited_faces[usize::from(self.corner_table.face_idx_containing(curr_corner))] {
53 continue;
54 }
55 let next_c = self.corner_table.next(curr_corner);
56 let next_v = self.corner_table.vertex_idx(next_c);
57 let prev_c = self.corner_table.previous(curr_corner);
58 let prev_v = self.corner_table.vertex_idx(prev_c);
59 if !self.is_vertex_visited(next_v) || !self.is_vertex_visited(prev_v) {
60 self.visit(next_v, next_c);
63 self.visit(prev_v, prev_c);
64 self.corner_traversal_stack.push(curr_corner);
65 continue;
66 }
67
68 let face_idx = self.corner_table.face_idx_containing(curr_corner);
70 self.visited_faces[usize::from(face_idx)] = true;
71 if !self.is_vertex_visited(v) {
78 self.visit(v, curr_corner);
79 if !self.corner_table.is_on_boundary(v) {
80 self.corner_traversal_stack.push(
81 self.corner_table.get_right_corner(curr_corner).unwrap(), );
83 continue;
84 }
85 }
86
87 self.visit(v, curr_corner);
88
89 let right_corner = self.corner_table.get_right_corner(curr_corner);
90 let left_corner = self.corner_table.get_left_corner(curr_corner);
91 let right_face = right_corner.map(|c| self.corner_table.face_idx_containing(c));
92 let left_face = left_corner.map(|c| self.corner_table.face_idx_containing(c));
93
94 if right_face.is_some() && self.visited_faces[usize::from(right_face.unwrap())] {
95 if left_face.is_some() && self.visited_faces[usize::from(left_face.unwrap())] {
97 } else {
99 if let Some(lc) = left_corner {
102 self.corner_traversal_stack.push(lc);
103 }
104 }
105 } else {
106 if left_face.is_some() && self.visited_faces[usize::from(left_face.unwrap())] {
108 if let Some(rc) = right_corner {
111 self.corner_traversal_stack.push(rc);
112 }
113 } else {
114 if let Some(lc) = left_corner {
118 self.corner_traversal_stack.push(lc);
119 }
120 if let Some(rc) = right_corner {
121 self.corner_traversal_stack.push(rc);
122 }
123 }
124 }
125 }
126 self.out
127 }
128}