fj_kernel/algorithms/approx/
cycle.rs1use std::ops::Deref;
6
7use fj_math::Segment;
8
9use crate::objects::{Cycle, Surface};
10
11use super::{
12 edge::{EdgeCache, HalfEdgeApprox},
13 Approx, ApproxPoint, Tolerance,
14};
15
16impl Approx for (&Cycle, &Surface) {
17 type Approximation = CycleApprox;
18 type Cache = EdgeCache;
19
20 fn approx_with_cache(
21 self,
22 tolerance: impl Into<Tolerance>,
23 cache: &mut Self::Cache,
24 ) -> Self::Approximation {
25 let (cycle, surface) = self;
26 let tolerance = tolerance.into();
27
28 let half_edges = cycle
29 .half_edges()
30 .map(|half_edge| {
31 (half_edge.deref(), surface).approx_with_cache(tolerance, cache)
32 })
33 .collect();
34
35 CycleApprox { half_edges }
36 }
37}
38
39#[derive(Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
41pub struct CycleApprox {
42 pub half_edges: Vec<HalfEdgeApprox>,
44}
45
46impl CycleApprox {
47 pub fn points(&self) -> Vec<ApproxPoint<2>> {
49 let mut points = Vec::new();
50
51 for approx in &self.half_edges {
52 points.extend(approx.points());
53 }
54
55 if let Some(point) = points.first() {
56 points.push(point.clone());
57 }
58
59 points
60 }
61
62 pub fn segments(&self) -> Vec<Segment<3>> {
64 let mut segments = Vec::new();
65
66 for segment in self.points().windows(2) {
67 let segment = [&segment[0], &segment[1]];
70
71 segments
72 .push(Segment::from(segment.map(|point| point.global_form)));
73 }
74
75 segments
76 }
77}