#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Tolerance {
pub confusion: f64,
pub angular: f64,
pub parametric: f64,
}
impl Tolerance {
pub const MODEL_SIZE: f64 = 1e5;
pub const DEFAULT: Tolerance = Tolerance {
confusion: 1e-7,
angular: 1e-12,
parametric: 1e-9,
};
pub const fn new(confusion: f64, angular: f64, parametric: f64) -> Tolerance {
Tolerance {
confusion,
angular,
parametric,
}
}
pub fn angular_for_extent(&self, extent: f64) -> f64 {
(self.confusion / extent).max(self.angular)
}
}
impl Default for Tolerance {
fn default() -> Tolerance {
Tolerance::DEFAULT
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_matches_constants() {
assert_eq!(Tolerance::default(), Tolerance::DEFAULT);
assert_eq!(Tolerance::DEFAULT.confusion, 1e-7);
assert_eq!(Tolerance::DEFAULT.angular, 1e-12);
assert_eq!(Tolerance::DEFAULT.parametric, 1e-9);
}
#[test]
fn test_default_angular_is_confusion_over_model_size() {
let derived = Tolerance::DEFAULT.confusion / Tolerance::MODEL_SIZE;
assert!((Tolerance::DEFAULT.angular / derived - 1.0).abs() < 1e-12);
}
#[test]
fn test_angular_for_extent_is_confusion_over_extent_down_to_angular() {
let tol = Tolerance::DEFAULT;
assert_eq!(tol.angular_for_extent(1.0), 1e-7);
assert_eq!(tol.angular_for_extent(1e9), tol.angular);
assert_eq!(tol.angular_for_extent(0.0), f64::INFINITY);
}
#[test]
fn test_struct_update_syntax() {
let loose = Tolerance {
confusion: 1e-3,
..Tolerance::DEFAULT
};
assert_eq!(loose.confusion, 1e-3);
assert_eq!(loose.angular, Tolerance::DEFAULT.angular);
assert_eq!(loose.parametric, Tolerance::DEFAULT.parametric);
}
}