fj_kernel/algorithms/approx/
face.rs1use std::{collections::BTreeSet, ops::Deref};
6
7use fj_interop::mesh::Color;
8
9use crate::{
10 objects::{Face, FaceSet, Handedness},
11 validate::ValidationConfig,
12};
13
14use super::{
15 cycle::CycleApprox, edge::EdgeCache, Approx, ApproxPoint, Tolerance,
16};
17
18impl Approx for &FaceSet {
19 type Approximation = BTreeSet<FaceApprox>;
20 type Cache = EdgeCache;
21
22 fn approx_with_cache(
23 self,
24 tolerance: impl Into<Tolerance>,
25 cache: &mut Self::Cache,
26 ) -> Self::Approximation {
27 let tolerance = tolerance.into();
28
29 let approx = self
30 .into_iter()
31 .map(|face| face.approx_with_cache(tolerance, cache))
32 .collect();
33
34 let min_distance = ValidationConfig::default().distinct_min_distance;
35 let mut all_points: BTreeSet<ApproxPoint<2>> = BTreeSet::new();
36
37 for approx in &approx {
39 let approx: &FaceApprox = approx;
40
41 for a in &approx.points() {
42 for b in &all_points {
43 let distance = (b.global_form - a.global_form).magnitude();
44
45 if b.global_form != a.global_form && distance < min_distance
46 {
47 panic!(
48 "Invalid approximation: \
49 Distinct points are too close \
50 (a: {:?}, b: {:?}, distance: {distance})",
51 a.global_form, b.global_form,
52 );
53 }
54 }
55
56 all_points.insert(a.clone());
57 }
58 }
59
60 approx
61 }
62}
63
64impl Approx for &Face {
65 type Approximation = FaceApprox;
66 type Cache = EdgeCache;
67
68 fn approx_with_cache(
69 self,
70 tolerance: impl Into<Tolerance>,
71 cache: &mut Self::Cache,
72 ) -> Self::Approximation {
73 let tolerance = tolerance.into();
74
75 let exterior = (self.exterior().deref(), self.surface().deref())
89 .approx_with_cache(tolerance, cache);
90
91 let mut interiors = BTreeSet::new();
92 for cycle in self.interiors() {
93 let cycle = (cycle.deref(), self.surface().deref())
94 .approx_with_cache(tolerance, cache);
95 interiors.insert(cycle);
96 }
97
98 FaceApprox {
99 exterior,
100 interiors,
101 color: self.color(),
102 coord_handedness: self.coord_handedness(),
103 }
104 }
105}
106
107#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
109pub struct FaceApprox {
110 pub exterior: CycleApprox,
112
113 pub interiors: BTreeSet<CycleApprox>,
115
116 pub color: Option<Color>,
118
119 pub coord_handedness: Handedness,
121}
122
123impl FaceApprox {
124 pub fn points(&self) -> BTreeSet<ApproxPoint<2>> {
126 let mut points = BTreeSet::new();
127
128 points.extend(self.exterior.points());
129
130 for cycle_approx in &self.interiors {
131 points.extend(cycle_approx.points());
132 }
133
134 points
135 }
136}