fj_core/operations/sweep/
region.rs

1use fj_interop::Color;
2use fj_math::Vector;
3
4use crate::{
5    geometry::SurfaceGeometry,
6    objects::{Cycle, Face, Region, Surface},
7    operations::{
8        insert::Insert, reverse::Reverse, transform::TransformObject,
9    },
10    storage::Handle,
11    Core,
12};
13
14use super::{SweepCache, SweepCycle};
15
16/// # Sweep a [`Region`]
17///
18/// See [module documentation] for more information.
19///
20/// [module documentation]: super
21pub trait SweepRegion {
22    /// # Sweep the [`Region`]
23    ///
24    /// Sweep the region into multiple sets of faces. Each set of faces is
25    /// formed by sweeping one of the region's cycles, then adding a top face.
26    ///
27    /// Requires the surface that the face that the region belongs to is defined
28    /// in.
29    ///
30    /// There no "bottom" face. Whether having one is desirable depends on the
31    /// context of the caller of this operation, and falls outside of this
32    /// operation's scope.
33    fn sweep_region(
34        &self,
35        surface: &Handle<Surface>,
36        color: Option<Color>,
37        path: impl Into<Vector<3>>,
38        cache: &mut SweepCache,
39        core: &mut Core,
40    ) -> SweptRegion;
41}
42
43impl SweepRegion for Region {
44    fn sweep_region(
45        &self,
46        surface: &Handle<Surface>,
47        color: Option<Color>,
48        path: impl Into<Vector<3>>,
49        cache: &mut SweepCache,
50        core: &mut Core,
51    ) -> SweptRegion {
52        let path = path.into();
53
54        let mut faces = Vec::new();
55
56        let top_exterior = sweep_cycle(
57            self.exterior(),
58            &core.layers.geometry.of_surface(surface),
59            color,
60            &mut faces,
61            path,
62            cache,
63            core,
64        );
65
66        let top_interiors = self
67            .interiors()
68            .iter()
69            .map(|bottom_cycle| {
70                sweep_cycle(
71                    bottom_cycle,
72                    &core.layers.geometry.of_surface(surface),
73                    color,
74                    &mut faces,
75                    path,
76                    cache,
77                    core,
78                )
79            })
80            .collect::<Vec<_>>();
81
82        let top_face = {
83            let top_surface = surface.translate(path, core).insert(core);
84            let top_region =
85                Region::new(top_exterior, top_interiors).insert(core);
86
87            Face::new(top_surface, top_region)
88        };
89
90        SweptRegion {
91            top_face,
92            side_faces: faces,
93        }
94    }
95}
96
97fn sweep_cycle(
98    bottom_cycle: &Cycle,
99    bottom_surface: &SurfaceGeometry,
100    color: Option<Color>,
101    faces: &mut Vec<Face>,
102    path: Vector<3>,
103    cache: &mut SweepCache,
104    core: &mut Core,
105) -> Handle<Cycle> {
106    let swept_cycle = bottom_cycle.reverse(core).sweep_cycle(
107        bottom_surface,
108        color,
109        path,
110        cache,
111        core,
112    );
113
114    faces.extend(swept_cycle.faces);
115
116    swept_cycle.top_cycle.insert(core)
117}
118
119/// The result of sweeping a [`Region`]
120///
121/// See [`SweepRegion`].
122#[derive(Clone)]
123pub struct SweptRegion {
124    /// The side faces created by the sweep
125    pub side_faces: Vec<Face>,
126
127    /// The top face created by the sweep
128    pub top_face: Face,
129}
130
131impl SweptRegion {
132    /// Return an iterator over all of the faces
133    pub fn all_faces(self) -> impl Iterator<Item = Face> {
134        self.side_faces.into_iter().chain([self.top_face])
135    }
136}