Skip to main content

geop_core_topology/validation/
parameters.rs

1use geop_core_math::scalars::Scalar;
2
3/// Shared tuning knobs for the whole-model validation checks — how many
4/// points to sample along a curve, and the budgets passed down to the
5/// underlying BFS/DFS geometric searches.
6#[derive(Clone, Copy, Debug)]
7pub struct ValidationParameters<S: Scalar> {
8    /// How many points to sample along a curve for sampling-based checks.
9    pub sample_count: usize,
10    /// Node budget for the BFS containment searches (see
11    /// `contains::curve::curve_could_contain`), and for the pairwise
12    /// `curve_curve_intersect`/`curve_surface_intersect` searches in
13    /// `disjointness_check` (which now error, rather than silently
14    /// returning a truncated result, if they exhaust it — see
15    /// `curve_surface_intersect`'s own doc comment).
16    pub max_nodes: usize,
17    /// Convergence tolerance for those same searches. Empirically, the
18    /// pairwise `curve_curve_intersect`/`curve_surface_intersect` searches
19    /// need a *much* looser tolerance than a single-curve
20    /// `curve_could_contain` query to reliably converge within `max_nodes`:
21    /// `1e-7` can fail to resolve a clean, unambiguous case at all; `1e-5`
22    /// resolves most cases but not a near-tangential edge/face pair (e.g.
23    /// two adjacent flat walls of an `extruded_cylinder`'s polygon
24    /// approximation meeting at a shallow dihedral angle, or an edge ending
25    /// exactly at a `revolve`d cap's own pole) — each halving of the
26    /// tolerance costs roughly one extra subdivision *level*, and a
27    /// near-tangential pair's hull-overlap pruning barely discriminates at
28    /// all (see `curve_surface_intersect`'s own doc comment), so that one
29    /// extra level can mean an order of magnitude more nodes. `1e-4` is
30    /// loose enough to resolve every case in this crate's own basic-shape
31    /// validations within `max_nodes`, while still being far tighter than
32    /// any genuine geometric feature these checks care about.
33    pub min_subdivision_size: S,
34    /// `max_solutions` passed to `curve_curve_intersect` for every edge x
35    /// edge pair: how many points to return at most. Coincidence is reported
36    /// directly (`Intersections::Coincident`), not inferred from reaching
37    /// this count.
38    pub max_edge_edge_intersection_samples: usize,
39    /// Same idea as `max_edge_edge_intersection_samples`, but for
40    /// `curve_surface_intersect` on every edge x face pair.
41    pub max_edge_face_intersection_samples: usize,
42    /// How many random (point-on-face-a, point-on-face-b) starting pairs
43    /// `face_face_numerical_intersection` tries per face pair.
44    pub face_face_sample_count: usize,
45    /// How many alternating-projection Newton rounds each of those starting
46    /// pairs gets to converge in.
47    pub face_face_newton_iterations: usize,
48    /// How many random points, and how many random ray directions per
49    /// point, `validate_manifold`'s ray-direction-consistency check tries
50    /// per shell.
51    pub manifold_ray_sample_count: usize,
52    /// Seeds every random draw in `validate_manifold`'s
53    /// ray-direction-consistency check.
54    pub manifold_seed: u64,
55}
56
57impl<S: Scalar> Default for ValidationParameters<S> {
58    fn default() -> Self {
59        Self {
60            sample_count: 17,
61            max_nodes: 5000,
62            min_subdivision_size: S::from_f64(1e-4),
63            max_edge_edge_intersection_samples: 17,
64            max_edge_face_intersection_samples: 7,
65            face_face_sample_count: 20,
66            face_face_newton_iterations: 20,
67            manifold_ray_sample_count: 10,
68            manifold_seed: 0x5EED_1234_5678_9ABC,
69        }
70    }
71}