fj_kernel/algorithms/approx/
mod.rs

1//! Approximation of objects
2
3pub mod cycle;
4pub mod edge;
5pub mod face;
6pub mod path;
7pub mod shell;
8pub mod sketch;
9pub mod solid;
10pub mod tolerance;
11
12use std::{
13    cmp::Ordering,
14    fmt::Debug,
15    hash::{Hash, Hasher},
16};
17
18use fj_math::Point;
19
20pub use self::tolerance::{InvalidTolerance, Tolerance};
21
22/// Approximate an object
23pub trait Approx: Sized {
24    /// The approximation of the object
25    type Approximation;
26
27    /// The cache used to cache approximation results
28    type Cache: Default;
29
30    /// Approximate the object
31    ///
32    /// `tolerance` defines how far the approximation is allowed to deviate from
33    /// the actual object.
34    fn approx(self, tolerance: impl Into<Tolerance>) -> Self::Approximation {
35        let mut cache = Self::Cache::default();
36        self.approx_with_cache(tolerance, &mut cache)
37    }
38
39    /// Approximate the object, using the provided cache
40    ///
41    /// This is a lower-level method that allows some degree of control over
42    /// caching. Callers might consider using [`Approx::approx`] instead.
43    fn approx_with_cache(
44        self,
45        tolerance: impl Into<Tolerance>,
46        cache: &mut Self::Cache,
47    ) -> Self::Approximation;
48}
49
50/// A point from an approximation, with local and global forms
51#[derive(Debug, Clone)]
52pub struct ApproxPoint<const D: usize> {
53    /// The local form of the point
54    pub local_form: Point<D>,
55
56    /// The global form of the points
57    pub global_form: Point<3>,
58}
59
60impl<const D: usize> ApproxPoint<D> {
61    /// Create an instance of `ApproxPoint`, without a source
62    pub fn new(local_form: Point<D>, global_form: Point<3>) -> Self {
63        Self {
64            local_form,
65            global_form,
66        }
67    }
68}
69
70impl<const D: usize> Eq for ApproxPoint<D> {}
71
72impl<const D: usize> PartialEq for ApproxPoint<D> {
73    fn eq(&self, other: &Self) -> bool {
74        self.local_form == other.local_form
75            && self.global_form == other.global_form
76    }
77}
78
79impl<const D: usize> Hash for ApproxPoint<D> {
80    fn hash<H: Hasher>(&self, state: &mut H) {
81        self.local_form.hash(state);
82        self.global_form.hash(state);
83    }
84}
85
86impl<const D: usize> Ord for ApproxPoint<D> {
87    fn cmp(&self, other: &Self) -> Ordering {
88        match self.local_form.cmp(&other.local_form) {
89            Ordering::Equal => {}
90            ord => return ord,
91        }
92        self.global_form.cmp(&other.global_form)
93    }
94}
95
96impl<const D: usize> PartialOrd for ApproxPoint<D> {
97    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
98        Some(self.cmp(other))
99    }
100}