fj-core 0.49.0

Early-stage b-rep CAD kernel.
Documentation
use fj_math::{Scalar, Vector};

use crate::{
    geometry::GlobalPath,
    objects::{Face, Sketch, Solid, Surface},
    operations::{derive::DeriveFrom, insert::Insert, reverse::Reverse},
    storage::Handle,
    Core,
};

use super::{face::SweepFace, SweepCache};

/// # Sweep a [`Sketch`]
///
/// See [module documentation] for more information.
///
/// [module documentation]: super
pub trait SweepSketch {
    /// # Sweep the [`Sketch`]
    fn sweep_sketch(
        &self,
        surface: Handle<Surface>,
        path: impl Into<Vector<3>>,
        core: &mut Core,
    ) -> Solid;
}

impl SweepSketch for Sketch {
    fn sweep_sketch(
        &self,
        surface: Handle<Surface>,
        path: impl Into<Vector<3>>,
        core: &mut Core,
    ) -> Solid {
        let path = path.into();
        let mut cache = SweepCache::default();

        let mut shells = Vec::new();
        for region in self.regions() {
            let region = {
                // The following code assumes that the sketch is winded counter-
                // clockwise. Let's check that real quick.
                assert!(region
                    .exterior()
                    .winding(&core.layers.geometry)
                    .is_ccw());

                let is_negative_sweep = {
                    let u = match core.layers.geometry.of_surface(&surface).u {
                        GlobalPath::Circle(_) => todo!(
                            "Sweeping sketch from a rounded surfaces is not \
                            supported"
                        ),
                        GlobalPath::Line(line) => line.direction(),
                    };
                    let v = core.layers.geometry.of_surface(&surface).v;

                    let normal = u.cross(&v);

                    normal.dot(&path) < Scalar::ZERO
                };

                if is_negative_sweep {
                    region.clone()
                } else {
                    region.reverse(core).insert(core).derive_from(region, core)
                }
            };

            let face = Face::new(surface.clone(), region.clone()).insert(core);
            let shell = face.sweep_face(path, &mut cache, core).insert(core);
            shells.push(shell);
        }

        Solid::new(shells)
    }
}