parry3d_f64/transformation/convex_hull3/
validation.rs

1use super::TriangleFacet;
2#[cfg(feature = "std")]
3use crate::math::Real;
4#[cfg(feature = "std")]
5use na::Point3;
6
7pub fn check_facet_links(ifacet: usize, facets: &[TriangleFacet]) {
8    let facet = &facets[ifacet];
9
10    for i in 0..3 {
11        assert!(facets[facet.adj[i]].valid);
12    }
13
14    for i in 0..3 {
15        let adj_facet = &facets[facet.adj[i]];
16
17        assert_eq!(adj_facet.adj[facet.indirect_adj_id[i]], ifacet);
18        assert_eq!(adj_facet.indirect_adj_id[facet.indirect_adj_id[i]], i);
19        assert_eq!(
20            adj_facet.first_point_from_edge(facet.indirect_adj_id[i]),
21            facet.second_point_from_edge(i)
22        );
23        assert_eq!(
24            adj_facet.second_point_from_edge(facet.indirect_adj_id[i]),
25            facet.first_point_from_edge(i)
26        );
27    }
28}
29
30/// Checks if a convex-hull is properly formed.
31#[cfg(feature = "std")]
32pub fn check_convex_hull(points: &[Point3<Real>], triangles: &[[u32; 3]]) {
33    use std::println;
34
35    use crate::utils::hashmap::{Entry, HashMap};
36    use crate::utils::SortedPair;
37    let mut edges = HashMap::default();
38
39    struct EdgeData {
40        adjacent_triangles: [usize; 2],
41    }
42
43    // println!(
44    //     "Investigating with {} triangles, and {} points.",
45    //     triangles.len(),
46    //     points.len()
47    // );
48    // print_buildable_vec("vertices", points);
49    // print_buildable_vec("indices", triangles);
50
51    for i in 0..points.len() {
52        for j in i + 1..points.len() {
53            if points[i] == points[j] {
54                println!("Duplicate: {}", points[i]);
55                panic!("Found duplicate points.")
56            }
57        }
58    }
59
60    for (itri, tri) in triangles.iter().enumerate() {
61        assert!(tri[0] != tri[1]);
62        assert!(tri[0] != tri[2]);
63        assert!(tri[2] != tri[1]);
64
65        for i in 0..3 {
66            let ivtx1 = tri[i as usize];
67            let ivtx2 = tri[(i as usize + 1) % 3];
68            let edge_key = SortedPair::new(ivtx1, ivtx2);
69
70            match edges.entry(edge_key) {
71                Entry::Vacant(e) => {
72                    let _ = e.insert(EdgeData {
73                        adjacent_triangles: [itri, usize::MAX],
74                    });
75                }
76                Entry::Occupied(mut e) => {
77                    if e.get().adjacent_triangles[1] != usize::MAX {
78                        panic!(
79                            "Detected t-junction for triangle {}, edge: {:?}.",
80                            itri,
81                            (ivtx1, ivtx2)
82                        );
83                    }
84
85                    e.get_mut().adjacent_triangles[1] = itri;
86                }
87            }
88        }
89    }
90
91    for edge in &edges {
92        if edge.1.adjacent_triangles[1] == usize::MAX {
93            panic!("Detected unfinished triangle.");
94        }
95    }
96
97    // Check Euler characteristic.
98    assert_eq!(points.len() + triangles.len() - edges.len(), 2);
99}
100
101// fn print_buildable_vec<T: core::fmt::Display + na::Scalar>(desc: &str, elts: &[Point3<T>]) {
102//     print!("let {} = vec![", desc);
103//     for elt in elts {
104//         print!("Point3::new({},{},{}),", elt.x, elt.y, elt.z);
105//     }
106//     println!("];")
107// }