axiolid_tessellation_contract/
options.rs

1//! Explicit tessellation quality policy.
2
3use axiolid_core::{Scalar, Tolerance};
4
5/// Invalid tessellation options.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub struct InvalidTessellationOptions;
8
9impl core::fmt::Display for InvalidTessellationOptions {
10    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
11        f.write_str("tessellation limits must be finite and positive")
12    }
13}
14
15impl std::error::Error for InvalidTessellationOptions {}
16
17/// Approximation controls. No global/default chord error exists because source
18/// units and downstream use determine acceptable error.
19#[derive(Debug, Clone, Copy, PartialEq)]
20pub struct TessellationOptions {
21    chord_error: Scalar,
22    maximum_angle: Scalar,
23    maximum_edge_length: Option<Scalar>,
24    tolerance: Tolerance,
25}
26
27impl TessellationOptions {
28    /// Construct validated approximation controls.
29    pub fn new(
30        chord_error: Scalar,
31        maximum_angle: Scalar,
32        tolerance: Tolerance,
33    ) -> Result<Self, InvalidTessellationOptions> {
34        if !chord_error.is_finite()
35            || chord_error <= 0.0
36            || !maximum_angle.is_finite()
37            || maximum_angle <= 0.0
38        {
39            return Err(InvalidTessellationOptions);
40        }
41        Ok(Self {
42            chord_error,
43            maximum_angle,
44            maximum_edge_length: None,
45            tolerance,
46        })
47    }
48
49    /// Add a maximum edge length.
50    pub fn with_maximum_edge_length(
51        mut self,
52        value: Scalar,
53    ) -> Result<Self, InvalidTessellationOptions> {
54        if !value.is_finite() || value <= 0.0 {
55            return Err(InvalidTessellationOptions);
56        }
57        self.maximum_edge_length = Some(value);
58        Ok(self)
59    }
60
61    /// Maximum chord deviation.
62    pub const fn chord_error(self) -> Scalar {
63        self.chord_error
64    }
65
66    /// Maximum change in tangent/normal in radians.
67    pub const fn maximum_angle(self) -> Scalar {
68        self.maximum_angle
69    }
70
71    /// Optional maximum generated edge length.
72    pub const fn maximum_edge_length(self) -> Option<Scalar> {
73        self.maximum_edge_length
74    }
75
76    /// Structural/evaluation tolerance.
77    pub const fn tolerance(self) -> Tolerance {
78        self.tolerance
79    }
80}