geop_core_topology/validation/
mod.rs1mod check_curves_and_surfaces_vertices;
10mod curve_and_surface_sampling_check;
11mod disjointness_check;
12mod face_face_numerical_intersection;
13mod face_orientation;
14mod faces_have_interior;
15mod holes_inside_outer;
16mod manifold_check;
17pub mod numerical_accuracy;
18mod parameters;
19mod pcurve_loop_continuity;
20mod pointer_check;
21mod two_way_references;
22
23pub use manifold_check::validate_manifold;
24pub use parameters::ValidationParameters;
25
26use crate::Model;
27use geop_core_math::{geop_error::GeopError, scalars::Scalar};
28
29pub fn validate<S: Scalar>(
30 params: &ValidationParameters<S>,
31 model: &Model<S>,
32) -> Result<(), Vec<GeopError>> {
33 let mut errors = Vec::new();
34
35 numerical_accuracy::check_numerical_accuracy(params, &mut errors, model);
37 pointer_check::check_pointers(params, &mut errors, model);
38 two_way_references::check_two_way_references(params, &mut errors, model);
39 check_curves_and_surfaces_vertices::check_curves_and_surfaces_vertices(
40 params,
41 &mut errors,
42 model,
43 );
44 curve_and_surface_sampling_check::check_curve_and_surface_sampling(params, &mut errors, model);
45 pcurve_loop_continuity::check_pcurve_loop_continuity(params, &mut errors, model);
46 disjointness_check::check_vertices_disjoint(params, &mut errors, model);
47 disjointness_check::check_edges_disjoint(params, &mut errors, model);
48 disjointness_check::check_edges_and_faces_consistent(params, &mut errors, model);
49 face_face_numerical_intersection::check_face_face_numerical_intersection(
50 params,
51 &mut errors,
52 model,
53 );
54 holes_inside_outer::check_holes_inside_outer(params, &mut errors, model);
55 face_orientation::check_loop_winding(params, &mut errors, model);
56 face_orientation::check_normals_point_outward(params, &mut errors, model);
57
58 if errors.is_empty() {
59 Ok(())
60 } else {
61 Err(errors)
62 }
63}
64
65pub fn validate_fast<S: Scalar>(
76 params: &ValidationParameters<S>,
77 model: &Model<S>,
78) -> Result<(), Vec<GeopError>> {
79 let mut errors = Vec::new();
80
81 numerical_accuracy::check_numerical_accuracy(params, &mut errors, model);
84 pointer_check::check_pointers(params, &mut errors, model);
85 two_way_references::check_two_way_references(params, &mut errors, model);
86 check_curves_and_surfaces_vertices::check_curves_and_surfaces_vertices(
87 params,
88 &mut errors,
89 model,
90 );
91 pcurve_loop_continuity::check_pcurve_loop_continuity(params, &mut errors, model);
92 faces_have_interior::check_faces_have_interior(params, &mut errors, model);
93
94 if errors.is_empty() {
95 Ok(())
96 } else {
97 Err(errors)
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::{ValidationParameters, validate};
104 use crate::Model;
105 use crate::test_fixtures::test_cube_solid;
106 use geop_core_math::{for_all_scalars, scalars::Scalar, vector::Vector3};
107
108 fn check_cube_passes_full_validate<S: Scalar>() {
109 let mut model = Model::<S>::new();
110 test_cube_solid(&mut model);
111 validate(&ValidationParameters::default(), &model).unwrap();
112 }
113 #[test]
114 fn cube_passes_full_validate() {
115 for_all_scalars!(check_cube_passes_full_validate);
116 }
117
118 fn check_independent_failures_are_all_reported<S: Scalar>() {
119 let mut model = Model::<S>::new();
120 test_cube_solid(&mut model);
121
122 let face_id = *model.faces.keys().next().unwrap();
126 let shell_id = model.faces[&face_id].shell;
127 model
128 .shells
129 .get_mut(&shell_id)
130 .unwrap()
131 .faces
132 .retain(|&f| f != face_id);
133
134 let vertex_id = *model.vertices.keys().next().unwrap();
135 model.vertices.get_mut(&vertex_id).unwrap().point =
136 Vector3::from_array([S::from_f64(42.0); 3]);
137
138 let errors = validate(&ValidationParameters::default(), &model).unwrap_err();
142 assert!(errors.len() >= 2);
143 }
144 #[test]
145 fn independent_failures_are_all_reported() {
146 for_all_scalars!(check_independent_failures_are_all_reported);
147 }
148}