1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
4pub enum SamplingMode {
6 TriangleCentroids,
8 Vertices,
10 CentroidsAndVertices,
12}
13
14#[derive(Clone, Debug, Deserialize, Serialize)]
15#[serde(default)]
16pub struct RecognitionOptions {
18 pub distance_tolerance: f64,
20 pub relative_tolerance: f64,
22 pub normal_tolerance: f64,
24 pub minimum_support: usize,
26 pub minimum_support_area: f64,
28 pub confidence: f64,
33 pub deterministic_seed: Option<u64>,
36 pub max_hypotheses: usize,
38 pub max_refinement_iterations: usize,
40 pub feature_angle: f64,
42 pub respect_features: bool,
44 pub discover_regions: bool,
46 pub allow_disconnected_same_surface: bool,
49 pub collect_phase_timings: bool,
52 pub sampling: SamplingMode,
54}
55
56impl Default for RecognitionOptions {
57 fn default() -> Self {
58 Self {
59 distance_tolerance: 1.0e-6,
60 relative_tolerance: 1.0e-8,
61 normal_tolerance: 5.0_f64.to_radians(),
62 minimum_support: 6,
63 minimum_support_area: 0.0,
64 confidence: 0.999,
65 deterministic_seed: Some(0x4341_4452_414e_5341),
66 max_hypotheses: 512,
67 max_refinement_iterations: 160,
71 feature_angle: 30.0_f64.to_radians(),
72 respect_features: true,
73 discover_regions: true,
74 allow_disconnected_same_surface: false,
75 collect_phase_timings: false,
76 sampling: SamplingMode::CentroidsAndVertices,
77 }
78 }
79}
80
81impl RecognitionOptions {
82 pub(crate) fn validate(&self) -> Result<(), crate::RecognitionError> {
83 if !self.distance_tolerance.is_finite() || self.distance_tolerance <= 0.0 {
84 return Err(crate::RecognitionError::InvalidOptions(
85 "distance_tolerance must be finite and positive".into(),
86 ));
87 }
88 if !self.relative_tolerance.is_finite() || self.relative_tolerance < 0.0 {
89 return Err(crate::RecognitionError::InvalidOptions(
90 "relative_tolerance must be finite and non-negative".into(),
91 ));
92 }
93 if !(0.0..=std::f64::consts::PI).contains(&self.normal_tolerance) {
94 return Err(crate::RecognitionError::InvalidOptions(
95 "normal_tolerance must be in [0, pi]".into(),
96 ));
97 }
98 if self.minimum_support == 0 {
99 return Err(crate::RecognitionError::InvalidOptions(
100 "minimum_support must be non-zero".into(),
101 ));
102 }
103 if !self.minimum_support_area.is_finite() || self.minimum_support_area < 0.0 {
104 return Err(crate::RecognitionError::InvalidOptions(
105 "minimum_support_area must be finite and non-negative".into(),
106 ));
107 }
108 if !(0.0..1.0).contains(&self.confidence) {
109 return Err(crate::RecognitionError::InvalidOptions(
110 "confidence must be in [0, 1)".into(),
111 ));
112 }
113 if self.max_hypotheses == 0 || self.max_refinement_iterations == 0 {
114 return Err(crate::RecognitionError::InvalidOptions(
115 "iteration limits must be non-zero".into(),
116 ));
117 }
118 if !(0.0..=std::f64::consts::PI).contains(&self.feature_angle) {
119 return Err(crate::RecognitionError::InvalidOptions(
120 "feature_angle must be finite and in [0, pi]".into(),
121 ));
122 }
123 Ok(())
124 }
125}
126
127