diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 766fb60ad..340b882fc 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -3,7 +3,9 @@ use fj_math::{Scalar, Vector}; use crate::{ algorithms::{reverse::Reverse, transform::TransformObject}, geometry::path::GlobalPath, + insert::Insert, objects::{Face, Objects, Shell}, + partial::{Partial, PartialObject, PartialShell}, services::Service, storage::Handle, }; @@ -74,7 +76,8 @@ impl Sweep for Handle { } } - Shell::builder().with_faces(faces).build(objects) + let faces = faces.into_iter().map(Partial::from).collect(); + PartialShell { faces }.build(objects).insert(objects) } } @@ -84,10 +87,9 @@ mod tests { use crate::{ algorithms::{reverse::Reverse, transform::TransformObject}, - builder::{FaceBuilder, HalfEdgeBuilder}, + builder::{FaceBuilder, HalfEdgeBuilder, SketchBuilder}, insert::Insert, - objects::Sketch, - partial::{PartialFace, PartialHalfEdge, PartialObject}, + partial::{PartialFace, PartialHalfEdge, PartialObject, PartialSketch}, services::Services, }; @@ -103,13 +105,11 @@ mod tests { let mut services = Services::new(); let surface = services.objects.surfaces.xy_plane(); - let solid = Sketch::builder() - .with_polygon_from_points( - surface.clone(), - TRIANGLE, - &mut services.objects, - ) + let mut sketch = PartialSketch::default(); + sketch.add_polygon_from_points(surface.clone(), TRIANGLE); + let solid = sketch .build(&mut services.objects) + .insert(&mut services.objects) .sweep(UP, &mut services.objects); let mut bottom = PartialFace::default(); @@ -156,13 +156,11 @@ mod tests { let mut services = Services::new(); let surface = services.objects.surfaces.xy_plane(); - let solid = Sketch::builder() - .with_polygon_from_points( - surface.clone(), - TRIANGLE, - &mut services.objects, - ) + let mut sketch = PartialSketch::default(); + sketch.add_polygon_from_points(surface.clone(), TRIANGLE); + let solid = sketch .build(&mut services.objects) + .insert(&mut services.objects) .sweep(DOWN, &mut services.objects); let mut bottom = PartialFace::default(); diff --git a/crates/fj-kernel/src/algorithms/sweep/sketch.rs b/crates/fj-kernel/src/algorithms/sweep/sketch.rs index ca57c39c5..e77bca1b1 100644 --- a/crates/fj-kernel/src/algorithms/sweep/sketch.rs +++ b/crates/fj-kernel/src/algorithms/sweep/sketch.rs @@ -1,7 +1,9 @@ use fj_math::Vector; use crate::{ + insert::Insert, objects::{Objects, Sketch, Solid}, + partial::{Partial, PartialObject, PartialSolid}, services::Service, storage::Handle, }; @@ -25,6 +27,7 @@ impl Sweep for Handle { shells.push(shell); } - Solid::builder().with_shells(shells).build(objects) + let shells = shells.into_iter().map(Partial::from).collect(); + PartialSolid { shells }.build(objects).insert(objects) } } diff --git a/crates/fj-kernel/src/builder/mod.rs b/crates/fj-kernel/src/builder/mod.rs index 7a7b4e70a..ee3bb86a0 100644 --- a/crates/fj-kernel/src/builder/mod.rs +++ b/crates/fj-kernel/src/builder/mod.rs @@ -1,17 +1,13 @@ //! API for building objects -// These are the old-style builders that need to be transferred to the partial -// object API. Issue: -// https://github.com/hannobraun/Fornjot/issues/1147 -mod shell; -mod sketch; -mod solid; - // These are new-style builders that build on top of the partial object API. mod curve; mod cycle; mod edge; mod face; +mod shell; +mod sketch; +mod solid; mod surface; mod vertex; diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs index 26615c48b..b3bc62629 100644 --- a/crates/fj-kernel/src/builder/shell.rs +++ b/crates/fj-kernel/src/builder/shell.rs @@ -9,37 +9,25 @@ use crate::{ builder::{ FaceBuilder, HalfEdgeBuilder, SurfaceBuilder, SurfaceVertexBuilder, }, - insert::Insert, - objects::{Face, FaceSet, HalfEdge, Objects, Shell}, + objects::{HalfEdge, Objects}, partial::{ - Partial, PartialCycle, PartialFace, PartialHalfEdge, PartialObject, + Partial, PartialCycle, PartialFace, PartialHalfEdge, PartialShell, PartialSurface, PartialSurfaceVertex, }, services::Service, - storage::Handle, }; -/// API for building a [`Shell`] -/// -/// Also see [`Shell::builder`]. -pub struct ShellBuilder { - /// The faces that make up the [`Shell`] - pub faces: FaceSet, +/// Builder API for [`PartialShell`] +pub trait ShellBuilder { + /// Create a cube from the length of its edges + fn create_cube_from_edge_length( + edge_length: impl Into, + objects: &mut Service, + ) -> Self; } -impl ShellBuilder { - /// Build the [`Shell`] with the provided faces - pub fn with_faces( - mut self, - faces: impl IntoIterator>, - ) -> Self { - self.faces.extend(faces); - self - } - - /// Create a cube from the length of its edges - pub fn with_cube_from_edge_length( - mut self, +impl ShellBuilder for PartialShell { + fn create_cube_from_edge_length( edge_length: impl Into, objects: &mut Service, ) -> Self { @@ -49,7 +37,7 @@ impl ShellBuilder { const Z: Scalar = Scalar::ZERO; let h = edge_length / 2.; - let bottom = { + let bottom_face = { let surface = objects.surfaces.xy_plane().translate([Z, Z, -h], objects); @@ -62,8 +50,8 @@ impl ShellBuilder { face }; - let (sides, top_edges) = { - let surfaces = bottom + let (side_faces, top_edges) = { + let side_surfaces = bottom_face .exterior .read() .half_edges @@ -79,18 +67,17 @@ impl ShellBuilder { }); let c = a + [Z, Z, edge_length]; - Partial::from_partial(PartialSurface::plane_from_points([ - a, b, c, - ])) + let surface = PartialSurface::plane_from_points([a, b, c]); + Partial::from_partial(surface) }) .collect::>(); - let bottoms = bottom + let bottom_edges = bottom_face .exterior .read() .half_edges .iter() - .zip(&surfaces) + .zip(&side_surfaces) .map(|(half_edge, surface)| { let global_edge = half_edge.read().global_form.clone(); @@ -119,10 +106,10 @@ impl ShellBuilder { }) .collect::>(); - let sides_up = bottoms + let side_edges_up = bottom_edges .clone() .into_iter() - .zip(&surfaces) + .zip(&side_surfaces) .map(|(bottom, surface): (Partial, _)| { let from_surface = { let [_, from] = &bottom.read().vertices; @@ -153,15 +140,15 @@ impl ShellBuilder { }) .collect::>(); - let sides_down = { - let mut sides_up_prev = sides_up.clone(); + let side_edges_down = { + let mut sides_up_prev = side_edges_up.clone(); sides_up_prev.rotate_right(1); - bottoms + bottom_edges .clone() .into_iter() .zip(sides_up_prev) - .zip(&surfaces) + .zip(&side_surfaces) .map( |((bottom, side_up_prev), surface): ( (_, Partial), @@ -215,10 +202,10 @@ impl ShellBuilder { .collect::>() }; - let tops = sides_up + let top_edges = side_edges_up .clone() .into_iter() - .zip(sides_down.clone()) + .zip(side_edges_down.clone()) .map(|(side_up, side_down): (_, Partial)| { let [_, from] = side_up.read().vertices.clone(); let [to, _] = side_down.read().vertices.clone(); @@ -248,11 +235,11 @@ impl ShellBuilder { }) .collect::>(); - let sides = bottoms + let side_faces = bottom_edges .into_iter() - .zip(sides_up) - .zip(tops.clone()) - .zip(sides_down) + .zip(side_edges_up) + .zip(top_edges.clone()) + .zip(side_edges_down) .map(|(((bottom, side_up), top), side_down)| { let mut cycle = PartialCycle::default(); cycle.half_edges.extend([bottom, side_up, top, side_down]); @@ -264,10 +251,10 @@ impl ShellBuilder { }) .collect::>(); - (sides, tops) + (side_faces, top_edges) }; - let top = { + let top_face = { let surface = Partial::from( objects.surfaces.xy_plane().translate([Z, Z, h], objects), ); @@ -340,19 +327,13 @@ impl ShellBuilder { } }; - self.faces.extend( - [bottom] + PartialShell { + faces: [bottom_face] .into_iter() - .chain(sides) - .chain([top]) - .map(|face| face.build(objects).insert(objects)), - ); - - self - } - - /// Build the [`Shell`] - pub fn build(self, objects: &mut Service) -> Handle { - Shell::new(self.faces).insert(objects) + .chain(side_faces) + .chain([top_face]) + .map(Partial::from_partial) + .collect(), + } } } diff --git a/crates/fj-kernel/src/builder/sketch.rs b/crates/fj-kernel/src/builder/sketch.rs index 20682748b..1deaee09a 100644 --- a/crates/fj-kernel/src/builder/sketch.rs +++ b/crates/fj-kernel/src/builder/sketch.rs @@ -1,50 +1,31 @@ use fj_math::Point; use crate::{ - insert::Insert, - objects::{Face, FaceSet, Objects, Sketch, Surface}, - partial::{PartialFace, PartialObject}, - services::Service, - storage::Handle, + objects::Surface, + partial::{Partial, PartialFace, PartialSketch}, }; use super::FaceBuilder; -/// API for building a [`Sketch`] -/// -/// Also see [`Sketch::builder`]. -pub struct SketchBuilder { - /// The faces that make up the [`Sketch`] - pub faces: FaceSet, +/// Builder API for [`PartialSketch`] +pub trait SketchBuilder { + /// Add a polygon to the sketch, created from the provided points + fn add_polygon_from_points( + &mut self, + surface: impl Into>, + points: impl IntoIterator>>, + ); } -impl SketchBuilder { - /// Build the [`Sketch`] with the provided faces - pub fn with_faces( - mut self, - faces: impl IntoIterator>, - ) -> Self { - self.faces.extend(faces); - self - } - - /// Construct a polygon from a list of points - pub fn with_polygon_from_points( - mut self, - surface: Handle, +impl SketchBuilder for PartialSketch { + fn add_polygon_from_points( + &mut self, + surface: impl Into>, points: impl IntoIterator>>, - objects: &mut Service, - ) -> Self { + ) { let mut face = PartialFace::default(); face.with_exterior_polygon_from_points(surface, points); - let face = face.build(objects).insert(objects); - - self.faces.extend([face]); - self - } - /// Build the [`Sketch`] - pub fn build(self, objects: &mut Service) -> Handle { - Sketch::new(self.faces).insert(objects) + self.faces.extend([Partial::from_partial(face)]); } } diff --git a/crates/fj-kernel/src/builder/solid.rs b/crates/fj-kernel/src/builder/solid.rs index 17c34a52c..6e76002ab 100644 --- a/crates/fj-kernel/src/builder/solid.rs +++ b/crates/fj-kernel/src/builder/solid.rs @@ -1,47 +1,31 @@ -use std::collections::BTreeSet; - use fj_math::Scalar; use crate::{ - insert::Insert, - objects::{Objects, Shell, Solid}, + objects::Objects, + partial::{Partial, PartialShell, PartialSolid}, services::Service, - storage::Handle, }; -/// API for building a [`Solid`] -/// -/// Also see [`Solid::builder`]. -pub struct SolidBuilder { - /// The shells that make up the [`Solid`] - pub shells: BTreeSet>, -} - -impl SolidBuilder { - /// Build the [`Solid`] with the provided shells - pub fn with_shells( - mut self, - shells: impl IntoIterator>, - ) -> Self { - self.shells.extend(shells); - self - } +use super::ShellBuilder; - /// Create a cube from the length of its edges - pub fn with_cube_from_edge_length( - mut self, +/// Builder API for [`PartialSolid`] +pub trait SolidBuilder { + /// Add a cube with the given edge length to the solid + fn with_cube_from_edge_length( + &mut self, edge_length: impl Into, objects: &mut Service, - ) -> Self { - let shell = Shell::builder() - .with_cube_from_edge_length(edge_length, objects) - .build(objects); - self.shells.insert(shell); - self - } + ); +} - /// Build the [`Solid`] - pub fn build(self, objects: &mut Service) -> Handle { - Solid::new(self.shells).insert(objects) +impl SolidBuilder for PartialSolid { + fn with_cube_from_edge_length( + &mut self, + edge_length: impl Into, + objects: &mut Service, + ) { + let shell = + PartialShell::create_cube_from_edge_length(edge_length, objects); + self.shells.push(Partial::from_partial(shell)); } } diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index f78c20565..0edb14bf2 100644 --- a/crates/fj-kernel/src/iter.rs +++ b/crates/fj-kernel/src/iter.rs @@ -360,15 +360,15 @@ impl Iterator for Iter { #[cfg(test)] mod tests { use crate::{ - builder::{CurveBuilder, CycleBuilder, FaceBuilder, HalfEdgeBuilder}, - insert::Insert, - objects::{ - GlobalCurve, GlobalVertex, Objects, Shell, Sketch, Solid, - SurfaceVertex, Vertex, + builder::{ + CurveBuilder, CycleBuilder, FaceBuilder, HalfEdgeBuilder, + ShellBuilder, SolidBuilder, }, + insert::Insert, + objects::{GlobalCurve, GlobalVertex, Objects, SurfaceVertex, Vertex}, partial::{ Partial, PartialCurve, PartialCycle, PartialFace, PartialHalfEdge, - PartialObject, + PartialObject, PartialShell, PartialSketch, PartialSolid, }, services::Services, }; @@ -529,9 +529,12 @@ mod tests { fn shell() { let mut services = Services::new(); - let object = Shell::builder() - .with_cube_from_edge_length(1., &mut services.objects) - .build(&mut services.objects); + let object = PartialShell::create_cube_from_edge_length( + 1., + &mut services.objects, + ) + .build(&mut services.objects) + .insert(&mut services.objects); assert_eq!(24, object.curve_iter().count()); assert_eq!(6, object.cycle_iter().count()); @@ -556,12 +559,10 @@ mod tests { surface, [[0., 0.], [1., 0.], [0., 1.]], ); - let face = face - .build(&mut services.objects) - .insert(&mut services.objects); - let object = Sketch::builder() - .with_faces([face]) - .build(&mut services.objects); + let object = PartialSketch { + faces: vec![Partial::from_partial(face)], + } + .build(&mut services.objects); assert_eq!(3, object.curve_iter().count()); assert_eq!(1, object.cycle_iter().count()); @@ -580,9 +581,11 @@ mod tests { fn solid() { let mut services = Services::new(); - let object = Solid::builder() - .with_cube_from_edge_length(1., &mut services.objects) - .build(&mut services.objects); + let object = { + let mut solid = PartialSolid::default(); + solid.with_cube_from_edge_length(1., &mut services.objects); + solid.build(&mut services.objects) + }; assert_eq!(24, object.curve_iter().count()); assert_eq!(6, object.cycle_iter().count()); diff --git a/crates/fj-kernel/src/objects/full/shell.rs b/crates/fj-kernel/src/objects/full/shell.rs index 4c280da2f..0fe1fb2e4 100644 --- a/crates/fj-kernel/src/objects/full/shell.rs +++ b/crates/fj-kernel/src/objects/full/shell.rs @@ -1,5 +1,4 @@ use crate::{ - builder::ShellBuilder, objects::{Face, FaceSet}, storage::Handle, }; @@ -16,13 +15,6 @@ pub struct Shell { } impl Shell { - /// Build a `Shell` using [`ShellBuilder`] - pub fn builder() -> ShellBuilder { - ShellBuilder { - faces: FaceSet::new(), - } - } - /// Construct an empty instance of `Shell` pub fn new(faces: impl IntoIterator>) -> Self { Self { diff --git a/crates/fj-kernel/src/objects/full/sketch.rs b/crates/fj-kernel/src/objects/full/sketch.rs index 3499f41e1..2f049a473 100644 --- a/crates/fj-kernel/src/objects/full/sketch.rs +++ b/crates/fj-kernel/src/objects/full/sketch.rs @@ -1,5 +1,4 @@ use crate::{ - builder::SketchBuilder, objects::{Face, FaceSet}, storage::Handle, }; @@ -16,13 +15,6 @@ pub struct Sketch { } impl Sketch { - /// Build a `Sketch` using [`SketchBuilder`] - pub fn builder() -> SketchBuilder { - SketchBuilder { - faces: FaceSet::new(), - } - } - /// Construct an empty instance of `Sketch` pub fn new(faces: impl IntoIterator>) -> Self { Self { diff --git a/crates/fj-kernel/src/objects/full/solid.rs b/crates/fj-kernel/src/objects/full/solid.rs index f82c98001..dfe53c885 100644 --- a/crates/fj-kernel/src/objects/full/solid.rs +++ b/crates/fj-kernel/src/objects/full/solid.rs @@ -1,7 +1,6 @@ use std::collections::BTreeSet; use crate::{ - builder::SolidBuilder, objects::{Face, Shell}, storage::Handle, }; @@ -18,13 +17,6 @@ pub struct Solid { } impl Solid { - /// Build a `Solid` using [`SolidBuilder`] - pub fn builder() -> SolidBuilder { - SolidBuilder { - shells: BTreeSet::new(), - } - } - /// Construct an empty instance of `Solid` pub fn new(shells: impl IntoIterator>) -> Self { Self { diff --git a/crates/fj-operations/src/difference_2d.rs b/crates/fj-operations/src/difference_2d.rs index d10a52131..300cd1c76 100644 --- a/crates/fj-operations/src/difference_2d.rs +++ b/crates/fj-operations/src/difference_2d.rs @@ -6,7 +6,7 @@ use fj_kernel::{ insert::Insert, iter::ObjectIters, objects::{Objects, Sketch}, - partial::{Partial, PartialFace, PartialObject}, + partial::{Partial, PartialFace, PartialObject, PartialSketch}, services::Service, }; use fj_math::Aabb; @@ -87,10 +87,10 @@ impl Shape for fj::Difference2d { interiors, color: Some(Color(self.color())), }; - faces.push(face.build(objects).insert(objects)); + faces.push(Partial::from_partial(face)); } - let difference = Sketch::builder().with_faces(faces).build(objects); + let difference = PartialSketch { faces }.build(objects).insert(objects); difference.deref().clone() } diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index ef645af26..742d58dd1 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -7,6 +7,7 @@ use fj_kernel::{ objects::{Objects, Sketch}, partial::{ Partial, PartialCycle, PartialFace, PartialHalfEdge, PartialObject, + PartialSketch, }, services::Service, }; @@ -46,12 +47,11 @@ impl Shape for fj::Sketch { half_edges: vec![half_edge], }); - let face = PartialFace { + PartialFace { exterior: cycle, color: Some(Color(self.color())), ..Default::default() - }; - face.build(objects).insert(objects) + } } fj::Chain::PolyChain(poly_chain) => { let points = poly_chain @@ -64,11 +64,15 @@ impl Shape for fj::Sketch { face.with_exterior_polygon_from_points(surface, points); face.color = Some(Color(self.color())); - face.build(objects).insert(objects) + face } }; - let sketch = Sketch::builder().with_faces([face]).build(objects); + let sketch = PartialSketch { + faces: vec![Partial::from_partial(face)], + } + .build(objects) + .insert(objects); sketch.deref().clone() }