diff --git a/Cargo.lock b/Cargo.lock index 327964088f..b63dddd89e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1259,6 +1259,14 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" +[[package]] +name = "holes" +version = "0.1.0" +dependencies = [ + "cuboid", + "fj", +] + [[package]] name = "http" version = "0.2.11" diff --git a/Cargo.toml b/Cargo.toml index 119d8db45c..a5d6bd8e09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = [ "models/all", "models/cuboid", + "models/holes", "models/spacer", "models/split", "models/star", diff --git a/crates/fj-core/src/operations/holes.rs b/crates/fj-core/src/operations/holes.rs new file mode 100644 index 0000000000..a5d42bc8fb --- /dev/null +++ b/crates/fj-core/src/operations/holes.rs @@ -0,0 +1,76 @@ +//! Add holes to shapes + +use fj_math::{Point, Vector}; + +use crate::{ + objects::{Cycle, Face, HalfEdge, Region, Shell}, + services::Services, + storage::Handle, +}; + +use super::{ + build::{BuildCycle, BuildHalfEdge, BuildRegion}, + insert::Insert, + join::JoinCycle, + sweep::{SweepCache, SweepRegion}, + update::{UpdateCycle, UpdateFace, UpdateRegion, UpdateShell}, +}; + +/// Add a hole to a [`Shell`] +pub trait AddHole { + /// Add a blind hole to the provided face of the shell + fn add_blind_hole( + &self, + face: &Handle, + position: impl Into>, + path: impl Into>, + services: &mut Services, + ) -> Self; +} + +impl AddHole for Shell { + fn add_blind_hole( + &self, + face: &Handle, + position: impl Into>, + path: impl Into>, + services: &mut Services, + ) -> Self { + let half_edge = + HalfEdge::circle(position, 0.25, services).insert(services); + let hole = Region::empty(services) + .update_exterior(|_| { + Cycle::empty() + .add_half_edges([half_edge.clone()]) + .insert(services) + }) + .sweep_region( + face.surface(), + path, + &mut SweepCache::default(), + services, + ) + .into_iter() + .map(|face| face.insert(services)) + .collect::>(); + + self.update_face(face, |face| { + face.update_region(|region| { + region + .add_interiors([Cycle::empty() + .add_joined_edges( + [( + half_edge.clone(), + half_edge.path(), + half_edge.boundary(), + )], + services, + ) + .insert(services)]) + .insert(services) + }) + .insert(services) + }) + .add_faces(hole) + } +} diff --git a/crates/fj-core/src/operations/mod.rs b/crates/fj-core/src/operations/mod.rs index 405884c503..790384d177 100644 --- a/crates/fj-core/src/operations/mod.rs +++ b/crates/fj-core/src/operations/mod.rs @@ -39,6 +39,7 @@ //! send a pull request! pub mod build; +pub mod holes; pub mod insert; pub mod join; pub mod merge; diff --git a/models/holes/Cargo.toml b/models/holes/Cargo.toml new file mode 100644 index 0000000000..5f90cc33a6 --- /dev/null +++ b/models/holes/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "holes" +version = "0.1.0" +edition = "2021" + +[dependencies.fj] +path = "../../crates/fj" + +[dependencies.cuboid] +path = "../cuboid" diff --git a/models/holes/src/lib.rs b/models/holes/src/lib.rs new file mode 100644 index 0000000000..56bbca819d --- /dev/null +++ b/models/holes/src/lib.rs @@ -0,0 +1,24 @@ +use fj::core::{ + objects::Solid, + operations::{holes::AddHole, insert::Insert, update::UpdateSolid}, + services::Services, + storage::Handle, +}; + +pub fn model(services: &mut Services) -> Handle { + let cuboid = cuboid::model(1., 1., 1., services); + + let shell = cuboid.shells().first(); + let bottom_face = shell.faces().first(); + + let hole_position = [0., 0.]; + let hole_path = [0., 0., 0.5]; + + cuboid + .update_shell(shell, |shell| { + shell + .add_blind_hole(bottom_face, hole_position, hole_path, services) + .insert(services) + }) + .insert(services) +} diff --git a/models/holes/src/main.rs b/models/holes/src/main.rs new file mode 100644 index 0000000000..9091143ecd --- /dev/null +++ b/models/holes/src/main.rs @@ -0,0 +1,8 @@ +use fj::{core::services::Services, handle_model}; + +fn main() -> fj::Result { + let mut services = Services::new(); + let model = holes::model(&mut services); + handle_model(model, services)?; + Ok(()) +}