1pub mod all_inclusive_corner_table;
2pub mod attribute_corner_table;
3
4use std::collections::BTreeMap;
5
6use crate::attribute::Attribute;
7use crate::types::{
8 AttributeValueIdx, CornerIdx, FaceIdx, PointIdx, VecCornerIdx, VecVertexIdx, VertexIdx,
9};
10
11pub trait GenericCornerTable {
12 fn face_idx_containing(&self, corner: CornerIdx) -> FaceIdx;
13 fn num_faces(&self) -> usize;
14 fn num_corners(&self) -> usize;
15 fn num_vertices(&self) -> usize;
16 fn point_idx(&self, corner: CornerIdx) -> PointIdx;
17 fn vertex_idx(&self, corner: CornerIdx) -> VertexIdx;
18 fn opposite(&self, corner: CornerIdx) -> Option<CornerIdx>;
19 fn previous(&self, corner: CornerIdx) -> CornerIdx;
20 fn next(&self, corner: CornerIdx) -> CornerIdx;
21 fn left_most_corner(&self, vertex: VertexIdx) -> CornerIdx;
22
23 fn swing_right(&self, corner: CornerIdx) -> Option<CornerIdx> {
24 if let Some(c) = self.opposite(self.previous(corner)) {
25 Some(self.previous(c))
26 } else {
27 None
28 }
29 }
30
31 fn swing_left(&self, corner: CornerIdx) -> Option<CornerIdx> {
32 if let Some(c) = self.opposite(self.next(corner)) {
33 Some(self.next(c))
34 } else {
35 None
36 }
37 }
38
39 fn is_on_boundary(&self, v: VertexIdx) -> bool {
40 self.swing_left(self.left_most_corner(v)).is_none()
41 }
42
43 fn get_left_corner(&self, corner: CornerIdx) -> Option<CornerIdx> {
44 self.opposite(self.previous(corner))
45 }
46
47 fn get_right_corner(&self, corner: CornerIdx) -> Option<CornerIdx> {
48 self.opposite(self.next(corner))
49 }
50
51 #[allow(unused)]
52 fn vertex_to_attribute_map(&self) -> Option<&VecVertexIdx<AttributeValueIdx>> {
53 None
54 }
55}
56
57#[derive(Debug, Clone)]
58pub struct CornerTable<'mesh> {
59 opposite_corners: VecCornerIdx<CornerIdx>,
62
63 mesh_faces: &'mesh [[PointIdx; 3]],
65
66 conn_faces: Vec<[VertexIdx; 3]>,
69
70 num_corners: usize,
72
73 num_vertices: usize,
75
76 left_most_corners: VecVertexIdx<CornerIdx>,
78
79 corner_to_vertex: BTreeMap<CornerIdx, VertexIdx>,
81
82 non_manifold_vertex_parents: Vec<VertexIdx>,
84}
85
86impl<'mesh> CornerTable<'mesh> {
87 pub fn new(mesh_faces: &'mesh [[PointIdx; 3]], pos_att: &Attribute) -> Self {
88 let conn_faces = mesh_faces
89 .iter()
90 .map(|f| {
91 [
92 usize::from(pos_att.get_unique_val_idx(f[0])).into(),
93 usize::from(pos_att.get_unique_val_idx(f[1])).into(),
94 usize::from(pos_att.get_unique_val_idx(f[2])).into(),
95 ]
96 })
97 .collect::<Vec<_>>();
98 let mut out = Self {
99 opposite_corners: VecCornerIdx::new(), num_corners: mesh_faces.len() * 3,
101 mesh_faces,
102 conn_faces,
103 num_vertices: 0, left_most_corners: VecVertexIdx::new(), corner_to_vertex: BTreeMap::new(), non_manifold_vertex_parents: Vec::new(), };
108
109 let unused_vertices = Self::get_unused_vertices(&out.conn_faces);
110 if !unused_vertices.is_empty() {
111 panic!(
112 "Mesh contains unused vertices: {:?}. This is not supported by the corner table.",
113 unused_vertices
114 );
115 }
116
117 out.compute_table();
118 if Self::contains_non_manifold_edges(&out.conn_faces) {
119 out.handle_no_manifold_edges();
120 }
121 out.compute_left_most_corners();
122
123 out
124 }
125
126 fn contains_non_manifold_edges(faces: &[[VertexIdx; 3]]) -> bool {
128 let mut edges = faces
129 .iter()
130 .flat_map(|f| {
131 let v0 = f[0];
132 let v1 = f[1];
133 let v2 = f[2];
134 vec![[v0, v1], [v1, v2], [v2, v0]]
135 })
136 .collect::<Vec<_>>();
137 for e in &mut edges {
138 e.sort();
139 }
140 edges.sort();
141 let mut count = 1;
143 for i in 1..edges.len() {
144 if edges[i] == edges[i - 1] {
145 count += 1;
146 if count > 2 {
147 return true; }
149 } else {
150 count = 1; }
152 }
153 false }
155
156 fn handle_no_manifold_edges(&mut self) {
159 let mut visited_corners = vec![false; self.num_corners()];
160 let mut sink_vertices: Vec<(VertexIdx, CornerIdx)> = Vec::new();
161 let mut connectivity_updated;
162 let default_opposite = CornerIdx::from(usize::MAX);
163 loop {
164 connectivity_updated = false;
165 for c in 0..self.num_corners() {
166 if visited_corners[c] {
167 continue;
168 }
169 let c = CornerIdx::from(c);
170 sink_vertices.clear();
171
172 let mut first_c = c;
174 let mut curr_c = c;
175 while let Some(next_c) = self.swing_left(curr_c) {
176 if next_c == first_c || visited_corners[usize::from(next_c)] {
177 break;
178 }
179 curr_c = next_c;
180 }
181
182 first_c = curr_c;
183
184 loop {
186 visited_corners[usize::from(curr_c)] = true;
187 let sink_c = self.next(curr_c);
188 let sink_v = self.corner_to_vert(sink_c);
189
190 let edge_c = self.previous(curr_c);
191 let mut vertex_connectivity_updated = false;
192
193 for &attached_sink_vertex in &sink_vertices {
194 if attached_sink_vertex.0 == sink_v {
195 let other_edge_c = attached_sink_vertex.1;
196 let opp_edge_c = self.opposite(edge_c);
197
198 if let Some(opp_edge_c) = opp_edge_c {
199 if opp_edge_c == other_edge_c {
200 continue;
201 }
202 }
203
204 let opp_other_edge_c = self.opposite(other_edge_c);
205 if let Some(opp_edge_c) = opp_edge_c {
206 self.opposite_corners[opp_edge_c] = default_opposite;
207 }
209 if let Some(opp_other_edge_c) = opp_other_edge_c {
210 self.opposite_corners[opp_other_edge_c] = default_opposite;
211 }
213
214 self.opposite_corners[edge_c] = default_opposite;
215 self.opposite_corners[other_edge_c] = default_opposite;
216
217 vertex_connectivity_updated = true;
218 break;
219 }
220 }
221 if vertex_connectivity_updated {
222 connectivity_updated = true;
223 break;
224 }
225 let new_sink_vert: (VertexIdx, CornerIdx) =
226 (self.corner_to_vert(self.previous(curr_c)), sink_c);
227 sink_vertices.push(new_sink_vert);
228
229 curr_c = if let Some(c) = self.swing_right(curr_c) {
230 c
231 } else {
232 break; };
234 if curr_c == first_c {
235 break; }
237 }
238 }
239 if !connectivity_updated {
240 break; }
242 }
243 }
244
245 fn get_unused_vertices(faces: &[[VertexIdx; 3]]) -> Vec<usize> {
246 let num_vertices = {
247 let num_vertices_minus_1 = *faces.iter().flatten().max().unwrap_or(&VertexIdx::from(0));
248 usize::from(num_vertices_minus_1) + 1
249 };
250 let mut used_vertices = vec![false; num_vertices];
251 for f in faces {
252 for &v in f {
253 used_vertices[usize::from(v)] = true;
254 }
255 }
256 used_vertices
257 .iter()
258 .enumerate()
259 .filter_map(|(idx, &used)| if !used { Some(idx) } else { None })
260 .collect()
261 }
262
263 fn compute_table(&mut self) {
264 let default_opposite = CornerIdx::from(usize::MAX);
265 let default_vertex = VertexIdx::from(usize::MAX);
266 self.opposite_corners
267 .resize(self.num_corners(), default_opposite);
268 let mut num_corners_on_vertices = VecVertexIdx::with_capacity(self.num_corners());
269
270 for c in 0..self.num_corners() {
273 let c = CornerIdx::from(c);
274 let v1 = self.vertex_idx(c);
275 if usize::from(v1) >= num_corners_on_vertices.len() {
276 num_corners_on_vertices.resize(usize::from(v1) + 1, 0);
277 }
278 num_corners_on_vertices[v1] += 1;
279 }
280
281 let mut vertex_edges: Vec<(VertexIdx, CornerIdx)> =
283 vec![(default_vertex, default_opposite); self.num_corners()];
284
285 let mut offset = 0;
286 let vertex_offset: VecVertexIdx<_> = (0..num_corners_on_vertices.len())
288 .map(|i| {
289 let i = VertexIdx::from(i);
290 let out = offset;
291 offset += num_corners_on_vertices[i];
292 out
293 })
294 .collect::<Vec<_>>()
295 .into();
296
297 for c in 0..self.num_corners() {
298 let c = CornerIdx::from(c);
299 let tip_v = self.vertex_idx(c);
300 let source_v = self.vertex_idx(self.next(c));
301 let sink_v = self.vertex_idx(self.previous(c));
302
303 let f_idx = self.face_idx_containing(c);
304 if c == Self::first_corner(f_idx) {
305 let v0 = self.vertex_idx(c);
306 if v0 == source_v || v0 == sink_v || source_v == sink_v {
307 continue; }
309 }
310
311 let mut opposite_c = default_opposite;
312 let num_corners_on_vert = num_corners_on_vertices[sink_v];
313 offset = vertex_offset[sink_v];
314 for i in 0..num_corners_on_vert {
315 let other_v = vertex_edges[offset].0;
316 if other_v == default_vertex {
317 break;
318 }
319 if other_v == source_v {
320 if tip_v == self.vertex_idx(vertex_edges[offset].1) {
323 continue;
324 }
325 opposite_c = vertex_edges[offset].1;
326 for _ in i + 1..num_corners_on_vert {
327 vertex_edges[offset] = vertex_edges[offset + 1];
328 if vertex_edges[offset].0 == default_vertex {
329 break;
330 }
331 offset += 1;
332 }
333 vertex_edges[offset].0 = default_vertex;
334 break;
335 }
336 offset += 1;
337 }
338 if opposite_c == default_opposite {
339 let num_corners_on_source_vert = num_corners_on_vertices[source_v];
340 let first_c = vertex_offset[source_v];
341 for corner in first_c..num_corners_on_source_vert + first_c {
342 if vertex_edges[corner].0 == default_vertex {
343 vertex_edges[corner].0 = sink_v;
344 vertex_edges[corner].1 = c;
345 break;
346 }
347 }
348 } else {
349 self.opposite_corners[c] = opposite_c;
350 self.opposite_corners[opposite_c] = c;
351 }
352 }
353 self.num_vertices = num_corners_on_vertices.len();
354 }
355
356 fn compute_left_most_corners(&mut self) {
357 let default_corner = CornerIdx::from(usize::MAX);
358 self.left_most_corners
359 .resize(self.num_vertices(), default_corner);
360 let mut visited_vertices = VecVertexIdx::from(vec![false; self.num_vertices()]);
361 let mut visited_corners = VecCornerIdx::from(vec![false; self.num_corners()]);
362
363 {
364 let mut vertices = VecVertexIdx::from(vec![false; self.num_vertices()]);
365 for f_idx in 0..self.get_mesh_faces().len() {
366 for i in 0..3 {
367 let c = CornerIdx::from(3 * f_idx + i);
368 let v = self.vertex_idx(c);
369 if !vertices[v] {
370 vertices[v] = true;
371 }
372 }
373 }
374 }
375
376 for f_idx in 0..self.get_mesh_faces().len() {
377 for i in 0..3 {
378 let c = CornerIdx::from(3 * f_idx + i);
379 if visited_corners[c] {
380 continue;
381 }
382
383 let mut v = self.vertex_idx(c);
384 let mut is_non_manifold_vertex = false;
385 if visited_vertices[v] {
386 self.left_most_corners.push(default_corner);
390 self.non_manifold_vertex_parents.push(v);
391 visited_vertices.push(false);
392 v = VertexIdx::from(self.num_vertices);
393 self.num_vertices += 1;
394 is_non_manifold_vertex = true;
395 }
396 visited_vertices[v] = true;
397 visited_corners[c] = true;
398 self.left_most_corners[v] = c;
399 if is_non_manifold_vertex {
400 self.corner_to_vertex.insert(c, v);
402 }
403
404 let mut maybe_act_c = self.swing_left(c);
406 while let Some(act_c) = maybe_act_c {
407 if act_c == c {
408 break;
410 }
411 visited_corners[act_c] = true;
412 self.left_most_corners[v] = act_c;
413 if is_non_manifold_vertex {
414 self.corner_to_vertex.insert(act_c, v);
416 }
417 maybe_act_c = self.swing_left(act_c);
418 }
419
420 if maybe_act_c.is_none() {
421 maybe_act_c = Some(c);
423 while let Some(act_c) = maybe_act_c {
424 visited_corners[act_c] = true;
425 if is_non_manifold_vertex {
426 self.corner_to_vertex.insert(act_c, v);
427 }
428 maybe_act_c = self.swing_right(act_c);
429 }
430 }
431 }
432 }
433 }
434
435 #[inline]
436 pub fn vertex_valence(&self, v: VertexIdx) -> usize {
437 let c = self.left_most_corner(v);
438 let mut count = 2;
439 while let Some(next_c) = self.swing_right(c) {
440 if next_c == c {
441 count -= 1;
442 break; }
444 count += 1;
445 }
446 count
447 }
448
449 #[inline]
450 pub fn first_corner(face_idx: FaceIdx) -> CornerIdx {
451 CornerIdx::from(usize::from(face_idx) * 3)
452 }
453
454 #[inline]
455 pub fn get_mesh_faces(&self) -> &[[PointIdx; 3]] {
456 self.mesh_faces
457 }
458
459 #[inline]
460 pub fn corner_to_vert(&self, corner: CornerIdx) -> VertexIdx {
461 if let Some(v) = self.corner_to_vertex.get(&corner) {
462 return *v;
463 };
464
465 let corner = usize::from(corner);
466
467 let local = corner % 3;
468 let face_idx = corner / 3;
469
470 match local {
471 0 => self.conn_faces[face_idx][0],
472 1 => self.conn_faces[face_idx][1],
473 2 => self.conn_faces[face_idx][2],
474 _ => unreachable!(), }
476 }
477}
478
479impl<'mesh> GenericCornerTable for CornerTable<'mesh> {
480 #[inline]
481 fn face_idx_containing(&self, corner: CornerIdx) -> FaceIdx {
482 (usize::from(corner) / 3).into()
483 }
484
485 #[inline]
486 fn num_faces(&self) -> usize {
487 self.get_mesh_faces().len()
488 }
489
490 #[inline]
491 fn num_corners(&self) -> usize {
492 self.num_corners
493 }
494
495 #[inline]
496 fn num_vertices(&self) -> usize {
497 self.num_vertices
498 }
499
500 #[inline]
501 fn point_idx(&self, corner: CornerIdx) -> PointIdx {
502 let corner = usize::from(corner);
503 self.get_mesh_faces()[corner / 3][corner % 3]
504 }
505
506 #[inline]
507 fn vertex_idx(&self, corner: CornerIdx) -> VertexIdx {
508 self.corner_to_vert(corner)
509 }
510
511 #[inline]
512 fn opposite(&self, corner: CornerIdx) -> Option<CornerIdx> {
513 if self.opposite_corners[corner] == CornerIdx::from(usize::MAX) {
514 None
515 } else {
516 Some(self.opposite_corners[corner])
517 }
518 }
519
520 #[inline]
521 fn previous(&self, corner: CornerIdx) -> CornerIdx {
522 let corner = usize::from(corner);
523 let out = if corner % 3 == 0 {
524 corner + 2
525 } else {
526 corner - 1
527 };
528 CornerIdx::from(out)
529 }
530
531 #[inline]
532 fn next(&self, corner: CornerIdx) -> CornerIdx {
533 let corner = usize::from(corner);
534 let out = if corner % 3 == 2 {
535 corner - 2
536 } else {
537 corner + 1
538 };
539 CornerIdx::from(out)
540 }
541
542 #[inline]
543 fn left_most_corner(&self, vertex: VertexIdx) -> CornerIdx {
544 self.left_most_corners[vertex]
545 }
546}
547
548#[cfg(test)]
549mod tests {
550 use crate::attribute::{AttributeDomain, AttributeType};
551 use crate::types::NdVector;
552
553 use super::*;
554
555 #[test]
556 fn test_corner_table() {
557 let faces = vec![
558 [PointIdx::from(0), PointIdx::from(1), PointIdx::from(2)],
559 [PointIdx::from(2), PointIdx::from(1), PointIdx::from(3)],
560 ];
561 let att = Attribute::new(
562 vec![
563 NdVector::from([0_f32, 0.0]),
564 NdVector::from([1_f32, 0.0]),
565 NdVector::from([0_f32, 1.0]),
566 NdVector::from([1_f32, 1.0]),
567 ],
568 AttributeType::Position,
569 AttributeDomain::Position,
570 vec![],
571 );
572
573 let corner_table = CornerTable::new(&faces, &att);
574 assert_eq!(corner_table.num_faces(), 2);
575 assert_eq!(corner_table.num_corners(), 6);
576 assert_eq!(corner_table.num_vertices(), 4);
577 assert_eq!(
578 corner_table.face_idx_containing(CornerIdx::from(0)),
579 FaceIdx::from(0)
580 );
581 assert_eq!(
582 corner_table.face_idx_containing(CornerIdx::from(1)),
583 FaceIdx::from(0)
584 );
585 assert_eq!(
586 corner_table.face_idx_containing(CornerIdx::from(2)),
587 FaceIdx::from(0)
588 );
589 assert_eq!(
590 corner_table.face_idx_containing(CornerIdx::from(3)),
591 FaceIdx::from(1)
592 );
593 assert_eq!(
594 corner_table.face_idx_containing(CornerIdx::from(4)),
595 FaceIdx::from(1)
596 );
597 assert_eq!(
598 corner_table.face_idx_containing(CornerIdx::from(5)),
599 FaceIdx::from(1)
600 );
601 assert!(corner_table.corner_to_vertex.is_empty());
602 assert_eq!(
603 corner_table.opposite(CornerIdx::from(0)),
604 Some(CornerIdx::from(5))
605 );
606 assert_eq!(corner_table.opposite(CornerIdx::from(1)), None);
607 assert_eq!(corner_table.opposite(CornerIdx::from(2)), None);
608 assert_eq!(corner_table.opposite(CornerIdx::from(3)), None);
609 assert_eq!(corner_table.opposite(CornerIdx::from(4)), None);
610 assert_eq!(
611 corner_table.opposite(CornerIdx::from(5)),
612 Some(CornerIdx::from(0))
613 );
614 assert_eq!(
615 corner_table.previous(CornerIdx::from(0)),
616 CornerIdx::from(2)
617 );
618 assert_eq!(
619 corner_table.previous(CornerIdx::from(1)),
620 CornerIdx::from(0)
621 );
622 assert_eq!(
623 corner_table.previous(CornerIdx::from(2)),
624 CornerIdx::from(1)
625 );
626 assert_eq!(corner_table.next(CornerIdx::from(0)), CornerIdx::from(1));
627 assert_eq!(corner_table.next(CornerIdx::from(1)), CornerIdx::from(2));
628 assert_eq!(corner_table.next(CornerIdx::from(2)), CornerIdx::from(0));
629 }
630
631 #[test]
632 fn test_no_att_seam() {
633 let faces = vec![
634 [PointIdx::from(0), PointIdx::from(1), PointIdx::from(2)],
635 [PointIdx::from(1), PointIdx::from(3), PointIdx::from(2)],
636 [PointIdx::from(2), PointIdx::from(3), PointIdx::from(4)],
637 [PointIdx::from(2), PointIdx::from(4), PointIdx::from(5)],
638 ];
639 let att = Attribute::new(
640 vec![
642 NdVector::from([0_f32, 0.0, 0.0]),
643 NdVector::from([1_f32, 0.0, 0.0]),
644 NdVector::from([0_f32, 1.0, 0.0]),
645 NdVector::from([1_f32, 1.0, 0.0]),
646 NdVector::from([0_f32, 0.5, 0.0]),
647 NdVector::from([1_f32, 0.5, 0.0]),
648 ],
649 AttributeType::Position,
650 AttributeDomain::Position,
651 vec![],
652 );
653
654 let corner_table = CornerTable::new(&faces, &att);
655 assert_eq!(corner_table.num_faces(), 4);
656 assert_eq!(corner_table.num_corners(), 12);
657 assert_eq!(corner_table.num_vertices(), 6);
658 assert!(corner_table.corner_to_vertex.is_empty());
659 }
660
661 #[test]
662 fn test_triangle() {
663 let faces = vec![[PointIdx::from(0), PointIdx::from(1), PointIdx::from(2)]];
664 let att = Attribute::new(
665 vec![
666 NdVector::from([0_f32, 0.0]),
667 NdVector::from([1_f32, 0.0]),
668 NdVector::from([0_f32, 1.0]),
669 ],
670 AttributeType::Position,
671 AttributeDomain::Position,
672 vec![],
673 );
674
675 let corner_table = CornerTable::new(&faces, &att);
676 assert_eq!(corner_table.num_faces(), 1);
677 assert_eq!(corner_table.num_corners(), 3);
678 assert_eq!(corner_table.num_vertices(), 3);
679 assert_eq!(
680 corner_table.left_most_corners,
681 VecVertexIdx::from(vec![
682 CornerIdx::from(0),
683 CornerIdx::from(1),
684 CornerIdx::from(2)
685 ])
686 );
687 }
688
689 #[test]
690 fn test_non_manifold() {
691 let faces = vec![
692 [PointIdx::from(0), PointIdx::from(1), PointIdx::from(2)],
693 [PointIdx::from(0), PointIdx::from(3), PointIdx::from(4)],
694 ];
695 let att = Attribute::new(
696 vec![
697 NdVector::from([0_f32, 0.0]),
698 NdVector::from([1_f32, 0.0]),
699 NdVector::from([0_f32, 1.0]),
700 NdVector::from([-1_f32, 1.0]),
701 NdVector::from([0_f32, -1.0]),
702 ],
703 AttributeType::Position,
704 AttributeDomain::Position,
705 vec![],
706 );
707
708 let corner_table = CornerTable::new(&faces, &att);
709 assert_eq!(corner_table.num_faces(), 2);
710 assert_eq!(corner_table.num_corners(), 6);
711 assert_eq!(corner_table.num_vertices(), 6); let answer: VecVertexIdx<CornerIdx> = vec![0, 1, 2, 4, 5, 3]
713 .into_iter()
714 .map(|x| CornerIdx::from(x))
715 .collect::<Vec<_>>()
716 .into();
717 assert_eq!(corner_table.left_most_corners, answer);
718 }
719
720 #[test]
721 fn test_non_manifold_with_seam() {
722 let faces = vec![
723 [VertexIdx::from(0), VertexIdx::from(1), VertexIdx::from(2)],
724 [VertexIdx::from(1), VertexIdx::from(3), VertexIdx::from(2)],
725 [VertexIdx::from(2), VertexIdx::from(1), VertexIdx::from(4)],
726 ];
727 assert!(
728 CornerTable::contains_non_manifold_edges(&faces),
729 "The mesh should contain non-manifold edges, but it does not."
730 );
731 }
732
733 }