From dad9b8db73746dd606f8f0860d17cb1053d08ad6 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:05:20 +0100 Subject: [PATCH 01/22] Move `FaceBuilder` to `partial::objects` This is the first step towards integrating `Face` into the partial object API. --- crates/fj-kernel/src/builder/mod.rs | 2 -- crates/fj-kernel/src/objects/face.rs | 2 +- crates/fj-kernel/src/partial/mod.rs | 1 + crates/fj-kernel/src/{builder => partial/objects}/face.rs | 3 +-- crates/fj-kernel/src/partial/objects/mod.rs | 1 + 5 files changed, 4 insertions(+), 5 deletions(-) rename crates/fj-kernel/src/{builder => partial/objects}/face.rs (99%) diff --git a/crates/fj-kernel/src/builder/mod.rs b/crates/fj-kernel/src/builder/mod.rs index 9dafd5326..b6cf74d99 100644 --- a/crates/fj-kernel/src/builder/mod.rs +++ b/crates/fj-kernel/src/builder/mod.rs @@ -3,7 +3,6 @@ // 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 face; mod shell; mod sketch; mod solid; @@ -18,7 +17,6 @@ pub use self::{ curve::CurveBuilder, cycle::CycleBuilder, edge::{GlobalEdgeBuilder, HalfEdgeBuilder}, - face::FaceBuilder, shell::ShellBuilder, sketch::SketchBuilder, solid::SolidBuilder, diff --git a/crates/fj-kernel/src/objects/face.rs b/crates/fj-kernel/src/objects/face.rs index 649c3d571..0439070dd 100644 --- a/crates/fj-kernel/src/objects/face.rs +++ b/crates/fj-kernel/src/objects/face.rs @@ -3,7 +3,7 @@ use std::collections::{btree_set, BTreeSet}; use fj_interop::mesh::Color; use fj_math::Winding; -use crate::{builder::FaceBuilder, storage::Handle}; +use crate::{partial::FaceBuilder, storage::Handle}; use super::{Cycle, Objects, Surface}; diff --git a/crates/fj-kernel/src/partial/mod.rs b/crates/fj-kernel/src/partial/mod.rs index 172c05cef..a19b0fb37 100644 --- a/crates/fj-kernel/src/partial/mod.rs +++ b/crates/fj-kernel/src/partial/mod.rs @@ -45,6 +45,7 @@ pub use self::{ curve::{PartialCurve, PartialGlobalCurve}, cycle::PartialCycle, edge::{PartialGlobalEdge, PartialHalfEdge}, + face::FaceBuilder, vertex::{PartialGlobalVertex, PartialSurfaceVertex, PartialVertex}, }, traits::{HasPartial, Partial}, diff --git a/crates/fj-kernel/src/builder/face.rs b/crates/fj-kernel/src/partial/objects/face.rs similarity index 99% rename from crates/fj-kernel/src/builder/face.rs rename to crates/fj-kernel/src/partial/objects/face.rs index 0f217d409..2fc4f93bf 100644 --- a/crates/fj-kernel/src/builder/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -2,13 +2,12 @@ use fj_interop::mesh::Color; use fj_math::Point; use crate::{ + builder::CycleBuilder, objects::{Cycle, Face, Objects, Surface}, partial::HasPartial, storage::Handle, }; -use super::CycleBuilder; - /// API for building a [`Face`] /// /// Also see [`Face::builder`]. diff --git a/crates/fj-kernel/src/partial/objects/mod.rs b/crates/fj-kernel/src/partial/objects/mod.rs index 751063c23..3a31e58eb 100644 --- a/crates/fj-kernel/src/partial/objects/mod.rs +++ b/crates/fj-kernel/src/partial/objects/mod.rs @@ -1,6 +1,7 @@ pub mod curve; pub mod cycle; pub mod edge; +pub mod face; pub mod vertex; use crate::{ From 398c73747dc3cbd8a18900edea3a7c528289db4c Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:24:36 +0100 Subject: [PATCH 02/22] Return `Result` from `FaceBuilder::build` --- .../src/algorithms/intersect/curve_face.rs | 2 +- .../src/algorithms/intersect/face_face.rs | 8 +-- .../src/algorithms/intersect/face_point.rs | 50 +++++++++++++------ .../src/algorithms/intersect/ray_face.rs | 20 ++++---- .../fj-kernel/src/algorithms/reverse/face.rs | 4 +- crates/fj-kernel/src/algorithms/sweep/edge.rs | 6 +-- crates/fj-kernel/src/algorithms/sweep/face.rs | 8 +-- .../src/algorithms/transform/face.rs | 4 +- .../src/algorithms/triangulate/mod.rs | 6 +-- crates/fj-kernel/src/builder/shell.rs | 7 ++- crates/fj-kernel/src/builder/sketch.rs | 3 +- crates/fj-kernel/src/iter.rs | 6 ++- crates/fj-kernel/src/partial/objects/face.rs | 12 +++-- crates/fj-kernel/src/validate/face.rs | 4 +- crates/fj-operations/src/difference_2d.rs | 2 +- crates/fj-operations/src/sketch.rs | 4 +- 16 files changed, 88 insertions(+), 58 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs index 9ede7f995..62de03a96 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs @@ -187,7 +187,7 @@ mod tests { .with_surface(surface) .with_exterior_polygon_from_points(exterior) .with_interior_polygon_from_points(interior) - .build(); + .build()?; let expected = CurveFaceIntersection::from_intervals([[[1.], [2.]], [[4.], [5.]]]); diff --git a/crates/fj-kernel/src/algorithms/intersect/face_face.rs b/crates/fj-kernel/src/algorithms/intersect/face_face.rs index ac9e2776c..b8467e62c 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_face.rs @@ -86,12 +86,12 @@ mod tests { [1., 2.], ]; let [a, b] = [objects.surfaces.xy_plane(), objects.surfaces.xz_plane()] - .map(|surface| { + .try_map_ext(|surface| { Face::builder(&objects) .with_surface(surface) .with_exterior_polygon_from_points(points) .build() - }); + })?; let intersection = FaceFaceIntersection::compute([&a, &b], &objects)?; @@ -113,12 +113,12 @@ mod tests { ]; let surfaces = [objects.surfaces.xy_plane(), objects.surfaces.xz_plane()]; - let [a, b] = surfaces.clone().map(|surface| { + let [a, b] = surfaces.clone().try_map_ext(|surface| { Face::builder(&objects) .with_surface(surface) .with_exterior_polygon_from_points(points) .build() - }); + })?; let intersection = FaceFaceIntersection::compute([&a, &b], &objects)?; diff --git a/crates/fj-kernel/src/algorithms/intersect/face_point.rs b/crates/fj-kernel/src/algorithms/intersect/face_point.rs index 639dde796..ba9b520e4 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_point.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_point.rs @@ -141,29 +141,31 @@ mod tests { }; #[test] - fn point_is_outside_face() { + fn point_is_outside_face() -> anyhow::Result<()> { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); let face = Face::builder(&objects) .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 1.], [0., 2.]]) - .build(); + .build()?; let point = Point::from([2., 1.]); let intersection = (&face, &point).intersect(); assert_eq!(intersection, None); + + Ok(()) } #[test] - fn ray_hits_vertex_while_passing_outside() { + fn ray_hits_vertex_while_passing_outside() -> anyhow::Result<()> { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); let face = Face::builder(&objects) .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [2., 1.], [0., 2.]]) - .build(); + .build()?; let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -171,17 +173,19 @@ mod tests { intersection, Some(FacePointIntersection::PointIsInsideFace) ); + + Ok(()) } #[test] - fn ray_hits_vertex_at_cycle_seam() { + fn ray_hits_vertex_at_cycle_seam() -> anyhow::Result<()> { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); let face = Face::builder(&objects) .with_surface(surface) .with_exterior_polygon_from_points([[4., 2.], [0., 4.], [0., 0.]]) - .build(); + .build()?; let point = Point::from([1., 2.]); let intersection = (&face, &point).intersect(); @@ -189,10 +193,12 @@ mod tests { intersection, Some(FacePointIntersection::PointIsInsideFace) ); + + Ok(()) } #[test] - fn ray_hits_vertex_while_staying_inside() { + fn ray_hits_vertex_while_staying_inside() -> anyhow::Result<()> { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); @@ -204,7 +210,7 @@ mod tests { [3., 0.], [3., 4.], ]) - .build(); + .build()?; let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -212,10 +218,13 @@ mod tests { intersection, Some(FacePointIntersection::PointIsInsideFace) ); + + Ok(()) } #[test] - fn ray_hits_parallel_edge_and_leaves_face_at_vertex() { + fn ray_hits_parallel_edge_and_leaves_face_at_vertex() -> anyhow::Result<()> + { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); @@ -227,7 +236,7 @@ mod tests { [3., 1.], [0., 2.], ]) - .build(); + .build()?; let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -235,10 +244,13 @@ mod tests { intersection, Some(FacePointIntersection::PointIsInsideFace) ); + + Ok(()) } #[test] - fn ray_hits_parallel_edge_and_does_not_leave_face_there() { + fn ray_hits_parallel_edge_and_does_not_leave_face_there( + ) -> anyhow::Result<()> { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); @@ -251,7 +263,7 @@ mod tests { [4., 0.], [4., 5.], ]) - .build(); + .build()?; let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -259,17 +271,19 @@ mod tests { intersection, Some(FacePointIntersection::PointIsInsideFace) ); + + Ok(()) } #[test] - fn point_is_coincident_with_edge() { + fn point_is_coincident_with_edge() -> anyhow::Result<()> { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); let face = Face::builder(&objects) .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [2., 0.], [0., 1.]]) - .build(); + .build()?; let point = Point::from([1., 0.]); let intersection = (&face, &point).intersect(); @@ -286,17 +300,19 @@ mod tests { intersection, Some(FacePointIntersection::PointIsOnEdge(edge.clone())) ); + + Ok(()) } #[test] - fn point_is_coincident_with_vertex() { + fn point_is_coincident_with_vertex() -> anyhow::Result<()> { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); let face = Face::builder(&objects) .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) - .build(); + .build()?; let point = Point::from([1., 0.]); let intersection = (&face, &point).intersect(); @@ -311,5 +327,7 @@ mod tests { intersection, Some(FacePointIntersection::PointIsOnVertex(vertex.clone())) ); + + Ok(()) } } diff --git a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs index ada935ad9..13daca4d1 100644 --- a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs @@ -171,7 +171,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build() + .build()? .translate([-1., 0., 0.], &objects)?; assert_eq!((&ray, &face).intersect(), None); @@ -193,7 +193,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build() + .build()? .translate([1., 0., 0.], &objects)?; assert_eq!( @@ -218,7 +218,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build() + .build()? .translate([0., 0., 2.], &objects)?; assert_eq!((&ray, &face).intersect(), None); @@ -240,7 +240,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build() + .build()? .translate([1., 1., 0.], &objects)?; let edge = face @@ -273,7 +273,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build() + .build()? .translate([1., 1., 1.], &objects)?; let vertex = face @@ -290,7 +290,7 @@ mod tests { } #[test] - fn ray_is_parallel_to_surface_and_hits() { + fn ray_is_parallel_to_surface_and_hits() -> anyhow::Result<()> { let objects = Objects::new(); let ray = HorizontalRayToTheRight::from([0., 0., 0.]); @@ -304,12 +304,14 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build(); + .build()?; assert_eq!( (&ray, &face).intersect(), Some(RayFaceIntersection::RayHitsFaceAndAreParallel) - ) + ); + + Ok(()) } #[test] @@ -327,7 +329,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build() + .build()? .translate([0., 0., 1.], &objects)?; assert_eq!((&ray, &face).intersect(), None); diff --git a/crates/fj-kernel/src/algorithms/reverse/face.rs b/crates/fj-kernel/src/algorithms/reverse/face.rs index e96edeeaa..9fae7ad8a 100644 --- a/crates/fj-kernel/src/algorithms/reverse/face.rs +++ b/crates/fj-kernel/src/algorithms/reverse/face.rs @@ -14,10 +14,10 @@ impl Reverse for Handle { .map(|cycle| cycle.clone().reverse(objects)) .collect::, _>>()?; - Ok(Face::builder(objects) + Face::builder(objects) .with_exterior(exterior) .with_interiors(interiors) .with_color(self.color()) - .build()) + .build() } } diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index a4c09f01e..24097fddc 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -175,10 +175,10 @@ impl Sweep for (Handle, Color) { objects.cycles.insert(Cycle::new(edges))? }; - Ok(Face::builder(objects) + Face::builder(objects) .with_exterior(cycle) .with_color(color) - .build()) + .build() } } @@ -256,7 +256,7 @@ mod tests { .cycles .insert(Cycle::new([bottom, side_up, top, side_down]))?; - Face::builder(&objects).with_exterior(cycle).build() + Face::builder(&objects).with_exterior(cycle).build()? }; assert_eq!(face, expected_face); diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index eb44fc87c..52299fa2e 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -110,12 +110,12 @@ mod tests { let bottom = Face::builder(&objects) .with_surface(surface.clone()) .with_exterior_polygon_from_points(TRIANGLE) - .build() + .build()? .reverse(&objects)?; let top = Face::builder(&objects) .with_surface(surface.translate(UP, &objects)?) .with_exterior_polygon_from_points(TRIANGLE) - .build(); + .build()?; assert!(solid.find_face(&bottom).is_some()); assert!(solid.find_face(&top).is_some()); @@ -154,12 +154,12 @@ mod tests { let bottom = Face::builder(&objects) .with_surface(surface.clone().translate(DOWN, &objects)?) .with_exterior_polygon_from_points(TRIANGLE) - .build() + .build()? .reverse(&objects)?; let top = Face::builder(&objects) .with_surface(surface) .with_exterior_polygon_from_points(TRIANGLE) - .build(); + .build()?; assert!(solid.find_face(&bottom).is_some()); assert!(solid.find_face(&top).is_some()); diff --git a/crates/fj-kernel/src/algorithms/transform/face.rs b/crates/fj-kernel/src/algorithms/transform/face.rs index 249f32700..7f18a45db 100644 --- a/crates/fj-kernel/src/algorithms/transform/face.rs +++ b/crates/fj-kernel/src/algorithms/transform/face.rs @@ -35,11 +35,11 @@ impl TransformObject for Handle { let color = self.color(); - Ok(Face::builder(objects) + Face::builder(objects) .with_exterior(exterior) .with_interiors(interiors) .with_color(color) - .build()) + .build() } } diff --git a/crates/fj-kernel/src/algorithms/triangulate/mod.rs b/crates/fj-kernel/src/algorithms/triangulate/mod.rs index 73b68039e..2610b0f2b 100644 --- a/crates/fj-kernel/src/algorithms/triangulate/mod.rs +++ b/crates/fj-kernel/src/algorithms/triangulate/mod.rs @@ -103,7 +103,7 @@ mod tests { let face = Face::builder(&objects) .with_surface(surface) .with_exterior_polygon_from_points([a, b, c, d]) - .build(); + .build()?; let a = Point::from(a).to_xyz(); let b = Point::from(b).to_xyz(); @@ -139,7 +139,7 @@ mod tests { .with_surface(surface.clone()) .with_exterior_polygon_from_points([a, b, c, d]) .with_interior_polygon_from_points([e, f, g, h]) - .build(); + .build()?; let triangles = triangulate(face)?; @@ -199,7 +199,7 @@ mod tests { let face = Face::builder(&objects) .with_surface(surface.clone()) .with_exterior_polygon_from_points([a, b, c, d, e]) - .build(); + .build()?; let triangles = triangulate(face)?; diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs index 9c6d1629b..b00e6decc 100644 --- a/crates/fj-kernel/src/builder/shell.rs +++ b/crates/fj-kernel/src/builder/shell.rs @@ -63,6 +63,7 @@ impl<'a> ShellBuilder<'a> { [-h, h], ]) .build() + .unwrap() }; let (sides, top_edges) = { @@ -193,7 +194,10 @@ impl<'a> ShellBuilder<'a> { .build(self.objects) .unwrap(); - Face::builder(self.objects).with_exterior(cycle).build() + Face::builder(self.objects) + .with_exterior(cycle) + .build() + .unwrap() }); (sides, tops) @@ -264,6 +268,7 @@ impl<'a> ShellBuilder<'a> { self.objects.cycles.insert(Cycle::new(edges)).unwrap(), ) .build() + .unwrap() }; self.faces.extend([bottom]); diff --git a/crates/fj-kernel/src/builder/sketch.rs b/crates/fj-kernel/src/builder/sketch.rs index e0aef7c48..634258013 100644 --- a/crates/fj-kernel/src/builder/sketch.rs +++ b/crates/fj-kernel/src/builder/sketch.rs @@ -47,7 +47,8 @@ impl<'a> SketchBuilder<'a> { self.faces.extend([Face::builder(self.objects) .with_surface(surface.clone()) .with_exterior_polygon_from_points(points) - .build()]); + .build() + .unwrap()]); self } diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index c27d3fbaf..a3933f2d7 100644 --- a/crates/fj-kernel/src/iter.rs +++ b/crates/fj-kernel/src/iter.rs @@ -528,14 +528,14 @@ mod tests { } #[test] - fn sketch() { + fn sketch() -> anyhow::Result<()> { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); let face = Face::builder(&objects) .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) - .build(); + .build()?; let object = Sketch::builder(&objects).with_faces([face]).build(); assert_eq!(3, object.curve_iter().count()); @@ -549,6 +549,8 @@ mod tests { assert_eq!(0, object.solid_iter().count()); assert_eq!(1, object.surface_iter().count()); assert_eq!(6, object.vertex_iter().count()); + + Ok(()) } #[test] diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index 2fc4f93bf..aa87682cd 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -6,6 +6,7 @@ use crate::{ objects::{Cycle, Face, Objects, Surface}, partial::HasPartial, storage::Handle, + validate::ValidationError, }; /// API for building a [`Face`] @@ -100,15 +101,16 @@ impl<'a> FaceBuilder<'a> { } /// Construct a polygon from a list of points - pub fn build(self) -> Handle { + pub fn build(self) -> Result, ValidationError> { let exterior = self .exterior .expect("Can't build `Face` without exterior cycle"); let color = self.color.unwrap_or_default(); - self.objects - .faces - .insert(Face::new(exterior, self.interiors, color)) - .unwrap() + Ok(self.objects.faces.insert(Face::new( + exterior, + self.interiors, + color, + ))?) } } diff --git a/crates/fj-kernel/src/validate/face.rs b/crates/fj-kernel/src/validate/face.rs index 166afb827..377878801 100644 --- a/crates/fj-kernel/src/validate/face.rs +++ b/crates/fj-kernel/src/validate/face.rs @@ -119,7 +119,7 @@ mod tests { .with_surface(objects.surfaces.xy_plane()) .with_exterior_polygon_from_points([[0., 0.], [3., 0.], [0., 3.]]) .with_interior_polygon_from_points([[1., 1.], [1., 2.], [2., 1.]]) - .build(); + .build()?; let invalid = { let interiors = [Cycle::partial() .with_poly_chain_from_points( @@ -146,7 +146,7 @@ mod tests { .with_surface(objects.surfaces.xy_plane()) .with_exterior_polygon_from_points([[0., 0.], [3., 0.], [0., 3.]]) .with_interior_polygon_from_points([[1., 1.], [1., 2.], [2., 1.]]) - .build(); + .build()?; let invalid = { let interiors = valid .interiors() diff --git a/crates/fj-operations/src/difference_2d.rs b/crates/fj-operations/src/difference_2d.rs index c5c5e9e30..7f9267045 100644 --- a/crates/fj-operations/src/difference_2d.rs +++ b/crates/fj-operations/src/difference_2d.rs @@ -82,7 +82,7 @@ impl Shape for fj::Difference2d { .with_exterior(exterior) .with_interiors(interiors) .with_color(Color(self.color())) - .build(), + .build()?, ); } diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 3b0573d76..085c701a5 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -35,7 +35,7 @@ impl Shape for fj::Sketch { Face::builder(objects) .with_exterior(cycle) .with_color(Color(self.color())) - .build() + .build()? } fj::Chain::PolyChain(poly_chain) => { let points = @@ -45,7 +45,7 @@ impl Shape for fj::Sketch { .with_surface(surface) .with_exterior_polygon_from_points(points) .with_color(Color(self.color())) - .build() + .build()? } }; From 960c87d99b9447efb60d0df74a95ff183a4b8db5 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:27:24 +0100 Subject: [PATCH 03/22] Make field of `FaceBuilder` more flexible --- crates/fj-kernel/src/objects/face.rs | 2 +- crates/fj-kernel/src/partial/objects/face.rs | 21 ++++++++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/crates/fj-kernel/src/objects/face.rs b/crates/fj-kernel/src/objects/face.rs index 0439070dd..b234d68c9 100644 --- a/crates/fj-kernel/src/objects/face.rs +++ b/crates/fj-kernel/src/objects/face.rs @@ -44,7 +44,7 @@ impl Face { FaceBuilder { objects, surface: None, - exterior: None, + exterior: Default::default(), interiors: Vec::new(), color: None, } diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index aa87682cd..c8d4721cd 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -4,7 +4,7 @@ use fj_math::Point; use crate::{ builder::CycleBuilder, objects::{Cycle, Face, Objects, Surface}, - partial::HasPartial, + partial::{HasPartial, MaybePartial}, storage::Handle, validate::ValidationError, }; @@ -23,7 +23,7 @@ pub struct FaceBuilder<'a> { /// /// Must be provided by the caller, directly or using one of the `with_` /// methods, before [`FaceBuilder::build`] is called. - pub exterior: Option>, + pub exterior: MaybePartial, /// The interior cycles that form holes in the [`Face`] pub interiors: Vec>, @@ -41,7 +41,7 @@ impl<'a> FaceBuilder<'a> { /// Build the [`Face`] with the provided exterior pub fn with_exterior(mut self, exterior: Handle) -> Self { - self.exterior = Some(exterior); + self.exterior = exterior.into(); self } @@ -55,13 +55,10 @@ impl<'a> FaceBuilder<'a> { .as_ref() .expect("Need surface to create polygon"); - self.exterior = Some( - Cycle::partial() - .with_poly_chain_from_points(surface.clone(), points) - .close_with_line_segment() - .build(self.objects) - .unwrap(), - ); + self.exterior = Cycle::partial() + .with_poly_chain_from_points(surface.clone(), points) + .close_with_line_segment() + .into(); self } @@ -102,9 +99,7 @@ impl<'a> FaceBuilder<'a> { /// Construct a polygon from a list of points pub fn build(self) -> Result, ValidationError> { - let exterior = self - .exterior - .expect("Can't build `Face` without exterior cycle"); + let exterior = self.exterior.into_full(self.objects)?; let color = self.color.unwrap_or_default(); Ok(self.objects.faces.insert(Face::new( From baea7b9e236b66d7eabeec55377b3bb280b4d2ba Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:32:42 +0100 Subject: [PATCH 04/22] Make field of `FaceBuilder` more flexible --- crates/fj-kernel/src/partial/objects/face.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index c8d4721cd..0e841dcff 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -26,7 +26,7 @@ pub struct FaceBuilder<'a> { pub exterior: MaybePartial, /// The interior cycles that form holes in the [`Face`] - pub interiors: Vec>, + pub interiors: Vec>, /// The color of the [`Face`] pub color: Option, @@ -67,6 +67,7 @@ impl<'a> FaceBuilder<'a> { mut self, interiors: impl IntoIterator>, ) -> Self { + let interiors = interiors.into_iter().map(Into::into); self.interiors.extend(interiors); self } @@ -85,8 +86,7 @@ impl<'a> FaceBuilder<'a> { Cycle::partial() .with_poly_chain_from_points(surface.clone(), points) .close_with_line_segment() - .build(self.objects) - .unwrap(), + .into(), ); self } @@ -100,12 +100,16 @@ impl<'a> FaceBuilder<'a> { /// Construct a polygon from a list of points pub fn build(self) -> Result, ValidationError> { let exterior = self.exterior.into_full(self.objects)?; + let interiors = self + .interiors + .into_iter() + .map(|cycle| cycle.into_full(self.objects)) + .collect::, _>>()?; let color = self.color.unwrap_or_default(); - Ok(self.objects.faces.insert(Face::new( - exterior, - self.interiors, - color, - ))?) + Ok(self + .objects + .faces + .insert(Face::new(exterior, interiors, color))?) } } From 1caa0f0cbe4a8efebf3e28e2457d0ceae89cd86c Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:33:24 +0100 Subject: [PATCH 05/22] Make method argument more flexible --- crates/fj-kernel/src/partial/objects/face.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index 0e841dcff..aca08ffc1 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -65,7 +65,7 @@ impl<'a> FaceBuilder<'a> { /// Build the [`Face`] with the provided interior polygons pub fn with_interiors( mut self, - interiors: impl IntoIterator>, + interiors: impl IntoIterator>>, ) -> Self { let interiors = interiors.into_iter().map(Into::into); self.interiors.extend(interiors); From 8e02f2f85abf1018322fd86ecb4ccf56b670b08e Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:38:59 +0100 Subject: [PATCH 06/22] Pass `&Objects` into `FaceBuilder::build` --- .../src/algorithms/intersect/curve_face.rs | 4 +-- .../src/algorithms/intersect/face_face.rs | 8 ++--- .../src/algorithms/intersect/face_point.rs | 32 +++++++++---------- .../src/algorithms/intersect/ray_face.rs | 28 ++++++++-------- .../fj-kernel/src/algorithms/reverse/face.rs | 4 +-- crates/fj-kernel/src/algorithms/sweep/edge.rs | 6 ++-- crates/fj-kernel/src/algorithms/sweep/face.rs | 16 +++++----- .../src/algorithms/transform/face.rs | 4 +-- .../src/algorithms/triangulate/mod.rs | 12 +++---- crates/fj-kernel/src/builder/shell.rs | 12 +++---- crates/fj-kernel/src/builder/sketch.rs | 4 +-- crates/fj-kernel/src/iter.rs | 8 ++--- crates/fj-kernel/src/objects/face.rs | 5 ++- crates/fj-kernel/src/partial/objects/face.rs | 19 ++++++----- crates/fj-kernel/src/validate/face.rs | 8 ++--- crates/fj-operations/src/difference_2d.rs | 4 +-- crates/fj-operations/src/sketch.rs | 8 ++--- 17 files changed, 90 insertions(+), 92 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs index 62de03a96..3b1eb1254 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs @@ -183,11 +183,11 @@ mod tests { [ 1., -1.], ]; - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points(exterior) .with_interior_polygon_from_points(interior) - .build()?; + .build(&objects)?; let expected = CurveFaceIntersection::from_intervals([[[1.], [2.]], [[4.], [5.]]]); diff --git a/crates/fj-kernel/src/algorithms/intersect/face_face.rs b/crates/fj-kernel/src/algorithms/intersect/face_face.rs index b8467e62c..f18f544ad 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_face.rs @@ -87,10 +87,10 @@ mod tests { ]; let [a, b] = [objects.surfaces.xy_plane(), objects.surfaces.xz_plane()] .try_map_ext(|surface| { - Face::builder(&objects) + Face::builder() .with_surface(surface) .with_exterior_polygon_from_points(points) - .build() + .build(&objects) })?; let intersection = FaceFaceIntersection::compute([&a, &b], &objects)?; @@ -114,10 +114,10 @@ mod tests { let surfaces = [objects.surfaces.xy_plane(), objects.surfaces.xz_plane()]; let [a, b] = surfaces.clone().try_map_ext(|surface| { - Face::builder(&objects) + Face::builder() .with_surface(surface) .with_exterior_polygon_from_points(points) - .build() + .build(&objects) })?; let intersection = FaceFaceIntersection::compute([&a, &b], &objects)?; diff --git a/crates/fj-kernel/src/algorithms/intersect/face_point.rs b/crates/fj-kernel/src/algorithms/intersect/face_point.rs index ba9b520e4..17614d985 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_point.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_point.rs @@ -145,10 +145,10 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 1.], [0., 2.]]) - .build()?; + .build(&objects)?; let point = Point::from([2., 1.]); let intersection = (&face, &point).intersect(); @@ -162,10 +162,10 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [2., 1.], [0., 2.]]) - .build()?; + .build(&objects)?; let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -182,10 +182,10 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([[4., 2.], [0., 4.], [0., 0.]]) - .build()?; + .build(&objects)?; let point = Point::from([1., 2.]); let intersection = (&face, &point).intersect(); @@ -202,7 +202,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([ [0., 0.], @@ -210,7 +210,7 @@ mod tests { [3., 0.], [3., 4.], ]) - .build()?; + .build(&objects)?; let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -228,7 +228,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([ [0., 0.], @@ -236,7 +236,7 @@ mod tests { [3., 1.], [0., 2.], ]) - .build()?; + .build(&objects)?; let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -254,7 +254,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([ [0., 0.], @@ -263,7 +263,7 @@ mod tests { [4., 0.], [4., 5.], ]) - .build()?; + .build(&objects)?; let point = Point::from([1., 1.]); let intersection = (&face, &point).intersect(); @@ -280,10 +280,10 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [2., 0.], [0., 1.]]) - .build()?; + .build(&objects)?; let point = Point::from([1., 0.]); let intersection = (&face, &point).intersect(); @@ -309,10 +309,10 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) - .build()?; + .build(&objects)?; let point = Point::from([1., 0.]); let intersection = (&face, &point).intersect(); diff --git a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs index 13daca4d1..b90ab212f 100644 --- a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs @@ -163,7 +163,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.yz_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -171,7 +171,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build()? + .build(&objects)? .translate([-1., 0., 0.], &objects)?; assert_eq!((&ray, &face).intersect(), None); @@ -185,7 +185,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.yz_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -193,7 +193,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build()? + .build(&objects)? .translate([1., 0., 0.], &objects)?; assert_eq!( @@ -210,7 +210,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.yz_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -218,7 +218,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build()? + .build(&objects)? .translate([0., 0., 2.], &objects)?; assert_eq!((&ray, &face).intersect(), None); @@ -232,7 +232,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.yz_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -240,7 +240,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build()? + .build(&objects)? .translate([1., 1., 0.], &objects)?; let edge = face @@ -265,7 +265,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.yz_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -273,7 +273,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build()? + .build(&objects)? .translate([1., 1., 1.], &objects)?; let vertex = face @@ -296,7 +296,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -304,7 +304,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build()?; + .build(&objects)?; assert_eq!( (&ray, &face).intersect(), @@ -321,7 +321,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -329,7 +329,7 @@ mod tests { [1., 1.], [-1., 1.], ]) - .build()? + .build(&objects)? .translate([0., 0., 1.], &objects)?; assert_eq!((&ray, &face).intersect(), None); diff --git a/crates/fj-kernel/src/algorithms/reverse/face.rs b/crates/fj-kernel/src/algorithms/reverse/face.rs index 9fae7ad8a..fa97496a9 100644 --- a/crates/fj-kernel/src/algorithms/reverse/face.rs +++ b/crates/fj-kernel/src/algorithms/reverse/face.rs @@ -14,10 +14,10 @@ impl Reverse for Handle { .map(|cycle| cycle.clone().reverse(objects)) .collect::, _>>()?; - Face::builder(objects) + Face::builder() .with_exterior(exterior) .with_interiors(interiors) .with_color(self.color()) - .build() + .build(objects) } } diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index 24097fddc..98a7e8272 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -175,10 +175,10 @@ impl Sweep for (Handle, Color) { objects.cycles.insert(Cycle::new(edges))? }; - Face::builder(objects) + Face::builder() .with_exterior(cycle) .with_color(color) - .build() + .build(objects) } } @@ -256,7 +256,7 @@ mod tests { .cycles .insert(Cycle::new([bottom, side_up, top, side_down]))?; - Face::builder(&objects).with_exterior(cycle).build()? + Face::builder().with_exterior(cycle).build(&objects)? }; assert_eq!(face, expected_face); diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 52299fa2e..0bcbffb09 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -107,15 +107,15 @@ mod tests { .build() .sweep(UP, &objects)?; - let bottom = Face::builder(&objects) + let bottom = Face::builder() .with_surface(surface.clone()) .with_exterior_polygon_from_points(TRIANGLE) - .build()? + .build(&objects)? .reverse(&objects)?; - let top = Face::builder(&objects) + let top = Face::builder() .with_surface(surface.translate(UP, &objects)?) .with_exterior_polygon_from_points(TRIANGLE) - .build()?; + .build(&objects)?; assert!(solid.find_face(&bottom).is_some()); assert!(solid.find_face(&top).is_some()); @@ -151,15 +151,15 @@ mod tests { .build() .sweep(DOWN, &objects)?; - let bottom = Face::builder(&objects) + let bottom = Face::builder() .with_surface(surface.clone().translate(DOWN, &objects)?) .with_exterior_polygon_from_points(TRIANGLE) - .build()? + .build(&objects)? .reverse(&objects)?; - let top = Face::builder(&objects) + let top = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points(TRIANGLE) - .build()?; + .build(&objects)?; assert!(solid.find_face(&bottom).is_some()); assert!(solid.find_face(&top).is_some()); diff --git a/crates/fj-kernel/src/algorithms/transform/face.rs b/crates/fj-kernel/src/algorithms/transform/face.rs index 7f18a45db..02f606fb2 100644 --- a/crates/fj-kernel/src/algorithms/transform/face.rs +++ b/crates/fj-kernel/src/algorithms/transform/face.rs @@ -35,11 +35,11 @@ impl TransformObject for Handle { let color = self.color(); - Face::builder(objects) + Face::builder() .with_exterior(exterior) .with_interiors(interiors) .with_color(color) - .build() + .build(objects) } } diff --git a/crates/fj-kernel/src/algorithms/triangulate/mod.rs b/crates/fj-kernel/src/algorithms/triangulate/mod.rs index 2610b0f2b..a77bd40aa 100644 --- a/crates/fj-kernel/src/algorithms/triangulate/mod.rs +++ b/crates/fj-kernel/src/algorithms/triangulate/mod.rs @@ -100,10 +100,10 @@ mod tests { let d = [0., 1.]; let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([a, b, c, d]) - .build()?; + .build(&objects)?; let a = Point::from(a).to_xyz(); let b = Point::from(b).to_xyz(); @@ -135,11 +135,11 @@ mod tests { let h = [3., 1.]; let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface.clone()) .with_exterior_polygon_from_points([a, b, c, d]) .with_interior_polygon_from_points([e, f, g, h]) - .build()?; + .build(&objects)?; let triangles = triangulate(face)?; @@ -196,10 +196,10 @@ mod tests { let e = [0., 0.8]; let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface.clone()) .with_exterior_polygon_from_points([a, b, c, d, e]) - .build()?; + .build(&objects)?; let triangles = triangulate(face)?; diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs index b00e6decc..4e39d1589 100644 --- a/crates/fj-kernel/src/builder/shell.rs +++ b/crates/fj-kernel/src/builder/shell.rs @@ -54,7 +54,7 @@ impl<'a> ShellBuilder<'a> { .translate([Z, Z, -h], self.objects) .unwrap(); - Face::builder(self.objects) + Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([ [-h, -h], @@ -62,7 +62,7 @@ impl<'a> ShellBuilder<'a> { [h, h], [-h, h], ]) - .build() + .build(self.objects) .unwrap() }; @@ -194,9 +194,9 @@ impl<'a> ShellBuilder<'a> { .build(self.objects) .unwrap(); - Face::builder(self.objects) + Face::builder() .with_exterior(cycle) - .build() + .build(self.objects) .unwrap() }); @@ -263,11 +263,11 @@ impl<'a> ShellBuilder<'a> { ); } - Face::builder(self.objects) + Face::builder() .with_exterior( self.objects.cycles.insert(Cycle::new(edges)).unwrap(), ) - .build() + .build(self.objects) .unwrap() }; diff --git a/crates/fj-kernel/src/builder/sketch.rs b/crates/fj-kernel/src/builder/sketch.rs index 634258013..23b4b9cf8 100644 --- a/crates/fj-kernel/src/builder/sketch.rs +++ b/crates/fj-kernel/src/builder/sketch.rs @@ -44,10 +44,10 @@ impl<'a> SketchBuilder<'a> { .surface .as_ref() .expect("Can't build `Sketch` without `Surface`"); - self.faces.extend([Face::builder(self.objects) + self.faces.extend([Face::builder() .with_surface(surface.clone()) .with_exterior_polygon_from_points(points) - .build() + .build(self.objects) .unwrap()]); self } diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index a3933f2d7..cd3452606 100644 --- a/crates/fj-kernel/src/iter.rs +++ b/crates/fj-kernel/src/iter.rs @@ -424,10 +424,10 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let object = Face::builder(&objects) + let object = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) - .build(); + .build(&objects); assert_eq!(3, object.curve_iter().count()); assert_eq!(1, object.cycle_iter().count()); @@ -532,10 +532,10 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder(&objects) + let face = Face::builder() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) - .build()?; + .build(&objects)?; let object = Sketch::builder(&objects).with_faces([face]).build(); assert_eq!(3, object.curve_iter().count()); diff --git a/crates/fj-kernel/src/objects/face.rs b/crates/fj-kernel/src/objects/face.rs index b234d68c9..8d6b4326f 100644 --- a/crates/fj-kernel/src/objects/face.rs +++ b/crates/fj-kernel/src/objects/face.rs @@ -5,7 +5,7 @@ use fj_math::Winding; use crate::{partial::FaceBuilder, storage::Handle}; -use super::{Cycle, Objects, Surface}; +use super::{Cycle, Surface}; /// A face of a shape /// @@ -40,9 +40,8 @@ pub struct Face { impl Face { /// Build a `Face` using [`FaceBuilder`] - pub fn builder(objects: &Objects) -> FaceBuilder { + pub fn builder() -> FaceBuilder { FaceBuilder { - objects, surface: None, exterior: Default::default(), interiors: Vec::new(), diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index aca08ffc1..bd9b85764 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -12,10 +12,7 @@ use crate::{ /// API for building a [`Face`] /// /// Also see [`Face::builder`]. -pub struct FaceBuilder<'a> { - /// The stores that the created objects are put in - pub objects: &'a Objects, - +pub struct FaceBuilder { /// The surface that the [`Face`] is defined in pub surface: Option>, @@ -32,7 +29,7 @@ pub struct FaceBuilder<'a> { pub color: Option, } -impl<'a> FaceBuilder<'a> { +impl FaceBuilder { /// Build the [`Face`] with the provided surface pub fn with_surface(mut self, surface: Handle) -> Self { self.surface = Some(surface); @@ -98,17 +95,19 @@ impl<'a> FaceBuilder<'a> { } /// Construct a polygon from a list of points - pub fn build(self) -> Result, ValidationError> { - let exterior = self.exterior.into_full(self.objects)?; + pub fn build( + self, + objects: &Objects, + ) -> Result, ValidationError> { + let exterior = self.exterior.into_full(objects)?; let interiors = self .interiors .into_iter() - .map(|cycle| cycle.into_full(self.objects)) + .map(|cycle| cycle.into_full(objects)) .collect::, _>>()?; let color = self.color.unwrap_or_default(); - Ok(self - .objects + Ok(objects .faces .insert(Face::new(exterior, interiors, color))?) } diff --git a/crates/fj-kernel/src/validate/face.rs b/crates/fj-kernel/src/validate/face.rs index 377878801..bf1f46614 100644 --- a/crates/fj-kernel/src/validate/face.rs +++ b/crates/fj-kernel/src/validate/face.rs @@ -115,11 +115,11 @@ mod tests { fn face_surface_mismatch() -> anyhow::Result<()> { let objects = Objects::new(); - let valid = Face::builder(&objects) + let valid = Face::builder() .with_surface(objects.surfaces.xy_plane()) .with_exterior_polygon_from_points([[0., 0.], [3., 0.], [0., 3.]]) .with_interior_polygon_from_points([[1., 1.], [1., 2.], [2., 1.]]) - .build()?; + .build(&objects)?; let invalid = { let interiors = [Cycle::partial() .with_poly_chain_from_points( @@ -142,11 +142,11 @@ mod tests { fn face_invalid_interior_winding() -> anyhow::Result<()> { let objects = Objects::new(); - let valid = Face::builder(&objects) + let valid = Face::builder() .with_surface(objects.surfaces.xy_plane()) .with_exterior_polygon_from_points([[0., 0.], [3., 0.], [0., 3.]]) .with_interior_polygon_from_points([[1., 1.], [1., 2.], [2., 1.]]) - .build()?; + .build(&objects)?; let invalid = { let interiors = valid .interiors() diff --git a/crates/fj-operations/src/difference_2d.rs b/crates/fj-operations/src/difference_2d.rs index 7f9267045..3432a0598 100644 --- a/crates/fj-operations/src/difference_2d.rs +++ b/crates/fj-operations/src/difference_2d.rs @@ -78,11 +78,11 @@ impl Shape for fj::Difference2d { ); faces.push( - Face::builder(objects) + Face::builder() .with_exterior(exterior) .with_interiors(interiors) .with_color(Color(self.color())) - .build()?, + .build(objects)?, ); } diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 085c701a5..8ec208f11 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -32,20 +32,20 @@ impl Shape for fj::Sketch { .build(objects)?; let cycle = objects.cycles.insert(Cycle::new([half_edge]))?; - Face::builder(objects) + Face::builder() .with_exterior(cycle) .with_color(Color(self.color())) - .build()? + .build(objects)? } fj::Chain::PolyChain(poly_chain) => { let points = poly_chain.to_points().into_iter().map(Point::from); - Face::builder(objects) + Face::builder() .with_surface(surface) .with_exterior_polygon_from_points(points) .with_color(Color(self.color())) - .build()? + .build(objects)? } }; From 467ad6457c242e33f04679c9facafb1d1e649d48 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:40:03 +0100 Subject: [PATCH 07/22] Rename `FaceBuilder` to `PartialFace` --- crates/fj-kernel/src/objects/face.rs | 8 ++++---- crates/fj-kernel/src/partial/mod.rs | 2 +- crates/fj-kernel/src/partial/objects/face.rs | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/fj-kernel/src/objects/face.rs b/crates/fj-kernel/src/objects/face.rs index 8d6b4326f..57c772d1a 100644 --- a/crates/fj-kernel/src/objects/face.rs +++ b/crates/fj-kernel/src/objects/face.rs @@ -3,7 +3,7 @@ use std::collections::{btree_set, BTreeSet}; use fj_interop::mesh::Color; use fj_math::Winding; -use crate::{partial::FaceBuilder, storage::Handle}; +use crate::{partial::PartialFace, storage::Handle}; use super::{Cycle, Surface}; @@ -39,9 +39,9 @@ pub struct Face { } impl Face { - /// Build a `Face` using [`FaceBuilder`] - pub fn builder() -> FaceBuilder { - FaceBuilder { + /// Build a `Face` using [`PartialFace`] + pub fn builder() -> PartialFace { + PartialFace { surface: None, exterior: Default::default(), interiors: Vec::new(), diff --git a/crates/fj-kernel/src/partial/mod.rs b/crates/fj-kernel/src/partial/mod.rs index a19b0fb37..f7e845d07 100644 --- a/crates/fj-kernel/src/partial/mod.rs +++ b/crates/fj-kernel/src/partial/mod.rs @@ -45,7 +45,7 @@ pub use self::{ curve::{PartialCurve, PartialGlobalCurve}, cycle::PartialCycle, edge::{PartialGlobalEdge, PartialHalfEdge}, - face::FaceBuilder, + face::PartialFace, vertex::{PartialGlobalVertex, PartialSurfaceVertex, PartialVertex}, }, traits::{HasPartial, Partial}, diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index bd9b85764..d8bcb8fd5 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -12,14 +12,14 @@ use crate::{ /// API for building a [`Face`] /// /// Also see [`Face::builder`]. -pub struct FaceBuilder { +pub struct PartialFace { /// The surface that the [`Face`] is defined in pub surface: Option>, /// The exterior cycle that bounds the [`Face`] on the outside /// /// Must be provided by the caller, directly or using one of the `with_` - /// methods, before [`FaceBuilder::build`] is called. + /// methods, before [`PartialFace::build`] is called. pub exterior: MaybePartial, /// The interior cycles that form holes in the [`Face`] @@ -29,7 +29,7 @@ pub struct FaceBuilder { pub color: Option, } -impl FaceBuilder { +impl PartialFace { /// Build the [`Face`] with the provided surface pub fn with_surface(mut self, surface: Handle) -> Self { self.surface = Some(surface); From 9f9bb75b6e96ff70a655b1052c21f9738c5bcfe0 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:43:23 +0100 Subject: [PATCH 08/22] Derive some traits for `PartialFace` --- crates/fj-kernel/src/partial/objects/face.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index d8bcb8fd5..caadca8a6 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -12,6 +12,7 @@ use crate::{ /// API for building a [`Face`] /// /// Also see [`Face::builder`]. +#[derive(Clone, Debug, Default)] pub struct PartialFace { /// The surface that the [`Face`] is defined in pub surface: Option>, From 8f7e4ae52e41cf989465af2425ec5387742d9be2 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:44:39 +0100 Subject: [PATCH 09/22] Add conversion from `Face` to `PartialFace` --- crates/fj-kernel/src/partial/objects/face.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index caadca8a6..208605750 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -113,3 +113,14 @@ impl PartialFace { .insert(Face::new(exterior, interiors, color))?) } } + +impl From<&Face> for PartialFace { + fn from(face: &Face) -> Self { + Self { + surface: Some(face.surface().clone()), + exterior: face.exterior().clone().into(), + interiors: face.interiors().cloned().map(Into::into).collect(), + color: Some(face.color()), + } + } +} From a5db05be180859e202ef4b63d21e2c33209ef1e6 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:45:59 +0100 Subject: [PATCH 10/22] Refactor --- crates/fj-kernel/src/objects/face.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crates/fj-kernel/src/objects/face.rs b/crates/fj-kernel/src/objects/face.rs index 57c772d1a..21270c56b 100644 --- a/crates/fj-kernel/src/objects/face.rs +++ b/crates/fj-kernel/src/objects/face.rs @@ -41,12 +41,7 @@ pub struct Face { impl Face { /// Build a `Face` using [`PartialFace`] pub fn builder() -> PartialFace { - PartialFace { - surface: None, - exterior: Default::default(), - interiors: Vec::new(), - color: None, - } + PartialFace::default() } /// Construct a new instance of `Face` From 3b54c6aa2bc89bb71948abc2d94c99da72171a89 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:54:55 +0100 Subject: [PATCH 11/22] Add getters for `PartialFace`'s fields --- crates/fj-kernel/src/partial/objects/face.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index 208605750..c2212b164 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -31,6 +31,26 @@ pub struct PartialFace { } impl PartialFace { + /// Access th surface that the [`Face`] is defined in + pub fn surface(&self) -> Option> { + self.surface.clone() + } + + /// Access the [`Face`]'s exterior cycle + pub fn exterior(&self) -> MaybePartial { + self.exterior.clone() + } + + /// Access the [`Face`]'s interior cycles + pub fn interiors(&self) -> impl Iterator> + '_ { + self.interiors.iter().cloned() + } + + /// Access the color of the [`Face`] + pub fn color(&self) -> Option { + self.color + } + /// Build the [`Face`] with the provided surface pub fn with_surface(mut self, surface: Handle) -> Self { self.surface = Some(surface); From a0ba3d95a55d157cd1a51c830c2fcc6866598199 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 13:55:44 +0100 Subject: [PATCH 12/22] Make fields of `PartialFace` private --- crates/fj-kernel/src/partial/objects/face.rs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index c2212b164..6d491897f 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -14,20 +14,10 @@ use crate::{ /// Also see [`Face::builder`]. #[derive(Clone, Debug, Default)] pub struct PartialFace { - /// The surface that the [`Face`] is defined in - pub surface: Option>, - - /// The exterior cycle that bounds the [`Face`] on the outside - /// - /// Must be provided by the caller, directly or using one of the `with_` - /// methods, before [`PartialFace::build`] is called. - pub exterior: MaybePartial, - - /// The interior cycles that form holes in the [`Face`] - pub interiors: Vec>, - - /// The color of the [`Face`] - pub color: Option, + surface: Option>, + exterior: MaybePartial, + interiors: Vec>, + color: Option, } impl PartialFace { From bfd08e4c7694afdf7e354d96695ac1192467f137 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 14:04:38 +0100 Subject: [PATCH 13/22] Make method argument more flexible --- crates/fj-kernel/src/partial/objects/face.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index 6d491897f..24de04bdf 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -48,7 +48,10 @@ impl PartialFace { } /// Build the [`Face`] with the provided exterior - pub fn with_exterior(mut self, exterior: Handle) -> Self { + pub fn with_exterior( + mut self, + exterior: impl Into>, + ) -> Self { self.exterior = exterior.into(); self } From efc209d7916c401c0664a0ad6dee2df9532cece9 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 14:10:44 +0100 Subject: [PATCH 14/22] Add `PartialFace::merge_with` --- crates/fj-kernel/src/partial/objects/face.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index 24de04bdf..394b4c399 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -4,7 +4,7 @@ use fj_math::Point; use crate::{ builder::CycleBuilder, objects::{Cycle, Face, Objects, Surface}, - partial::{HasPartial, MaybePartial}, + partial::{util::merge_options, HasPartial, MaybePartial}, storage::Handle, validate::ValidationError, }; @@ -108,6 +108,19 @@ impl PartialFace { self } + /// Merge this partial object with another + pub fn merge_with(self, other: Self) -> Self { + let mut interiors = self.interiors; + interiors.extend(other.interiors); + + Self { + surface: merge_options(self.surface, other.surface), + exterior: self.exterior.merge_with(other.exterior), + interiors, + color: merge_options(self.color, other.color), + } + } + /// Construct a polygon from a list of points pub fn build( self, From fcbdd882c38cad139722f73552a43cb52024e7a8 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 14:11:06 +0100 Subject: [PATCH 15/22] Make `PartialFace` a proper partial object --- .../src/algorithms/transform/face.rs | 33 +++++++++++-------- crates/fj-kernel/src/partial/objects/mod.rs | 7 ++-- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/transform/face.rs b/crates/fj-kernel/src/algorithms/transform/face.rs index 02f606fb2..3a406ed4f 100644 --- a/crates/fj-kernel/src/algorithms/transform/face.rs +++ b/crates/fj-kernel/src/algorithms/transform/face.rs @@ -2,44 +2,51 @@ use fj_math::Transform; use crate::{ objects::{Face, FaceSet, Objects}, - partial::HasPartial, - storage::Handle, + partial::PartialFace, validate::ValidationError, }; use super::TransformObject; -impl TransformObject for Handle { +impl TransformObject for PartialFace { fn transform( self, transform: &Transform, objects: &Objects, ) -> Result { - let surface = self.surface().clone().transform(transform, objects)?; + let surface = self + .surface() + .map(|surface| surface.transform(transform, objects)) + .transpose()?; let exterior = self .exterior() - .to_partial() + .into_partial() .transform(transform, objects)? - .with_surface(Some(surface.clone())) - .build(objects)?; + .with_surface(surface.clone()); let interiors = self .interiors() .map(|cycle| -> Result<_, ValidationError> { cycle - .to_partial() + .into_partial() .transform(transform, objects)? - .with_surface(Some(surface.clone())) + .with_surface(surface.clone()) .build(objects) }) .collect::, _>>()?; let color = self.color(); - Face::builder() + let mut face = Face::builder() .with_exterior(exterior) - .with_interiors(interiors) - .with_color(color) - .build(objects) + .with_interiors(interiors); + if let Some(surface) = surface { + face = face.with_surface(surface); + } + if let Some(color) = color { + face = face.with_color(color); + } + + Ok(face) } } diff --git a/crates/fj-kernel/src/partial/objects/mod.rs b/crates/fj-kernel/src/partial/objects/mod.rs index 3a31e58eb..5ab9c57b7 100644 --- a/crates/fj-kernel/src/partial/objects/mod.rs +++ b/crates/fj-kernel/src/partial/objects/mod.rs @@ -6,14 +6,14 @@ pub mod vertex; use crate::{ objects::{ - Curve, Cycle, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects, - SurfaceVertex, Vertex, + Curve, Cycle, Face, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, + Objects, SurfaceVertex, Vertex, }, storage::Handle, }; use super::{ - HasPartial, MaybePartial, Partial, PartialCurve, PartialCycle, + HasPartial, MaybePartial, Partial, PartialCurve, PartialCycle, PartialFace, PartialGlobalCurve, PartialGlobalEdge, PartialGlobalVertex, PartialHalfEdge, PartialSurfaceVertex, PartialVertex, }; @@ -54,6 +54,7 @@ macro_rules! impl_traits { impl_traits!( Curve, PartialCurve; Cycle, PartialCycle; + Face, PartialFace; GlobalCurve, PartialGlobalCurve; GlobalEdge, PartialGlobalEdge; GlobalVertex, PartialGlobalVertex; From 7a0d12a667c1d4231c845a426666037332ff70a4 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 14:15:37 +0100 Subject: [PATCH 16/22] Update doc comment --- crates/fj-kernel/src/partial/objects/face.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index 394b4c399..3288e4cc2 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -9,9 +9,9 @@ use crate::{ validate::ValidationError, }; -/// API for building a [`Face`] +/// A partial [`Face`] /// -/// Also see [`Face::builder`]. +/// See [`crate::partial`] for more information. #[derive(Clone, Debug, Default)] pub struct PartialFace { surface: Option>, From 75879231205ddb0e53a67e6a59ef7a24138263ed Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 14:15:55 +0100 Subject: [PATCH 17/22] Remove `Face::builder` --- .../src/algorithms/intersect/curve_face.rs | 2 +- .../src/algorithms/intersect/face_face.rs | 4 ++-- .../src/algorithms/intersect/face_point.rs | 17 +++++++++-------- .../src/algorithms/intersect/ray_face.rs | 15 ++++++++------- crates/fj-kernel/src/algorithms/reverse/face.rs | 3 ++- crates/fj-kernel/src/algorithms/sweep/edge.rs | 5 +++-- crates/fj-kernel/src/algorithms/sweep/face.rs | 8 ++++---- .../fj-kernel/src/algorithms/transform/face.rs | 4 ++-- .../fj-kernel/src/algorithms/triangulate/mod.rs | 7 ++++--- crates/fj-kernel/src/builder/shell.rs | 6 +++--- crates/fj-kernel/src/builder/sketch.rs | 3 ++- crates/fj-kernel/src/iter.rs | 4 ++-- crates/fj-kernel/src/objects/face.rs | 7 +------ crates/fj-kernel/src/validate/face.rs | 4 ++-- crates/fj-operations/src/difference_2d.rs | 3 ++- crates/fj-operations/src/sketch.rs | 4 ++-- 16 files changed, 49 insertions(+), 47 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs index 3b1eb1254..3dbe4a484 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs @@ -183,7 +183,7 @@ mod tests { [ 1., -1.], ]; - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points(exterior) .with_interior_polygon_from_points(interior) diff --git a/crates/fj-kernel/src/algorithms/intersect/face_face.rs b/crates/fj-kernel/src/algorithms/intersect/face_face.rs index f18f544ad..3f72039e7 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_face.rs @@ -87,7 +87,7 @@ mod tests { ]; let [a, b] = [objects.surfaces.xy_plane(), objects.surfaces.xz_plane()] .try_map_ext(|surface| { - Face::builder() + Face::partial() .with_surface(surface) .with_exterior_polygon_from_points(points) .build(&objects) @@ -114,7 +114,7 @@ mod tests { let surfaces = [objects.surfaces.xy_plane(), objects.surfaces.xz_plane()]; let [a, b] = surfaces.clone().try_map_ext(|surface| { - Face::builder() + Face::partial() .with_surface(surface) .with_exterior_polygon_from_points(points) .build(&objects) diff --git a/crates/fj-kernel/src/algorithms/intersect/face_point.rs b/crates/fj-kernel/src/algorithms/intersect/face_point.rs index 17614d985..007caa096 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_point.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_point.rs @@ -138,6 +138,7 @@ mod tests { algorithms::intersect::{face_point::FacePointIntersection, Intersect}, iter::ObjectIters, objects::{Face, Objects}, + partial::HasPartial, }; #[test] @@ -145,7 +146,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 1.], [0., 2.]]) .build(&objects)?; @@ -162,7 +163,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [2., 1.], [0., 2.]]) .build(&objects)?; @@ -182,7 +183,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[4., 2.], [0., 4.], [0., 0.]]) .build(&objects)?; @@ -202,7 +203,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ [0., 0.], @@ -228,7 +229,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ [0., 0.], @@ -254,7 +255,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ [0., 0.], @@ -280,7 +281,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [2., 0.], [0., 1.]]) .build(&objects)?; @@ -309,7 +310,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) .build(&objects)?; diff --git a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs index b90ab212f..9a3b873da 100644 --- a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs @@ -154,6 +154,7 @@ mod tests { }, iter::ObjectIters, objects::{Face, Objects}, + partial::HasPartial, }; #[test] @@ -163,7 +164,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.yz_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -185,7 +186,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.yz_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -210,7 +211,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.yz_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -232,7 +233,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.yz_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -265,7 +266,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.yz_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -296,7 +297,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], @@ -321,7 +322,7 @@ mod tests { let ray = HorizontalRayToTheRight::from([0., 0., 0.]); let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ [-1., -1.], diff --git a/crates/fj-kernel/src/algorithms/reverse/face.rs b/crates/fj-kernel/src/algorithms/reverse/face.rs index fa97496a9..9f7a20607 100644 --- a/crates/fj-kernel/src/algorithms/reverse/face.rs +++ b/crates/fj-kernel/src/algorithms/reverse/face.rs @@ -1,5 +1,6 @@ use crate::{ objects::{Face, Objects}, + partial::HasPartial, storage::Handle, validate::ValidationError, }; @@ -14,7 +15,7 @@ impl Reverse for Handle { .map(|cycle| cycle.clone().reverse(objects)) .collect::, _>>()?; - Face::builder() + Face::partial() .with_exterior(exterior) .with_interiors(interiors) .with_color(self.color()) diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index 98a7e8272..b4659507a 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -7,6 +7,7 @@ use crate::{ Curve, Cycle, Face, GlobalEdge, HalfEdge, Objects, SurfaceVertex, Vertex, }, + partial::HasPartial, path::SurfacePath, storage::Handle, validate::ValidationError, @@ -175,7 +176,7 @@ impl Sweep for (Handle, Color) { objects.cycles.insert(Cycle::new(edges))? }; - Face::builder() + Face::partial() .with_exterior(cycle) .with_color(color) .build(objects) @@ -256,7 +257,7 @@ mod tests { .cycles .insert(Cycle::new([bottom, side_up, top, side_down]))?; - Face::builder().with_exterior(cycle).build(&objects)? + Face::partial().with_exterior(cycle).build(&objects)? }; assert_eq!(face, expected_face); diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 0bcbffb09..181da6a69 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -107,12 +107,12 @@ mod tests { .build() .sweep(UP, &objects)?; - let bottom = Face::builder() + let bottom = Face::partial() .with_surface(surface.clone()) .with_exterior_polygon_from_points(TRIANGLE) .build(&objects)? .reverse(&objects)?; - let top = Face::builder() + let top = Face::partial() .with_surface(surface.translate(UP, &objects)?) .with_exterior_polygon_from_points(TRIANGLE) .build(&objects)?; @@ -151,12 +151,12 @@ mod tests { .build() .sweep(DOWN, &objects)?; - let bottom = Face::builder() + let bottom = Face::partial() .with_surface(surface.clone().translate(DOWN, &objects)?) .with_exterior_polygon_from_points(TRIANGLE) .build(&objects)? .reverse(&objects)?; - let top = Face::builder() + let top = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points(TRIANGLE) .build(&objects)?; diff --git a/crates/fj-kernel/src/algorithms/transform/face.rs b/crates/fj-kernel/src/algorithms/transform/face.rs index 3a406ed4f..833eaebaa 100644 --- a/crates/fj-kernel/src/algorithms/transform/face.rs +++ b/crates/fj-kernel/src/algorithms/transform/face.rs @@ -2,7 +2,7 @@ use fj_math::Transform; use crate::{ objects::{Face, FaceSet, Objects}, - partial::PartialFace, + partial::{HasPartial, PartialFace}, validate::ValidationError, }; @@ -36,7 +36,7 @@ impl TransformObject for PartialFace { let color = self.color(); - let mut face = Face::builder() + let mut face = Face::partial() .with_exterior(exterior) .with_interiors(interiors); if let Some(surface) = surface { diff --git a/crates/fj-kernel/src/algorithms/triangulate/mod.rs b/crates/fj-kernel/src/algorithms/triangulate/mod.rs index a77bd40aa..8fc63496a 100644 --- a/crates/fj-kernel/src/algorithms/triangulate/mod.rs +++ b/crates/fj-kernel/src/algorithms/triangulate/mod.rs @@ -85,6 +85,7 @@ mod tests { use crate::{ algorithms::approx::{Approx, Tolerance}, objects::{Face, Objects}, + partial::HasPartial, storage::Handle, }; @@ -100,7 +101,7 @@ mod tests { let d = [0., 1.]; let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([a, b, c, d]) .build(&objects)?; @@ -135,7 +136,7 @@ mod tests { let h = [3., 1.]; let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface.clone()) .with_exterior_polygon_from_points([a, b, c, d]) .with_interior_polygon_from_points([e, f, g, h]) @@ -196,7 +197,7 @@ mod tests { let e = [0., 0.8]; let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface.clone()) .with_exterior_polygon_from_points([a, b, c, d, e]) .build(&objects)?; diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs index 4e39d1589..ef1580478 100644 --- a/crates/fj-kernel/src/builder/shell.rs +++ b/crates/fj-kernel/src/builder/shell.rs @@ -54,7 +54,7 @@ impl<'a> ShellBuilder<'a> { .translate([Z, Z, -h], self.objects) .unwrap(); - Face::builder() + Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([ [-h, -h], @@ -194,7 +194,7 @@ impl<'a> ShellBuilder<'a> { .build(self.objects) .unwrap(); - Face::builder() + Face::partial() .with_exterior(cycle) .build(self.objects) .unwrap() @@ -263,7 +263,7 @@ impl<'a> ShellBuilder<'a> { ); } - Face::builder() + Face::partial() .with_exterior( self.objects.cycles.insert(Cycle::new(edges)).unwrap(), ) diff --git a/crates/fj-kernel/src/builder/sketch.rs b/crates/fj-kernel/src/builder/sketch.rs index 23b4b9cf8..7052b4a36 100644 --- a/crates/fj-kernel/src/builder/sketch.rs +++ b/crates/fj-kernel/src/builder/sketch.rs @@ -2,6 +2,7 @@ use fj_math::Point; use crate::{ objects::{Face, FaceSet, Objects, Sketch, Surface}, + partial::HasPartial, storage::Handle, }; @@ -44,7 +45,7 @@ impl<'a> SketchBuilder<'a> { .surface .as_ref() .expect("Can't build `Sketch` without `Surface`"); - self.faces.extend([Face::builder() + self.faces.extend([Face::partial() .with_surface(surface.clone()) .with_exterior_polygon_from_points(points) .build(self.objects) diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index cd3452606..3be9a3493 100644 --- a/crates/fj-kernel/src/iter.rs +++ b/crates/fj-kernel/src/iter.rs @@ -424,7 +424,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let object = Face::builder() + let object = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) .build(&objects); @@ -532,7 +532,7 @@ mod tests { let objects = Objects::new(); let surface = objects.surfaces.xy_plane(); - let face = Face::builder() + let face = Face::partial() .with_surface(surface) .with_exterior_polygon_from_points([[0., 0.], [1., 0.], [0., 1.]]) .build(&objects)?; diff --git a/crates/fj-kernel/src/objects/face.rs b/crates/fj-kernel/src/objects/face.rs index 21270c56b..7fba05e73 100644 --- a/crates/fj-kernel/src/objects/face.rs +++ b/crates/fj-kernel/src/objects/face.rs @@ -3,7 +3,7 @@ use std::collections::{btree_set, BTreeSet}; use fj_interop::mesh::Color; use fj_math::Winding; -use crate::{partial::PartialFace, storage::Handle}; +use crate::storage::Handle; use super::{Cycle, Surface}; @@ -39,11 +39,6 @@ pub struct Face { } impl Face { - /// Build a `Face` using [`PartialFace`] - pub fn builder() -> PartialFace { - PartialFace::default() - } - /// Construct a new instance of `Face` pub fn new( exterior: Handle, diff --git a/crates/fj-kernel/src/validate/face.rs b/crates/fj-kernel/src/validate/face.rs index bf1f46614..f0b0fdd81 100644 --- a/crates/fj-kernel/src/validate/face.rs +++ b/crates/fj-kernel/src/validate/face.rs @@ -115,7 +115,7 @@ mod tests { fn face_surface_mismatch() -> anyhow::Result<()> { let objects = Objects::new(); - let valid = Face::builder() + let valid = Face::partial() .with_surface(objects.surfaces.xy_plane()) .with_exterior_polygon_from_points([[0., 0.], [3., 0.], [0., 3.]]) .with_interior_polygon_from_points([[1., 1.], [1., 2.], [2., 1.]]) @@ -142,7 +142,7 @@ mod tests { fn face_invalid_interior_winding() -> anyhow::Result<()> { let objects = Objects::new(); - let valid = Face::builder() + let valid = Face::partial() .with_surface(objects.surfaces.xy_plane()) .with_exterior_polygon_from_points([[0., 0.], [3., 0.], [0., 3.]]) .with_interior_polygon_from_points([[1., 1.], [1., 2.], [2., 1.]]) diff --git a/crates/fj-operations/src/difference_2d.rs b/crates/fj-operations/src/difference_2d.rs index 3432a0598..341ac2b30 100644 --- a/crates/fj-operations/src/difference_2d.rs +++ b/crates/fj-operations/src/difference_2d.rs @@ -5,6 +5,7 @@ use fj_kernel::{ algorithms::reverse::Reverse, iter::ObjectIters, objects::{Face, Objects, Sketch}, + partial::HasPartial, validate::ValidationError, }; use fj_math::Aabb; @@ -78,7 +79,7 @@ impl Shape for fj::Difference2d { ); faces.push( - Face::builder() + Face::partial() .with_exterior(exterior) .with_interiors(interiors) .with_color(Color(self.color())) diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 8ec208f11..f3ebf3dbd 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -32,7 +32,7 @@ impl Shape for fj::Sketch { .build(objects)?; let cycle = objects.cycles.insert(Cycle::new([half_edge]))?; - Face::builder() + Face::partial() .with_exterior(cycle) .with_color(Color(self.color())) .build(objects)? @@ -41,7 +41,7 @@ impl Shape for fj::Sketch { let points = poly_chain.to_points().into_iter().map(Point::from); - Face::builder() + Face::partial() .with_surface(surface) .with_exterior_polygon_from_points(points) .with_color(Color(self.color())) From cf326cd8e1c594cfaf3a659f04cdc0b11da79954 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 14:16:51 +0100 Subject: [PATCH 18/22] Refactor --- crates/fj-kernel/src/partial/objects/face.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index 3288e4cc2..18ecbad46 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -61,13 +61,10 @@ impl PartialFace { mut self, points: impl IntoIterator>>, ) -> Self { - let surface = self - .surface - .as_ref() - .expect("Need surface to create polygon"); + let surface = self.surface().expect("Need surface to create polygon"); self.exterior = Cycle::partial() - .with_poly_chain_from_points(surface.clone(), points) + .with_poly_chain_from_points(surface, points) .close_with_line_segment() .into(); self From 09bde74e09e1b33a9e51544b13c0c473e55efae0 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 14:17:40 +0100 Subject: [PATCH 19/22] Use public API in `PartialFace` method --- crates/fj-kernel/src/partial/objects/face.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index 18ecbad46..496313b56 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -58,16 +58,16 @@ impl PartialFace { /// Build the [`Face`] with an exterior polygon from the provided points pub fn with_exterior_polygon_from_points( - mut self, + self, points: impl IntoIterator>>, ) -> Self { let surface = self.surface().expect("Need surface to create polygon"); - self.exterior = Cycle::partial() - .with_poly_chain_from_points(surface, points) - .close_with_line_segment() - .into(); - self + self.with_exterior( + Cycle::partial() + .with_poly_chain_from_points(surface, points) + .close_with_line_segment(), + ) } /// Build the [`Face`] with the provided interior polygons From b2337c322eb515f42e53e9c5ee1cf50f62852089 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 14:24:10 +0100 Subject: [PATCH 20/22] Refactor --- crates/fj-kernel/src/partial/objects/face.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index 496313b56..60061ff48 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -85,14 +85,11 @@ impl PartialFace { mut self, points: impl IntoIterator>>, ) -> Self { - let surface = self - .surface - .as_ref() - .expect("Need surface to build polygon."); + let surface = self.surface().expect("Need surface to build polygon."); self.interiors.push( Cycle::partial() - .with_poly_chain_from_points(surface.clone(), points) + .with_poly_chain_from_points(surface, points) .close_with_line_segment() .into(), ); From 2dd5f6d68d3a26463b874634c2317e688f1c8428 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 14:25:46 +0100 Subject: [PATCH 21/22] Use public API in `PartialFace` method --- crates/fj-kernel/src/partial/objects/face.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index 60061ff48..87cf3bb23 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -82,18 +82,14 @@ impl PartialFace { /// Build the [`Face`] with an interior polygon from the provided points pub fn with_interior_polygon_from_points( - mut self, + self, points: impl IntoIterator>>, ) -> Self { let surface = self.surface().expect("Need surface to build polygon."); - self.interiors.push( - Cycle::partial() - .with_poly_chain_from_points(surface, points) - .close_with_line_segment() - .into(), - ); - self + self.with_interiors([Cycle::partial() + .with_poly_chain_from_points(surface, points) + .close_with_line_segment()]) } /// Build the [`Face`] with the provided color From e8e74cf2954573f8de5891f08d1ed434b465294f Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 9 Nov 2022 14:30:32 +0100 Subject: [PATCH 22/22] Extract non-essential methods from `PartialFace` --- .../src/algorithms/intersect/curve_face.rs | 2 +- .../src/algorithms/intersect/face_face.rs | 2 +- .../src/algorithms/intersect/face_point.rs | 1 + .../src/algorithms/intersect/ray_face.rs | 1 + crates/fj-kernel/src/algorithms/sweep/face.rs | 2 +- .../src/algorithms/triangulate/mod.rs | 1 + crates/fj-kernel/src/builder/face.rs | 49 +++++++++++++++++++ crates/fj-kernel/src/builder/mod.rs | 2 + crates/fj-kernel/src/builder/shell.rs | 2 +- crates/fj-kernel/src/builder/sketch.rs | 2 + crates/fj-kernel/src/iter.rs | 2 +- crates/fj-kernel/src/partial/objects/face.rs | 30 +----------- crates/fj-kernel/src/validate/face.rs | 2 +- crates/fj-operations/src/sketch.rs | 2 +- 14 files changed, 64 insertions(+), 36 deletions(-) create mode 100644 crates/fj-kernel/src/builder/face.rs diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs index 3dbe4a484..9e87ec130 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_face.rs @@ -150,7 +150,7 @@ where #[cfg(test)] mod tests { use crate::{ - builder::CurveBuilder, + builder::{CurveBuilder, FaceBuilder}, objects::{Curve, Face, Objects}, partial::HasPartial, }; diff --git a/crates/fj-kernel/src/algorithms/intersect/face_face.rs b/crates/fj-kernel/src/algorithms/intersect/face_face.rs index 3f72039e7..66b41ac30 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_face.rs @@ -67,7 +67,7 @@ mod tests { use crate::{ algorithms::intersect::CurveFaceIntersection, - builder::CurveBuilder, + builder::{CurveBuilder, FaceBuilder}, objects::{Curve, Face, Objects}, partial::HasPartial, }; diff --git a/crates/fj-kernel/src/algorithms/intersect/face_point.rs b/crates/fj-kernel/src/algorithms/intersect/face_point.rs index 007caa096..6fa3d17b9 100644 --- a/crates/fj-kernel/src/algorithms/intersect/face_point.rs +++ b/crates/fj-kernel/src/algorithms/intersect/face_point.rs @@ -136,6 +136,7 @@ mod tests { use crate::{ algorithms::intersect::{face_point::FacePointIntersection, Intersect}, + builder::FaceBuilder, iter::ObjectIters, objects::{Face, Objects}, partial::HasPartial, diff --git a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs index 9a3b873da..38201c372 100644 --- a/crates/fj-kernel/src/algorithms/intersect/ray_face.rs +++ b/crates/fj-kernel/src/algorithms/intersect/ray_face.rs @@ -152,6 +152,7 @@ mod tests { }, transform::TransformObject, }, + builder::FaceBuilder, iter::ObjectIters, objects::{Face, Objects}, partial::HasPartial, diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 181da6a69..3919832f7 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -84,7 +84,7 @@ mod tests { use crate::{ algorithms::{reverse::Reverse, transform::TransformObject}, - builder::HalfEdgeBuilder, + builder::{FaceBuilder, HalfEdgeBuilder}, objects::{Face, HalfEdge, Objects, Sketch}, partial::HasPartial, }; diff --git a/crates/fj-kernel/src/algorithms/triangulate/mod.rs b/crates/fj-kernel/src/algorithms/triangulate/mod.rs index 8fc63496a..6f9579c70 100644 --- a/crates/fj-kernel/src/algorithms/triangulate/mod.rs +++ b/crates/fj-kernel/src/algorithms/triangulate/mod.rs @@ -84,6 +84,7 @@ mod tests { use crate::{ algorithms::approx::{Approx, Tolerance}, + builder::FaceBuilder, objects::{Face, Objects}, partial::HasPartial, storage::Handle, diff --git a/crates/fj-kernel/src/builder/face.rs b/crates/fj-kernel/src/builder/face.rs new file mode 100644 index 000000000..41f6dc5b1 --- /dev/null +++ b/crates/fj-kernel/src/builder/face.rs @@ -0,0 +1,49 @@ +use fj_math::Point; + +use crate::{ + objects::Cycle, + partial::{HasPartial, PartialFace}, +}; + +use super::CycleBuilder; + +/// Builder API for [`PartialFace`] +pub trait FaceBuilder { + /// Update the [`PartialFace`] with an exterior polygon + fn with_exterior_polygon_from_points( + self, + points: impl IntoIterator>>, + ) -> Self; + + /// Update the [`PartialFace`] with an interior polygon + fn with_interior_polygon_from_points( + self, + points: impl IntoIterator>>, + ) -> Self; +} + +impl FaceBuilder for PartialFace { + fn with_exterior_polygon_from_points( + self, + points: impl IntoIterator>>, + ) -> Self { + let surface = self.surface().expect("Need surface to create polygon"); + + self.with_exterior( + Cycle::partial() + .with_poly_chain_from_points(surface, points) + .close_with_line_segment(), + ) + } + + fn with_interior_polygon_from_points( + self, + points: impl IntoIterator>>, + ) -> Self { + let surface = self.surface().expect("Need surface to build polygon."); + + self.with_interiors([Cycle::partial() + .with_poly_chain_from_points(surface, points) + .close_with_line_segment()]) + } +} diff --git a/crates/fj-kernel/src/builder/mod.rs b/crates/fj-kernel/src/builder/mod.rs index b6cf74d99..1d96e73d7 100644 --- a/crates/fj-kernel/src/builder/mod.rs +++ b/crates/fj-kernel/src/builder/mod.rs @@ -11,12 +11,14 @@ mod solid; mod curve; mod cycle; mod edge; +mod face; mod vertex; pub use self::{ curve::CurveBuilder, cycle::CycleBuilder, edge::{GlobalEdgeBuilder, HalfEdgeBuilder}, + face::FaceBuilder, shell::ShellBuilder, sketch::SketchBuilder, solid::SolidBuilder, diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs index ef1580478..867519507 100644 --- a/crates/fj-kernel/src/builder/shell.rs +++ b/crates/fj-kernel/src/builder/shell.rs @@ -5,7 +5,7 @@ use fj_math::Scalar; use crate::{ algorithms::transform::TransformObject, - builder::HalfEdgeBuilder, + builder::{FaceBuilder, HalfEdgeBuilder}, objects::{ Curve, Cycle, Face, FaceSet, HalfEdge, Objects, Shell, Surface, SurfaceVertex, Vertex, diff --git a/crates/fj-kernel/src/builder/sketch.rs b/crates/fj-kernel/src/builder/sketch.rs index 7052b4a36..aad2b9620 100644 --- a/crates/fj-kernel/src/builder/sketch.rs +++ b/crates/fj-kernel/src/builder/sketch.rs @@ -6,6 +6,8 @@ use crate::{ storage::Handle, }; +use super::FaceBuilder; + /// API for building a [`Sketch`] /// /// Also see [`Sketch::builder`]. diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index 3be9a3493..6708c96b1 100644 --- a/crates/fj-kernel/src/iter.rs +++ b/crates/fj-kernel/src/iter.rs @@ -360,7 +360,7 @@ impl Iterator for Iter { #[cfg(test)] mod tests { use crate::{ - builder::{CurveBuilder, CycleBuilder, HalfEdgeBuilder}, + builder::{CurveBuilder, CycleBuilder, FaceBuilder, HalfEdgeBuilder}, objects::{ Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Objects, Shell, Sketch, Solid, SurfaceVertex, Vertex, diff --git a/crates/fj-kernel/src/partial/objects/face.rs b/crates/fj-kernel/src/partial/objects/face.rs index 87cf3bb23..c2dbf2a33 100644 --- a/crates/fj-kernel/src/partial/objects/face.rs +++ b/crates/fj-kernel/src/partial/objects/face.rs @@ -1,10 +1,8 @@ use fj_interop::mesh::Color; -use fj_math::Point; use crate::{ - builder::CycleBuilder, objects::{Cycle, Face, Objects, Surface}, - partial::{util::merge_options, HasPartial, MaybePartial}, + partial::{util::merge_options, MaybePartial}, storage::Handle, validate::ValidationError, }; @@ -56,20 +54,6 @@ impl PartialFace { self } - /// Build the [`Face`] with an exterior polygon from the provided points - pub fn with_exterior_polygon_from_points( - self, - points: impl IntoIterator>>, - ) -> Self { - let surface = self.surface().expect("Need surface to create polygon"); - - self.with_exterior( - Cycle::partial() - .with_poly_chain_from_points(surface, points) - .close_with_line_segment(), - ) - } - /// Build the [`Face`] with the provided interior polygons pub fn with_interiors( mut self, @@ -80,18 +64,6 @@ impl PartialFace { self } - /// Build the [`Face`] with an interior polygon from the provided points - pub fn with_interior_polygon_from_points( - self, - points: impl IntoIterator>>, - ) -> Self { - let surface = self.surface().expect("Need surface to build polygon."); - - self.with_interiors([Cycle::partial() - .with_poly_chain_from_points(surface, points) - .close_with_line_segment()]) - } - /// Build the [`Face`] with the provided color pub fn with_color(mut self, color: Color) -> Self { self.color = Some(color); diff --git a/crates/fj-kernel/src/validate/face.rs b/crates/fj-kernel/src/validate/face.rs index f0b0fdd81..098b5ea28 100644 --- a/crates/fj-kernel/src/validate/face.rs +++ b/crates/fj-kernel/src/validate/face.rs @@ -105,7 +105,7 @@ impl FaceValidationError { mod tests { use crate::{ algorithms::reverse::Reverse, - builder::CycleBuilder, + builder::{CycleBuilder, FaceBuilder}, objects::{Cycle, Face, Objects}, partial::HasPartial, validate::Validate, diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index f3ebf3dbd..83ab1911c 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use fj_interop::{debug::DebugInfo, mesh::Color}; use fj_kernel::{ - builder::HalfEdgeBuilder, + builder::{FaceBuilder, HalfEdgeBuilder}, objects::{Cycle, Face, HalfEdge, Objects, Sketch}, partial::HasPartial, validate::ValidationError,