From c2fbd8cb686401c439d3ac945311961bce45b62b Mon Sep 17 00:00:00 2001 From: A-Walrus Date: Mon, 15 May 2023 19:35:35 +0300 Subject: [PATCH 1/3] Switch to Regions --- .../fj-kernel/src/algorithms/approx/sketch.rs | 6 +- .../fj-kernel/src/algorithms/sweep/sketch.rs | 6 +- .../fj-kernel/src/algorithms/transform/mod.rs | 1 - .../src/algorithms/transform/sketch.rs | 21 ----- crates/fj-kernel/src/geometry/mod.rs | 1 + crates/fj-kernel/src/geometry/region.rs | 77 +++++++++++++++++++ crates/fj-kernel/src/objects/full/face.rs | 17 ++-- crates/fj-kernel/src/objects/full/sketch.rs | 25 ++++-- 8 files changed, 109 insertions(+), 45 deletions(-) delete mode 100644 crates/fj-kernel/src/algorithms/transform/sketch.rs create mode 100644 crates/fj-kernel/src/geometry/region.rs diff --git a/crates/fj-kernel/src/algorithms/approx/sketch.rs b/crates/fj-kernel/src/algorithms/approx/sketch.rs index 873257a01..7748fb92a 100644 --- a/crates/fj-kernel/src/algorithms/approx/sketch.rs +++ b/crates/fj-kernel/src/algorithms/approx/sketch.rs @@ -12,9 +12,9 @@ impl Approx for &Sketch { fn approx_with_cache( self, - tolerance: impl Into, - cache: &mut Self::Cache, + _tolerance: impl Into, + _cache: &mut Self::Cache, ) -> Self::Approximation { - self.faces().approx_with_cache(tolerance, cache) + todo!() } } diff --git a/crates/fj-kernel/src/algorithms/sweep/sketch.rs b/crates/fj-kernel/src/algorithms/sweep/sketch.rs index 4e8fb5789..45f8e977e 100644 --- a/crates/fj-kernel/src/algorithms/sweep/sketch.rs +++ b/crates/fj-kernel/src/algorithms/sweep/sketch.rs @@ -1,7 +1,7 @@ use fj_math::Vector; use crate::{ - objects::{Sketch, Solid}, + objects::{Sketch, Solid, Surface}, operations::Insert, services::Services, storage::Handle, @@ -9,7 +9,7 @@ use crate::{ use super::{Sweep, SweepCache}; -impl Sweep for Handle { +impl Sweep for (Handle, Handle) { type Swept = Handle; fn sweep_with_cache( @@ -21,7 +21,7 @@ impl Sweep for Handle { let path = path.into(); let mut shells = Vec::new(); - for face in self.faces().clone() { + for face in self.0.faces(self.1, services).clone() { let shell = face.sweep_with_cache(path, cache, services); shells.push(shell); } diff --git a/crates/fj-kernel/src/algorithms/transform/mod.rs b/crates/fj-kernel/src/algorithms/transform/mod.rs index 2157917f4..da46c29ef 100644 --- a/crates/fj-kernel/src/algorithms/transform/mod.rs +++ b/crates/fj-kernel/src/algorithms/transform/mod.rs @@ -4,7 +4,6 @@ mod cycle; mod edge; mod face; mod shell; -mod sketch; mod solid; mod surface; mod vertex; diff --git a/crates/fj-kernel/src/algorithms/transform/sketch.rs b/crates/fj-kernel/src/algorithms/transform/sketch.rs deleted file mode 100644 index 03b0e1387..000000000 --- a/crates/fj-kernel/src/algorithms/transform/sketch.rs +++ /dev/null @@ -1,21 +0,0 @@ -use fj_math::Transform; - -use crate::{objects::Sketch, services::Services}; - -use super::{TransformCache, TransformObject}; - -impl TransformObject for Sketch { - fn transform_with_cache( - self, - transform: &Transform, - services: &mut Services, - cache: &mut TransformCache, - ) -> Self { - let faces = - self.faces().into_iter().cloned().map(|face| { - face.transform_with_cache(transform, services, cache) - }); - - Self::new(faces) - } -} diff --git a/crates/fj-kernel/src/geometry/mod.rs b/crates/fj-kernel/src/geometry/mod.rs index af0cf08f9..6d34554b1 100644 --- a/crates/fj-kernel/src/geometry/mod.rs +++ b/crates/fj-kernel/src/geometry/mod.rs @@ -1,4 +1,5 @@ //! Types that are tied to objects, but aren't objects themselves pub mod curve; +pub mod region; pub mod surface; diff --git a/crates/fj-kernel/src/geometry/region.rs b/crates/fj-kernel/src/geometry/region.rs new file mode 100644 index 000000000..302a6ea1d --- /dev/null +++ b/crates/fj-kernel/src/geometry/region.rs @@ -0,0 +1,77 @@ +//! A single, continues 2d region +use fj_interop::mesh::Color; + +use crate::{ + objects::{Cycle, Face, Surface}, + operations::Insert, + services::Services, + storage::Handle, +}; + +/// A single, continues 2d region, may contain holes. Once applied to a +/// [`Surface`] becomes a [`Face`] +/// +/// Interior cycles must have the opposite winding of the exterior cycle, +/// meaning on the front side of the region, they must appear clockwise. This +/// means that all [`HalfEdge`]s that bound a `Region` have the interior of the +/// region on their left side (on the region's front side). +/// +/// [`HalfEdge`]: crate::objects::HalfEdge +#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct Region { + exterior: Handle, + interiors: Vec>, + color: Option, +} + +impl Region { + /// Construct an instance of `Region` + pub fn new( + exterior: Handle, + interiors: Vec>, + color: Option, + ) -> Self { + Self { + exterior, + interiors, + color, + } + } + + /// Access the cycle that bounds the region on the outside + pub fn exterior(&self) -> &Handle { + &self.exterior + } + + /// Access the cycles that bound the region on the inside + /// + /// Each of these cycles defines a hole in the region . + pub fn interiors(&self) -> impl Iterator> + '_ { + self.interiors.iter() + } + + /// Access all cycles of the region (both exterior and interior) + pub fn all_cycles(&self) -> impl Iterator> + '_ { + [self.exterior()].into_iter().chain(self.interiors()) + } + + /// Access the color of the region + pub fn color(&self) -> Option { + self.color + } + + /// Convert the 2D region to a 3D face, by applying it to a surface. + pub fn face( + &self, + surface: Handle, + services: &mut Services, + ) -> Handle { + let face: Face = Face::new( + surface, + self.exterior().clone(), + self.interiors().cloned(), + self.color, + ); + face.insert(services) + } +} diff --git a/crates/fj-kernel/src/objects/full/face.rs b/crates/fj-kernel/src/objects/full/face.rs index 1b22a0962..62ec2a906 100644 --- a/crates/fj-kernel/src/objects/full/face.rs +++ b/crates/fj-kernel/src/objects/full/face.rs @@ -4,6 +4,7 @@ use fj_interop::mesh::Color; use fj_math::Winding; use crate::{ + geometry::region::Region, objects::{Cycle, Surface}, storage::Handle, }; @@ -35,9 +36,7 @@ use crate::{ #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct Face { surface: Handle, - exterior: Handle, - interiors: Vec>, - color: Option, + region: Region, } impl Face { @@ -52,9 +51,7 @@ impl Face { Self { surface, - exterior, - interiors, - color, + region: Region::new(exterior, interiors, color), } } @@ -65,24 +62,24 @@ impl Face { /// Access the cycle that bounds the face on the outside pub fn exterior(&self) -> &Handle { - &self.exterior + &self.region.exterior() } /// Access the cycles that bound the face on the inside /// /// Each of these cycles defines a hole in the face. pub fn interiors(&self) -> impl Iterator> + '_ { - self.interiors.iter() + self.region.interiors() } /// Access all cycles of the face (both exterior and interior) pub fn all_cycles(&self) -> impl Iterator> + '_ { - [self.exterior()].into_iter().chain(self.interiors()) + self.region.all_cycles() } /// Access the color of the face pub fn color(&self) -> Option { - self.color + self.region.color() } /// Determine handed-ness of the face's front-side coordinate system diff --git a/crates/fj-kernel/src/objects/full/sketch.rs b/crates/fj-kernel/src/objects/full/sketch.rs index 2f049a473..69003e279 100644 --- a/crates/fj-kernel/src/objects/full/sketch.rs +++ b/crates/fj-kernel/src/objects/full/sketch.rs @@ -1,5 +1,9 @@ +use std::collections::BTreeSet; + use crate::{ - objects::{Face, FaceSet}, + geometry::region::Region, + objects::{FaceSet, Surface}, + services::Services, storage::Handle, }; @@ -11,19 +15,26 @@ use crate::{ /// currently validated. #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct Sketch { - faces: FaceSet, + regions: BTreeSet, } impl Sketch { /// Construct an empty instance of `Sketch` - pub fn new(faces: impl IntoIterator>) -> Self { + pub fn new(regions: impl IntoIterator) -> Self { Self { - faces: faces.into_iter().collect(), + regions: regions.into_iter().collect(), } } - /// Access the faces of the sketch - pub fn faces(&self) -> &FaceSet { - &self.faces + /// Apply the regions of the sketch to some [`Surface`] + pub fn faces( + &self, + surface: Handle, + services: &mut Services, + ) -> FaceSet { + self.regions + .iter() + .map(|r| r.face(surface.clone(), services)) + .collect() } } From 131757ade6a522951c27cbdd731d224e1385566c Mon Sep 17 00:00:00 2001 From: A-Walrus Date: Mon, 15 May 2023 19:43:21 +0300 Subject: [PATCH 2/3] Make clippy happy --- crates/fj-kernel/src/algorithms/sweep/sketch.rs | 2 +- crates/fj-kernel/src/objects/full/face.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/sweep/sketch.rs b/crates/fj-kernel/src/algorithms/sweep/sketch.rs index 45f8e977e..c50b06777 100644 --- a/crates/fj-kernel/src/algorithms/sweep/sketch.rs +++ b/crates/fj-kernel/src/algorithms/sweep/sketch.rs @@ -21,7 +21,7 @@ impl Sweep for (Handle, Handle) { let path = path.into(); let mut shells = Vec::new(); - for face in self.0.faces(self.1, services).clone() { + for face in self.0.faces(self.1, services) { let shell = face.sweep_with_cache(path, cache, services); shells.push(shell); } diff --git a/crates/fj-kernel/src/objects/full/face.rs b/crates/fj-kernel/src/objects/full/face.rs index 62ec2a906..2dd26e6da 100644 --- a/crates/fj-kernel/src/objects/full/face.rs +++ b/crates/fj-kernel/src/objects/full/face.rs @@ -62,7 +62,7 @@ impl Face { /// Access the cycle that bounds the face on the outside pub fn exterior(&self) -> &Handle { - &self.region.exterior() + self.region.exterior() } /// Access the cycles that bound the face on the inside From 5f6ca60884a5435d08338fcd6373edeb45fbd2da Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 16 May 2023 10:28:26 +0200 Subject: [PATCH 3/3] Fix typo in doc comment --- crates/fj-kernel/src/geometry/region.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/geometry/region.rs b/crates/fj-kernel/src/geometry/region.rs index 302a6ea1d..7731a44c0 100644 --- a/crates/fj-kernel/src/geometry/region.rs +++ b/crates/fj-kernel/src/geometry/region.rs @@ -8,7 +8,7 @@ use crate::{ storage::Handle, }; -/// A single, continues 2d region, may contain holes. Once applied to a +/// A single, continuous 2d region, may contain holes. Once applied to a /// [`Surface`] becomes a [`Face`] /// /// Interior cycles must have the opposite winding of the exterior cycle,