fj_core/operations/sweep/
sketch.rs

1use fj_math::{Scalar, Vector};
2
3use crate::{
4    geometry::GlobalPath,
5    objects::{Face, Sketch, Solid, Surface},
6    operations::{derive::DeriveFrom, insert::Insert, reverse::Reverse},
7    storage::Handle,
8    Core,
9};
10
11use super::{face::SweepFace, SweepCache};
12
13/// # Sweep a [`Sketch`]
14///
15/// See [module documentation] for more information.
16///
17/// [module documentation]: super
18pub trait SweepSketch {
19    /// # Sweep the [`Sketch`]
20    fn sweep_sketch(
21        &self,
22        surface: Handle<Surface>,
23        path: impl Into<Vector<3>>,
24        core: &mut Core,
25    ) -> Solid;
26}
27
28impl SweepSketch for Sketch {
29    fn sweep_sketch(
30        &self,
31        surface: Handle<Surface>,
32        path: impl Into<Vector<3>>,
33        core: &mut Core,
34    ) -> Solid {
35        let path = path.into();
36        let mut cache = SweepCache::default();
37
38        let mut shells = Vec::new();
39        for region in self.regions() {
40            let region = {
41                // The following code assumes that the sketch is winded counter-
42                // clockwise. Let's check that real quick.
43                assert!(region
44                    .exterior()
45                    .winding(&core.layers.geometry)
46                    .is_ccw());
47
48                let is_negative_sweep = {
49                    let u = match core.layers.geometry.of_surface(&surface).u {
50                        GlobalPath::Circle(_) => todo!(
51                            "Sweeping sketch from a rounded surfaces is not \
52                            supported"
53                        ),
54                        GlobalPath::Line(line) => line.direction(),
55                    };
56                    let v = core.layers.geometry.of_surface(&surface).v;
57
58                    let normal = u.cross(&v);
59
60                    normal.dot(&path) < Scalar::ZERO
61                };
62
63                if is_negative_sweep {
64                    region.clone()
65                } else {
66                    region.reverse(core).insert(core).derive_from(region, core)
67                }
68            };
69
70            let face = Face::new(surface.clone(), region.clone()).insert(core);
71            let shell = face.sweep_face(path, &mut cache, core).insert(core);
72            shells.push(shell);
73        }
74
75        Solid::new(shells)
76    }
77}