fj_core/algorithms/approx/
mod.rs

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