From cf50aac9d03a78daba0821ef24f166d6f17ea051 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 10:40:43 +0100 Subject: [PATCH 01/22] Fix formatting in error message --- crates/fj-kernel/src/validate/vertex.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/validate/vertex.rs b/crates/fj-kernel/src/validate/vertex.rs index 2257510e0..075c57cf1 100644 --- a/crates/fj-kernel/src/validate/vertex.rs +++ b/crates/fj-kernel/src/validate/vertex.rs @@ -51,8 +51,8 @@ pub enum VertexValidationError { /// Mismatch between the surface's of the curve and surface form #[error( "Surface form of vertex must be defined on same surface as curve\n\ - `- Surface` of curve: {curve_surface:#?}\n\ - `- Surface` of surface form: {surface_form_surface:#?}" + - `Surface` of curve: {curve_surface:#?}\n\ + - `Surface` of surface form: {surface_form_surface:#?}" )] SurfaceMismatch { /// The surface of the vertex' curve From 7c1351710aefa58cf6aab120843a257d4dab9c6e Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 10:46:58 +0100 Subject: [PATCH 02/22] Add getters for fields of `PartialGlobalEdge` --- crates/fj-kernel/src/algorithms/transform/edge.rs | 4 ++-- crates/fj-kernel/src/partial/maybe_partial.rs | 4 ++-- crates/fj-kernel/src/partial/objects/edge.rs | 10 ++++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/transform/edge.rs b/crates/fj-kernel/src/algorithms/transform/edge.rs index 2d9b3b95f..407d0ede1 100644 --- a/crates/fj-kernel/src/algorithms/transform/edge.rs +++ b/crates/fj-kernel/src/algorithms/transform/edge.rs @@ -57,9 +57,9 @@ impl TransformObject for PartialGlobalEdge { transform: &Transform, objects: &Objects, ) -> Result { - let curve = self.curve.transform(transform, objects)?; + let curve = self.curve().transform(transform, objects)?; let vertices = self - .vertices + .vertices() .map(|vertices| { vertices.try_map_ext(|vertex| -> Result<_, ValidationError> { vertex.transform(transform, objects) diff --git a/crates/fj-kernel/src/partial/maybe_partial.rs b/crates/fj-kernel/src/partial/maybe_partial.rs index 5b5e43988..0322dfc0b 100644 --- a/crates/fj-kernel/src/partial/maybe_partial.rs +++ b/crates/fj-kernel/src/partial/maybe_partial.rs @@ -144,7 +144,7 @@ impl MaybePartial { pub fn curve(&self) -> MaybePartial { match self { Self::Full(full) => full.curve().clone().into(), - Self::Partial(partial) => partial.curve.clone(), + Self::Partial(partial) => partial.curve(), } } @@ -154,7 +154,7 @@ impl MaybePartial { Self::Full(full) => Some( full.vertices().access_in_normalized_order().map(Into::into), ), - Self::Partial(partial) => partial.vertices.clone(), + Self::Partial(partial) => partial.vertices(), } } } diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 3df61f925..ce626b066 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -328,6 +328,16 @@ pub struct PartialGlobalEdge { } impl PartialGlobalEdge { + /// Access the curve that the [`GlobalEdge`] is defined in + pub fn curve(&self) -> MaybePartial { + self.curve.clone() + } + + /// Access the vertices that bound the [`GlobalEdge`] in the curve + pub fn vertices(&self) -> Option<[MaybePartial; 2]> { + self.vertices.clone() + } + /// Update the partial global edge with the given curve pub fn with_curve( mut self, From 852a8b6e0fbb4c8593ed06eacbba5bed8150e27a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 10:47:14 +0100 Subject: [PATCH 03/22] Make fields of `PartialGlobalEdge` private --- crates/fj-kernel/src/algorithms/transform/edge.rs | 4 +++- crates/fj-kernel/src/partial/objects/edge.rs | 11 ++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/transform/edge.rs b/crates/fj-kernel/src/algorithms/transform/edge.rs index 407d0ede1..c84dc60ac 100644 --- a/crates/fj-kernel/src/algorithms/transform/edge.rs +++ b/crates/fj-kernel/src/algorithms/transform/edge.rs @@ -67,6 +67,8 @@ impl TransformObject for PartialGlobalEdge { }) .transpose()?; - Ok(Self { curve, vertices }) + Ok(Self::default() + .with_curve(Some(curve)) + .with_vertices(vertices)) } } diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index ce626b066..a134e80e2 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -316,15 +316,8 @@ impl From<&HalfEdge> for PartialHalfEdge { /// See [`crate::partial`] for more information. #[derive(Clone, Debug, Default)] pub struct PartialGlobalEdge { - /// The curve that the [`GlobalEdge`] is defined in - /// - /// Must be provided before [`PartialGlobalEdge::build`] is called. - pub curve: MaybePartial, - - /// The vertices that bound the [`GlobalEdge`] in the curve - /// - /// Must be provided before [`PartialGlobalEdge::build`] is called. - pub vertices: Option<[MaybePartial; 2]>, + curve: MaybePartial, + vertices: Option<[MaybePartial; 2]>, } impl PartialGlobalEdge { From f7af714719b33c1f0c07eeab5aa4870b9077da92 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 10:54:09 +0100 Subject: [PATCH 04/22] Add getters for fields of `PartialHalfEdge` --- .../src/algorithms/transform/edge.rs | 9 ++++----- crates/fj-kernel/src/partial/maybe_partial.rs | 4 ++-- crates/fj-kernel/src/partial/objects/cycle.rs | 2 +- crates/fj-kernel/src/partial/objects/edge.rs | 20 +++++++++++++++++++ 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/transform/edge.rs b/crates/fj-kernel/src/algorithms/transform/edge.rs index c84dc60ac..48caa0809 100644 --- a/crates/fj-kernel/src/algorithms/transform/edge.rs +++ b/crates/fj-kernel/src/algorithms/transform/edge.rs @@ -16,17 +16,16 @@ impl TransformObject for PartialHalfEdge { objects: &Objects, ) -> Result { let surface = self - .surface + .surface() .map(|surface| surface.transform(transform, objects)) .transpose()?; let curve: MaybePartial<_> = self - .curve - .clone() + .curve() .into_partial() .transform(transform, objects)? .with_surface(surface.clone()) .into(); - let vertices = self.vertices.clone().try_map_ext( + let vertices = self.vertices().try_map_ext( |vertex| -> Result<_, ValidationError> { Ok(vertex .into_partial() @@ -36,7 +35,7 @@ impl TransformObject for PartialHalfEdge { }, )?; let global_form = self - .global_form + .global_form() .into_partial() .transform(transform, objects)? .with_curve(curve.global_form()) diff --git a/crates/fj-kernel/src/partial/maybe_partial.rs b/crates/fj-kernel/src/partial/maybe_partial.rs index 0322dfc0b..7431df451 100644 --- a/crates/fj-kernel/src/partial/maybe_partial.rs +++ b/crates/fj-kernel/src/partial/maybe_partial.rs @@ -165,7 +165,7 @@ impl MaybePartial { match self { Self::Full(full) => full.front().clone().into(), Self::Partial(partial) => { - let [_, front] = &partial.vertices; + let [_, front] = &partial.vertices(); front.clone() } } @@ -175,7 +175,7 @@ impl MaybePartial { pub fn vertices(&self) -> [MaybePartial; 2] { match self { Self::Full(full) => full.vertices().clone().map(Into::into), - Self::Partial(partial) => partial.vertices.clone(), + Self::Partial(partial) => partial.vertices(), } } } diff --git a/crates/fj-kernel/src/partial/objects/cycle.rs b/crates/fj-kernel/src/partial/objects/cycle.rs index 65c16f6d4..2d4495712 100644 --- a/crates/fj-kernel/src/partial/objects/cycle.rs +++ b/crates/fj-kernel/src/partial/objects/cycle.rs @@ -202,7 +202,7 @@ impl PartialCycle { let half_edge = half_edge .update_partial(|half_edge| { - let [back, _] = half_edge.vertices.clone(); + let [back, _] = half_edge.vertices(); let back = back.update_partial(|partial| { partial.with_surface_form(previous_vertex) }); diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index a134e80e2..b812fe704 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -33,6 +33,26 @@ pub struct PartialHalfEdge { } impl PartialHalfEdge { + /// Access the surface that the [`HalfEdge`]'s [`Curve`] is defined in + pub fn surface(&self) -> Option> { + self.surface.clone() + } + + /// Access the curve that the [`HalfEdge`] is defined in + pub fn curve(&self) -> MaybePartial { + self.curve.clone() + } + + /// Access the vertices that bound this [`HalfEdge`] in the [`Curve`] + pub fn vertices(&self) -> [MaybePartial; 2] { + self.vertices.clone() + } + + /// Access the global form of the [`HalfEdge`] + pub fn global_form(&self) -> MaybePartial { + self.global_form.clone() + } + /// Extract the global curve from either the curve or global form /// /// If a global curve is available through both, the curve is preferred. From 3921ba3067d28cb98302aee28a0cab23d9937216 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 10:55:09 +0100 Subject: [PATCH 05/22] Make fields of `PartialHalfEdge` private --- .../fj-kernel/src/algorithms/transform/edge.rs | 14 ++++++-------- crates/fj-kernel/src/partial/objects/edge.rs | 17 ++++------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/transform/edge.rs b/crates/fj-kernel/src/algorithms/transform/edge.rs index 48caa0809..3e7dac5ae 100644 --- a/crates/fj-kernel/src/algorithms/transform/edge.rs +++ b/crates/fj-kernel/src/algorithms/transform/edge.rs @@ -30,8 +30,7 @@ impl TransformObject for PartialHalfEdge { Ok(vertex .into_partial() .transform(transform, objects)? - .with_curve(Some(curve.clone())) - .into()) + .with_curve(Some(curve.clone()))) }, )?; let global_form = self @@ -41,12 +40,11 @@ impl TransformObject for PartialHalfEdge { .with_curve(curve.global_form()) .into(); - Ok(Self { - surface, - curve, - vertices, - global_form, - }) + Ok(Self::default() + .with_surface(surface) + .with_curve(Some(curve)) + .with_vertices(Some(vertices)) + .with_global_form(global_form)) } } diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index b812fe704..43a84a56c 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -17,19 +17,10 @@ use crate::{ /// See [`crate::partial`] for more information. #[derive(Clone, Debug, Default)] pub struct PartialHalfEdge { - /// The surface that the [`HalfEdge`]'s [`Curve`] is defined in - pub surface: Option>, - - /// The curve that the [`HalfEdge`] is defined in - pub curve: MaybePartial, - - /// The vertices that bound this [`HalfEdge`] in the [`Curve`] - pub vertices: [MaybePartial; 2], - - /// The global form of the [`HalfEdge`] - /// - /// Can be computed by [`PartialHalfEdge::build`], if not available. - pub global_form: MaybePartial, + surface: Option>, + curve: MaybePartial, + vertices: [MaybePartial; 2], + global_form: MaybePartial, } impl PartialHalfEdge { From defaabb1819606022bdcaad272cdd19cc8ef0c0c Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:11:39 +0100 Subject: [PATCH 06/22] Fix argument name --- crates/fj-kernel/src/partial/objects/cycle.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/cycle.rs b/crates/fj-kernel/src/partial/objects/cycle.rs index 2d4495712..1ad0da44a 100644 --- a/crates/fj-kernel/src/partial/objects/cycle.rs +++ b/crates/fj-kernel/src/partial/objects/cycle.rs @@ -34,10 +34,10 @@ impl PartialCycle { /// Update the partial cycle with the given half-edges pub fn with_half_edges( mut self, - half_edge: impl IntoIterator>>, + half_edges: impl IntoIterator>>, ) -> Self { self.half_edges - .extend(half_edge.into_iter().map(Into::into)); + .extend(half_edges.into_iter().map(Into::into)); self } From 61440ad828aeaa0bcef47547b0941306c73010d8 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:13:34 +0100 Subject: [PATCH 07/22] Add getters for fields of `PartialCycle` --- crates/fj-kernel/src/algorithms/transform/cycle.rs | 6 ++---- crates/fj-kernel/src/partial/objects/cycle.rs | 10 ++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/transform/cycle.rs b/crates/fj-kernel/src/algorithms/transform/cycle.rs index c515fb807..9527fbb4f 100644 --- a/crates/fj-kernel/src/algorithms/transform/cycle.rs +++ b/crates/fj-kernel/src/algorithms/transform/cycle.rs @@ -13,13 +13,11 @@ impl TransformObject for PartialCycle { objects: &Objects, ) -> Result { let surface = self - .surface - .clone() + .surface() .map(|surface| surface.transform(transform, objects)) .transpose()?; let half_edges = self - .half_edges - .into_iter() + .half_edges() .map(|edge| { Ok(edge .into_partial() diff --git a/crates/fj-kernel/src/partial/objects/cycle.rs b/crates/fj-kernel/src/partial/objects/cycle.rs index 1ad0da44a..1d84c4199 100644 --- a/crates/fj-kernel/src/partial/objects/cycle.rs +++ b/crates/fj-kernel/src/partial/objects/cycle.rs @@ -23,6 +23,16 @@ pub struct PartialCycle { } impl PartialCycle { + /// Access the surface that the [`Cycle`] is defined in + pub fn surface(&self) -> Option> { + self.surface.clone() + } + + /// Access the half-edges that make up the [`Cycle`] + pub fn half_edges(&self) -> impl Iterator> { + self.half_edges.clone().into_iter() + } + /// Update the partial cycle with the given surface pub fn with_surface(mut self, surface: Option>) -> Self { if let Some(surface) = surface { From daae0efb3bb5d025c68ae39ae29435347edd344c Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:15:20 +0100 Subject: [PATCH 08/22] Make fields of `PartialCycle` private --- crates/fj-kernel/src/algorithms/transform/cycle.rs | 12 +++++------- crates/fj-kernel/src/partial/objects/cycle.rs | 7 ++----- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/transform/cycle.rs b/crates/fj-kernel/src/algorithms/transform/cycle.rs index 9527fbb4f..1cbf50694 100644 --- a/crates/fj-kernel/src/algorithms/transform/cycle.rs +++ b/crates/fj-kernel/src/algorithms/transform/cycle.rs @@ -22,14 +22,12 @@ impl TransformObject for PartialCycle { Ok(edge .into_partial() .transform(transform, objects)? - .with_surface(surface.clone()) - .into()) + .with_surface(surface.clone())) }) - .collect::>()?; + .collect::, ValidationError>>()?; - Ok(Self { - surface, - half_edges, - }) + Ok(Self::default() + .with_surface(surface) + .with_half_edges(half_edges)) } } diff --git a/crates/fj-kernel/src/partial/objects/cycle.rs b/crates/fj-kernel/src/partial/objects/cycle.rs index 1d84c4199..5f4c900a7 100644 --- a/crates/fj-kernel/src/partial/objects/cycle.rs +++ b/crates/fj-kernel/src/partial/objects/cycle.rs @@ -15,11 +15,8 @@ use crate::{ /// See [`crate::partial`] for more information. #[derive(Clone, Debug, Default)] pub struct PartialCycle { - /// The surface that the [`Cycle`] is defined in - pub surface: Option>, - - /// The half-edges that make up the [`Cycle`] - pub half_edges: Vec>, + surface: Option>, + half_edges: Vec>, } impl PartialCycle { From 920e48c9d9aa77e2841839301157522f9ef60469 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:25:44 +0100 Subject: [PATCH 09/22] Extract builder method from `PartialGlobalEdge` --- crates/fj-kernel/src/builder/edge.rs | 29 ++++++++++++++++++++ crates/fj-kernel/src/builder/mod.rs | 2 ++ crates/fj-kernel/src/partial/objects/edge.rs | 14 +--------- 3 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 crates/fj-kernel/src/builder/edge.rs diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs new file mode 100644 index 000000000..09707f7fe --- /dev/null +++ b/crates/fj-kernel/src/builder/edge.rs @@ -0,0 +1,29 @@ +use crate::{ + objects::{Curve, Vertex}, + partial::PartialGlobalEdge, + storage::Handle, +}; + +/// Builder API for [`PartialGlobalEdge`] +#[allow(clippy::wrong_self_convention)] +pub trait GlobalEdgeBuilder { + /// Update partial global edge from the given curve and vertices + fn from_curve_and_vertices( + self, + curve: &Curve, + vertices: &[Handle; 2], + ) -> Self; +} + +impl GlobalEdgeBuilder for PartialGlobalEdge { + fn from_curve_and_vertices( + self, + curve: &Curve, + vertices: &[Handle; 2], + ) -> Self { + self.with_curve(Some(curve.global_form().clone())) + .with_vertices(Some( + vertices.clone().map(|vertex| vertex.global_form().clone()), + )) + } +} diff --git a/crates/fj-kernel/src/builder/mod.rs b/crates/fj-kernel/src/builder/mod.rs index ab4abf95d..b479d5fa2 100644 --- a/crates/fj-kernel/src/builder/mod.rs +++ b/crates/fj-kernel/src/builder/mod.rs @@ -10,10 +10,12 @@ mod solid; // These are new-style builders that build on top of the partial object API. mod curve; +mod edge; mod vertex; pub use self::{ curve::CurveBuilder, + edge::GlobalEdgeBuilder, face::FaceBuilder, shell::ShellBuilder, sketch::SketchBuilder, diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 43a84a56c..1d725ac69 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -2,7 +2,7 @@ use fj_interop::ext::ArrayExt; use fj_math::{Point, Scalar}; use crate::{ - builder::{CurveBuilder, GlobalVertexBuilder}, + builder::{CurveBuilder, GlobalVertexBuilder, GlobalEdgeBuilder}, objects::{ Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects, Surface, SurfaceVertex, Vertex, VerticesInNormalizedOrder, @@ -364,18 +364,6 @@ impl PartialGlobalEdge { self } - /// Update partial global edge from the given curve and vertices - pub fn from_curve_and_vertices( - self, - curve: &Curve, - vertices: &[Handle; 2], - ) -> Self { - self.with_curve(Some(curve.global_form().clone())) - .with_vertices(Some( - vertices.clone().map(|vertex| vertex.global_form().clone()), - )) - } - /// Build a full [`GlobalEdge`] from the partial global edge pub fn build( self, From d87a11a4e4d9219e2c84d383ad0062570f367025 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:26:41 +0100 Subject: [PATCH 10/22] Improve method name --- crates/fj-kernel/src/builder/edge.rs | 5 ++--- crates/fj-kernel/src/partial/objects/edge.rs | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 09707f7fe..f5a3f9d8a 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -5,10 +5,9 @@ use crate::{ }; /// Builder API for [`PartialGlobalEdge`] -#[allow(clippy::wrong_self_convention)] pub trait GlobalEdgeBuilder { /// Update partial global edge from the given curve and vertices - fn from_curve_and_vertices( + fn update_from_curve_and_vertices( self, curve: &Curve, vertices: &[Handle; 2], @@ -16,7 +15,7 @@ pub trait GlobalEdgeBuilder { } impl GlobalEdgeBuilder for PartialGlobalEdge { - fn from_curve_and_vertices( + fn update_from_curve_and_vertices( self, curve: &Curve, vertices: &[Handle; 2], diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 1d725ac69..4840d11e9 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -2,7 +2,7 @@ use fj_interop::ext::ArrayExt; use fj_math::{Point, Scalar}; use crate::{ - builder::{CurveBuilder, GlobalVertexBuilder, GlobalEdgeBuilder}, + builder::{CurveBuilder, GlobalEdgeBuilder, GlobalVertexBuilder}, objects::{ Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects, Surface, SurfaceVertex, Vertex, VerticesInNormalizedOrder, @@ -298,7 +298,7 @@ impl PartialHalfEdge { let global_form = self .global_form .update_partial(|partial| { - partial.from_curve_and_vertices(&curve, &vertices) + partial.update_from_curve_and_vertices(&curve, &vertices) }) .into_full(objects)?; From 0cce6a50a15935a976462c2acad7e26dd4171723 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:27:32 +0100 Subject: [PATCH 11/22] Improve method name --- crates/fj-kernel/src/partial/objects/edge.rs | 2 +- crates/fj-operations/src/sketch.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 4840d11e9..98246d119 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -133,7 +133,7 @@ impl PartialHalfEdge { /// In principle, only the `build` method should take a reference to /// [`Objects`]. As of this writing, this method is the only one that /// deviates from that. I couldn't think of a way to do it better. - pub fn as_circle_from_radius( + pub fn update_as_circle_from_radius( mut self, radius: impl Into, objects: &Objects, diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 3f91514ca..e94d77ed2 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -28,7 +28,7 @@ impl Shape for fj::Sketch { let half_edge = HalfEdge::partial() .with_surface(Some(surface)) - .as_circle_from_radius(circle.radius(), objects)? + .update_as_circle_from_radius(circle.radius(), objects)? .build(objects)?; let cycle = objects.cycles.insert(Cycle::new([half_edge]))?; From 84be57e104c5cbc30c3f955e80cd690e0860ee35 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:28:01 +0100 Subject: [PATCH 12/22] Improve method name --- crates/fj-kernel/src/algorithms/intersect/curve_edge.rs | 8 ++++---- crates/fj-kernel/src/algorithms/sweep/edge.rs | 4 ++-- crates/fj-kernel/src/algorithms/sweep/face.rs | 4 ++-- crates/fj-kernel/src/algorithms/sweep/vertex.rs | 2 +- crates/fj-kernel/src/builder/shell.rs | 5 ++++- crates/fj-kernel/src/iter.rs | 2 +- crates/fj-kernel/src/objects/edge.rs | 4 ++-- crates/fj-kernel/src/partial/objects/cycle.rs | 2 +- crates/fj-kernel/src/partial/objects/edge.rs | 2 +- crates/fj-kernel/src/validate/edge.rs | 8 ++++---- 10 files changed, 22 insertions(+), 19 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs index 55486f2ee..4be1af326 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs @@ -93,7 +93,7 @@ mod tests { .build(&objects)?; let half_edge = HalfEdge::partial() .with_surface(Some(surface)) - .as_line_segment_from_points([[1., -1.], [1., 1.]]) + .update_as_line_segment_from_points([[1., -1.], [1., 1.]]) .build(&objects)?; let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -118,7 +118,7 @@ mod tests { .build(&objects)?; let half_edge = HalfEdge::partial() .with_surface(Some(surface)) - .as_line_segment_from_points([[-1., -1.], [-1., 1.]]) + .update_as_line_segment_from_points([[-1., -1.], [-1., 1.]]) .build(&objects)?; let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -143,7 +143,7 @@ mod tests { .build(&objects)?; let half_edge = HalfEdge::partial() .with_surface(Some(surface)) - .as_line_segment_from_points([[-1., -1.], [1., -1.]]) + .update_as_line_segment_from_points([[-1., -1.], [1., -1.]]) .build(&objects)?; let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -163,7 +163,7 @@ mod tests { .build(&objects)?; let half_edge = HalfEdge::partial() .with_surface(Some(surface)) - .as_line_segment_from_points([[-1., 0.], [1., 0.]]) + .update_as_line_segment_from_points([[-1., 0.], [1., 0.]]) .build(&objects)?; let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index 6aeeafe3c..f914d7b53 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -199,7 +199,7 @@ mod tests { let half_edge = HalfEdge::partial() .with_surface(Some(objects.surfaces.xy_plane())) - .as_line_segment_from_points([[0., 0.], [1., 0.]]) + .update_as_line_segment_from_points([[0., 0.], [1., 0.]]) .build(&objects)?; let face = @@ -210,7 +210,7 @@ mod tests { let bottom = HalfEdge::partial() .with_surface(Some(surface.clone())) - .as_line_segment_from_points([[0., 0.], [1., 0.]]) + .update_as_line_segment_from_points([[0., 0.], [1., 0.]]) .build(&objects)?; let side_up = HalfEdge::partial() .with_surface(Some(surface.clone())) diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index ef79f1a1b..26266ab4c 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -125,7 +125,7 @@ mod tests { .map(|&[a, b]| { let half_edge = HalfEdge::partial() .with_surface(Some(objects.surfaces.xy_plane())) - .as_line_segment_from_points([a, b]) + .update_as_line_segment_from_points([a, b]) .build(&objects)?; (half_edge, Color::default()).sweep(UP, &objects) }) @@ -167,7 +167,7 @@ mod tests { .map(|&[a, b]| { let half_edge = HalfEdge::partial() .with_surface(Some(objects.surfaces.xy_plane())) - .as_line_segment_from_points([a, b]) + .update_as_line_segment_from_points([a, b]) .build(&objects)? .reverse(&objects)?; (half_edge, Color::default()).sweep(DOWN, &objects) diff --git a/crates/fj-kernel/src/algorithms/sweep/vertex.rs b/crates/fj-kernel/src/algorithms/sweep/vertex.rs index 8b55c5d46..315e61d1d 100644 --- a/crates/fj-kernel/src/algorithms/sweep/vertex.rs +++ b/crates/fj-kernel/src/algorithms/sweep/vertex.rs @@ -192,7 +192,7 @@ mod tests { let expected_half_edge = HalfEdge::partial() .with_surface(Some(surface)) - .as_line_segment_from_points([[0., 0.], [0., 1.]]) + .update_as_line_segment_from_points([[0., 0.], [0., 1.]]) .build(&objects)?; assert_eq!(half_edge, expected_half_edge); Ok(()) diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs index 029284398..769c208aa 100644 --- a/crates/fj-kernel/src/builder/shell.rs +++ b/crates/fj-kernel/src/builder/shell.rs @@ -90,7 +90,10 @@ impl<'a> ShellBuilder<'a> { HalfEdge::partial() .with_surface(Some(surface.clone())) .with_global_form(Some(half_edge.global_form().clone())) - .as_line_segment_from_points([[Z, Z], [edge_length, Z]]) + .update_as_line_segment_from_points([ + [Z, Z], + [edge_length, Z], + ]) .build(self.objects) .unwrap() }) diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index 2538869c6..c17c5e9e6 100644 --- a/crates/fj-kernel/src/iter.rs +++ b/crates/fj-kernel/src/iter.rs @@ -486,7 +486,7 @@ mod tests { let object = HalfEdge::partial() .with_surface(Some(objects.surfaces.xy_plane())) - .as_line_segment_from_points([[0., 0.], [1., 0.]]) + .update_as_line_segment_from_points([[0., 0.], [1., 0.]]) .build(&objects); assert_eq!(1, object.curve_iter().count()); diff --git a/crates/fj-kernel/src/objects/edge.rs b/crates/fj-kernel/src/objects/edge.rs index 2eb6e1bcd..beec41fac 100644 --- a/crates/fj-kernel/src/objects/edge.rs +++ b/crates/fj-kernel/src/objects/edge.rs @@ -164,11 +164,11 @@ mod tests { let a_to_b = HalfEdge::partial() .with_surface(Some(surface.clone())) - .as_line_segment_from_points([a, b]) + .update_as_line_segment_from_points([a, b]) .build(&objects)?; let b_to_a = HalfEdge::partial() .with_surface(Some(surface)) - .as_line_segment_from_points([b, a]) + .update_as_line_segment_from_points([b, a]) .build(&objects)?; assert_eq!(a_to_b.global_form(), b_to_a.global_form()); diff --git a/crates/fj-kernel/src/partial/objects/cycle.rs b/crates/fj-kernel/src/partial/objects/cycle.rs index 5f4c900a7..055797cf2 100644 --- a/crates/fj-kernel/src/partial/objects/cycle.rs +++ b/crates/fj-kernel/src/partial/objects/cycle.rs @@ -151,7 +151,7 @@ impl PartialCycle { self.half_edges.push( HalfEdge::partial() .with_surface(Some(surface)) - .as_line_segment_from_points(vertices) + .update_as_line_segment_from_points(vertices) .into(), ); } diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 98246d119..2c164efc4 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -178,7 +178,7 @@ impl PartialHalfEdge { } /// Update partial half-edge as a line segment, from the given points - pub fn as_line_segment_from_points( + pub fn update_as_line_segment_from_points( self, points: [impl Into>; 2], ) -> Self { diff --git a/crates/fj-kernel/src/validate/edge.rs b/crates/fj-kernel/src/validate/edge.rs index fddd9a618..bf1a24982 100644 --- a/crates/fj-kernel/src/validate/edge.rs +++ b/crates/fj-kernel/src/validate/edge.rs @@ -208,7 +208,7 @@ mod tests { let valid = HalfEdge::partial() .with_surface(Some(objects.surfaces.xy_plane())) - .as_line_segment_from_points([[0., 0.], [1., 0.]]) + .update_as_line_segment_from_points([[0., 0.], [1., 0.]]) .build(&objects)?; let invalid = { let mut vertices = valid.vertices().clone(); @@ -233,7 +233,7 @@ mod tests { let valid = HalfEdge::partial() .with_surface(Some(objects.surfaces.xy_plane())) - .as_line_segment_from_points([[0., 0.], [1., 0.]]) + .update_as_line_segment_from_points([[0., 0.], [1., 0.]]) .build(&objects)?; let invalid = HalfEdge::new( valid.vertices().clone(), @@ -256,7 +256,7 @@ mod tests { let valid = HalfEdge::partial() .with_surface(Some(objects.surfaces.xy_plane())) - .as_line_segment_from_points([[0., 0.], [1., 0.]]) + .update_as_line_segment_from_points([[0., 0.], [1., 0.]]) .build(&objects)?; let invalid = HalfEdge::new( valid.vertices().clone(), @@ -286,7 +286,7 @@ mod tests { let valid = HalfEdge::partial() .with_surface(Some(objects.surfaces.xy_plane())) - .as_line_segment_from_points([[0., 0.], [1., 0.]]) + .update_as_line_segment_from_points([[0., 0.], [1., 0.]]) .build(&objects)?; let invalid = HalfEdge::new( valid.vertices().clone().try_map_ext(|vertex| { From 2373589b7bf44c9c53cb990767700b67208a368b Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:28:29 +0100 Subject: [PATCH 13/22] Improve method name --- crates/fj-kernel/src/algorithms/sweep/edge.rs | 6 +++--- crates/fj-kernel/src/builder/shell.rs | 8 ++++---- crates/fj-kernel/src/partial/objects/edge.rs | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index f914d7b53..24b8b50f3 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -222,7 +222,7 @@ mod tests { SurfaceVertex::partial().with_position(Some([1., 1.])), ), ))) - .as_line_segment() + .update_as_line_segment() .build(&objects)?; let top = HalfEdge::partial() .with_surface(Some(surface.clone())) @@ -234,7 +234,7 @@ mod tests { .with_front_vertex(Some(Vertex::partial().with_surface_form( Some(side_up.front().surface_form().clone()), ))) - .as_line_segment() + .update_as_line_segment() .build(&objects)? .reverse(&objects)?; let side_down = HalfEdge::partial() @@ -245,7 +245,7 @@ mod tests { .with_front_vertex(Some(Vertex::partial().with_surface_form( Some(top.front().surface_form().clone()), ))) - .as_line_segment() + .update_as_line_segment() .build(&objects)? .reverse(&objects)?; diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs index 769c208aa..25597d883 100644 --- a/crates/fj-kernel/src/builder/shell.rs +++ b/crates/fj-kernel/src/builder/shell.rs @@ -116,7 +116,7 @@ impl<'a> ShellBuilder<'a> { Vertex::partial().with_surface_form(Some(from)), Vertex::partial().with_surface_form(Some(to)), ])) - .as_line_segment() + .update_as_line_segment() .build(self.objects) .unwrap() }) @@ -153,7 +153,7 @@ impl<'a> ShellBuilder<'a> { Vertex::partial().with_surface_form(Some(from)), Vertex::partial().with_surface_form(Some(to)), ])) - .as_line_segment() + .update_as_line_segment() .build(self.objects) .unwrap() }) @@ -176,7 +176,7 @@ impl<'a> ShellBuilder<'a> { HalfEdge::partial() .with_vertices(Some([from, to])) - .as_line_segment() + .update_as_line_segment() .build(self.objects) .unwrap() }) @@ -255,7 +255,7 @@ impl<'a> ShellBuilder<'a> { HalfEdge::partial() .with_vertices(Some(vertices)) .with_global_form(Some(edge.global_form().clone())) - .as_line_segment() + .update_as_line_segment() .build(self.objects) .unwrap(), ); diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 2c164efc4..d4dded0a4 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -191,11 +191,11 @@ impl PartialHalfEdge { Vertex::partial().with_surface_form(Some(surface_form)) }); - self.with_vertices(Some(vertices)).as_line_segment() + self.with_vertices(Some(vertices)).update_as_line_segment() } /// Update partial half-edge as a line segment, reusing existing vertices - pub fn as_line_segment(mut self) -> Self { + pub fn update_as_line_segment(mut self) -> Self { let [from, to] = self.vertices.clone(); let [from_surface, to_surface] = [&from, &to].map(|vertex| vertex.surface_form()); From c79cf7181420aa0c9a57e69deacf56bf1804051e Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:35:56 +0100 Subject: [PATCH 14/22] Refactor --- crates/fj-kernel/src/partial/objects/edge.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index d4dded0a4..88ddf111c 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -134,7 +134,7 @@ impl PartialHalfEdge { /// [`Objects`]. As of this writing, this method is the only one that /// deviates from that. I couldn't think of a way to do it better. pub fn update_as_circle_from_radius( - mut self, + self, radius: impl Into, objects: &Objects, ) -> Result { @@ -168,13 +168,11 @@ impl PartialHalfEdge { .with_position(Some(point_curve)) .with_curve(Some(curve.clone())) .with_surface_form(Some(surface_vertex.clone())) - .into() }); - self.curve = curve.into(); - self.vertices = [back, front]; - - Ok(self) + Ok(self + .with_curve(Some(curve)) + .with_vertices(Some([back, front]))) } /// Update partial half-edge as a line segment, from the given points From 6f81dd62d46357c15fa951594cd177904bdbd63d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:36:20 +0100 Subject: [PATCH 15/22] Make use of `PartialHalfEdge` getters --- crates/fj-kernel/src/partial/objects/edge.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 88ddf111c..440ea24d7 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -140,7 +140,7 @@ impl PartialHalfEdge { ) -> Result { let curve = Curve::partial() .with_global_form(Some(self.extract_global_curve())) - .with_surface(self.surface.clone()) + .with_surface(self.surface()) .update_as_circle_from_radius(radius); let path = curve.path().expect("Expected path that was just created"); @@ -159,7 +159,7 @@ impl PartialHalfEdge { let surface_vertex = SurfaceVertex::partial() .with_position(Some(path.point_from_path_coords(a_curve))) - .with_surface(self.surface.clone()) + .with_surface(self.surface()) .with_global_form(Some(global_vertex)) .build(objects)?; @@ -180,7 +180,7 @@ impl PartialHalfEdge { self, points: [impl Into>; 2], ) -> Self { - let surface = self.surface.clone(); + let surface = self.surface(); let vertices = points.map(|point| { let surface_form = SurfaceVertex::partial() .with_surface(surface.clone()) @@ -194,13 +194,12 @@ impl PartialHalfEdge { /// Update partial half-edge as a line segment, reusing existing vertices pub fn update_as_line_segment(mut self) -> Self { - let [from, to] = self.vertices.clone(); + let [from, to] = self.vertices(); let [from_surface, to_surface] = [&from, &to].map(|vertex| vertex.surface_form()); let surface = self - .surface - .clone() + .surface() .or_else(|| from_surface.surface()) .or_else(|| to_surface.surface()) .expect("Can't infer line segment without a surface"); From d161bec85aef86b35909e4ce552c6e843d3f0caf Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:39:12 +0100 Subject: [PATCH 16/22] Refactor --- crates/fj-kernel/src/partial/objects/edge.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 440ea24d7..880015d38 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -193,7 +193,7 @@ impl PartialHalfEdge { } /// Update partial half-edge as a line segment, reusing existing vertices - pub fn update_as_line_segment(mut self) -> Self { + pub fn update_as_line_segment(self) -> Self { let [from, to] = self.vertices(); let [from_surface, to_surface] = [&from, &to].map(|vertex| vertex.surface_form()); @@ -270,10 +270,8 @@ impl PartialHalfEdge { }) }; - self.curve = curve.into(); - self.vertices = [back, front]; - - self + self.with_curve(Some(curve)) + .with_vertices(Some([back, front])) } /// Build a full [`HalfEdge`] from the partial half-edge From 5f9a477482ae3cf0e1a11d0a468f48f6c9cab882 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 11:40:20 +0100 Subject: [PATCH 17/22] Extract builder methods from `PartialHalfEdge` --- .../src/algorithms/intersect/curve_edge.rs | 2 +- crates/fj-kernel/src/algorithms/sweep/edge.rs | 1 + crates/fj-kernel/src/algorithms/sweep/face.rs | 1 + .../fj-kernel/src/algorithms/sweep/vertex.rs | 2 +- crates/fj-kernel/src/builder/edge.rs | 179 +++++++++++++++++- crates/fj-kernel/src/builder/mod.rs | 2 +- crates/fj-kernel/src/builder/shell.rs | 1 + crates/fj-kernel/src/iter.rs | 2 +- crates/fj-kernel/src/objects/edge.rs | 4 +- crates/fj-kernel/src/partial/objects/cycle.rs | 2 +- crates/fj-kernel/src/partial/objects/edge.rs | 155 +-------------- crates/fj-kernel/src/validate/edge.rs | 2 +- crates/fj-operations/src/sketch.rs | 1 + 13 files changed, 193 insertions(+), 161 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs index 4be1af326..065e7f44c 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs @@ -75,7 +75,7 @@ mod tests { use fj_math::Point; use crate::{ - builder::CurveBuilder, + builder::{CurveBuilder, HalfEdgeBuilder}, objects::{Curve, HalfEdge, Objects}, partial::HasPartial, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index 24b8b50f3..40b44d62d 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -189,6 +189,7 @@ mod tests { use crate::{ algorithms::{reverse::Reverse, sweep::Sweep}, + builder::HalfEdgeBuilder, objects::{Cycle, Face, HalfEdge, Objects, SurfaceVertex, Vertex}, partial::HasPartial, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 26266ab4c..2a95a7438 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -84,6 +84,7 @@ mod tests { use crate::{ algorithms::{reverse::Reverse, transform::TransformObject}, + builder::HalfEdgeBuilder, objects::{Face, HalfEdge, Objects, Sketch}, partial::HasPartial, }; diff --git a/crates/fj-kernel/src/algorithms/sweep/vertex.rs b/crates/fj-kernel/src/algorithms/sweep/vertex.rs index 315e61d1d..9946dc987 100644 --- a/crates/fj-kernel/src/algorithms/sweep/vertex.rs +++ b/crates/fj-kernel/src/algorithms/sweep/vertex.rs @@ -168,7 +168,7 @@ mod tests { use crate::{ algorithms::sweep::Sweep, - builder::CurveBuilder, + builder::{CurveBuilder, HalfEdgeBuilder}, objects::{Curve, HalfEdge, Objects, Vertex}, partial::HasPartial, }; diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index f5a3f9d8a..e23263f9c 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -1,9 +1,184 @@ +use fj_interop::ext::ArrayExt; +use fj_math::{Point, Scalar}; + use crate::{ - objects::{Curve, Vertex}, - partial::PartialGlobalEdge, + objects::{ + Curve, GlobalVertex, Objects, SurfaceVertex, Vertex, + VerticesInNormalizedOrder, + }, + partial::{HasPartial, PartialGlobalEdge, PartialHalfEdge}, storage::Handle, + validate::ValidationError, }; +use super::{CurveBuilder, GlobalVertexBuilder}; + +/// Builder API for [`PartialHalfEdge`] +pub trait HalfEdgeBuilder: Sized { + /// Update partial half-edge as a circle, from the given radius + /// + /// # Implementation Note + /// + /// In principle, only the `build` method should take a reference to + /// [`Objects`]. As of this writing, this method is the only one that + /// deviates from that. I couldn't think of a way to do it better. + fn update_as_circle_from_radius( + self, + radius: impl Into, + objects: &Objects, + ) -> Result; + + /// Update partial half-edge as a line segment, from the given points + fn update_as_line_segment_from_points( + self, + points: [impl Into>; 2], + ) -> Self; + + /// Update partial half-edge as a line segment, reusing existing vertices + fn update_as_line_segment(self) -> Self; +} + +impl HalfEdgeBuilder for PartialHalfEdge { + fn update_as_circle_from_radius( + self, + radius: impl Into, + objects: &Objects, + ) -> Result { + let curve = Curve::partial() + .with_global_form(Some(self.extract_global_curve())) + .with_surface(self.surface()) + .update_as_circle_from_radius(radius); + + let path = curve.path().expect("Expected path that was just created"); + + let [a_curve, b_curve] = + [Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord])); + + let global_vertex = self + .extract_global_vertices() + .map(|[global_form, _]| global_form) + .unwrap_or_else(|| { + GlobalVertex::partial() + .update_from_curve_and_position(curve.clone(), a_curve) + .into() + }); + + let surface_vertex = SurfaceVertex::partial() + .with_position(Some(path.point_from_path_coords(a_curve))) + .with_surface(self.surface()) + .with_global_form(Some(global_vertex)) + .build(objects)?; + + let [back, front] = [a_curve, b_curve].map(|point_curve| { + Vertex::partial() + .with_position(Some(point_curve)) + .with_curve(Some(curve.clone())) + .with_surface_form(Some(surface_vertex.clone())) + }); + + Ok(self + .with_curve(Some(curve)) + .with_vertices(Some([back, front]))) + } + + fn update_as_line_segment_from_points( + self, + points: [impl Into>; 2], + ) -> Self { + let surface = self.surface(); + let vertices = points.map(|point| { + let surface_form = SurfaceVertex::partial() + .with_surface(surface.clone()) + .with_position(Some(point)); + + Vertex::partial().with_surface_form(Some(surface_form)) + }); + + self.with_vertices(Some(vertices)).update_as_line_segment() + } + + fn update_as_line_segment(self) -> Self { + let [from, to] = self.vertices(); + let [from_surface, to_surface] = + [&from, &to].map(|vertex| vertex.surface_form()); + + let surface = self + .surface() + .or_else(|| from_surface.surface()) + .or_else(|| to_surface.surface()) + .expect("Can't infer line segment without a surface"); + let points = [&from_surface, &to_surface].map(|vertex| { + vertex + .position() + .expect("Can't infer line segment without surface position") + }); + + let curve = Curve::partial() + .with_global_form(Some(self.extract_global_curve())) + .with_surface(Some(surface)) + .update_as_line_from_points(points); + + let [back, front] = { + let vertices = [(from, 0.), (to, 1.)].map(|(vertex, position)| { + vertex.update_partial(|vertex| { + vertex + .with_position(Some([position])) + .with_curve(Some(curve.clone())) + }) + }); + + // The global vertices we extracted are in normalized order, which + // means we might need to switch their order here. This is a bit of + // a hack, but I can't think of something better. + let global_forms = { + let must_switch_order = { + let objects = Objects::new(); + let vertices = vertices.clone().map(|vertex| { + vertex + .into_full(&objects) + .unwrap() + .global_form() + .clone() + }); + + let (_, must_switch_order) = + VerticesInNormalizedOrder::new(vertices); + + must_switch_order + }; + + self.extract_global_vertices() + .map( + |[a, b]| { + if must_switch_order { + [b, a] + } else { + [a, b] + } + }, + ) + .map(|[a, b]| [Some(a), Some(b)]) + .unwrap_or([None, None]) + }; + + vertices.zip_ext(global_forms).map(|(vertex, global_form)| { + vertex.update_partial(|vertex| { + vertex.clone().with_surface_form(Some( + vertex.surface_form().update_partial( + |surface_vertex| { + surface_vertex.with_global_form(global_form) + }, + ), + )) + }) + }) + }; + + self.with_curve(Some(curve)) + .with_vertices(Some([back, front])) + } +} + /// Builder API for [`PartialGlobalEdge`] pub trait GlobalEdgeBuilder { /// Update partial global edge from the given curve and vertices diff --git a/crates/fj-kernel/src/builder/mod.rs b/crates/fj-kernel/src/builder/mod.rs index b479d5fa2..4cce10b4f 100644 --- a/crates/fj-kernel/src/builder/mod.rs +++ b/crates/fj-kernel/src/builder/mod.rs @@ -15,7 +15,7 @@ mod vertex; pub use self::{ curve::CurveBuilder, - edge::GlobalEdgeBuilder, + edge::{GlobalEdgeBuilder, HalfEdgeBuilder}, face::FaceBuilder, shell::ShellBuilder, sketch::SketchBuilder, diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs index 25597d883..83c73cf29 100644 --- a/crates/fj-kernel/src/builder/shell.rs +++ b/crates/fj-kernel/src/builder/shell.rs @@ -5,6 +5,7 @@ use fj_math::Scalar; use crate::{ algorithms::transform::TransformObject, + builder::HalfEdgeBuilder, objects::{ Curve, Cycle, Face, FaceSet, HalfEdge, Objects, Shell, Surface, SurfaceVertex, Vertex, diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index c17c5e9e6..05ca0b96d 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, + builder::{CurveBuilder, HalfEdgeBuilder}, objects::{ Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Objects, Shell, Sketch, Solid, SurfaceVertex, Vertex, diff --git a/crates/fj-kernel/src/objects/edge.rs b/crates/fj-kernel/src/objects/edge.rs index beec41fac..5e5dc45fb 100644 --- a/crates/fj-kernel/src/objects/edge.rs +++ b/crates/fj-kernel/src/objects/edge.rs @@ -149,7 +149,9 @@ impl VerticesInNormalizedOrder { mod tests { use pretty_assertions::assert_eq; - use crate::{objects::Objects, partial::HasPartial}; + use crate::{ + builder::HalfEdgeBuilder, objects::Objects, partial::HasPartial, + }; use super::HalfEdge; diff --git a/crates/fj-kernel/src/partial/objects/cycle.rs b/crates/fj-kernel/src/partial/objects/cycle.rs index 055797cf2..82791f33d 100644 --- a/crates/fj-kernel/src/partial/objects/cycle.rs +++ b/crates/fj-kernel/src/partial/objects/cycle.rs @@ -1,7 +1,7 @@ use fj_math::Point; use crate::{ - builder::CurveBuilder, + builder::{CurveBuilder, HalfEdgeBuilder}, objects::{ Curve, Cycle, HalfEdge, Objects, Surface, SurfaceVertex, Vertex, }, diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 880015d38..4265d158c 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -1,13 +1,12 @@ use fj_interop::ext::ArrayExt; -use fj_math::{Point, Scalar}; use crate::{ - builder::{CurveBuilder, GlobalEdgeBuilder, GlobalVertexBuilder}, + builder::GlobalEdgeBuilder, objects::{ Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects, - Surface, SurfaceVertex, Vertex, VerticesInNormalizedOrder, + Surface, Vertex, }, - partial::{HasPartial, MaybePartial}, + partial::MaybePartial, storage::Handle, validate::ValidationError, }; @@ -126,154 +125,6 @@ impl PartialHalfEdge { self } - /// Update partial half-edge as a circle, from the given radius - /// - /// # Implementation Note - /// - /// In principle, only the `build` method should take a reference to - /// [`Objects`]. As of this writing, this method is the only one that - /// deviates from that. I couldn't think of a way to do it better. - pub fn update_as_circle_from_radius( - self, - radius: impl Into, - objects: &Objects, - ) -> Result { - let curve = Curve::partial() - .with_global_form(Some(self.extract_global_curve())) - .with_surface(self.surface()) - .update_as_circle_from_radius(radius); - - let path = curve.path().expect("Expected path that was just created"); - - let [a_curve, b_curve] = - [Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord])); - - let global_vertex = self - .extract_global_vertices() - .map(|[global_form, _]| global_form) - .unwrap_or_else(|| { - GlobalVertex::partial() - .update_from_curve_and_position(curve.clone(), a_curve) - .into() - }); - - let surface_vertex = SurfaceVertex::partial() - .with_position(Some(path.point_from_path_coords(a_curve))) - .with_surface(self.surface()) - .with_global_form(Some(global_vertex)) - .build(objects)?; - - let [back, front] = [a_curve, b_curve].map(|point_curve| { - Vertex::partial() - .with_position(Some(point_curve)) - .with_curve(Some(curve.clone())) - .with_surface_form(Some(surface_vertex.clone())) - }); - - Ok(self - .with_curve(Some(curve)) - .with_vertices(Some([back, front]))) - } - - /// Update partial half-edge as a line segment, from the given points - pub fn update_as_line_segment_from_points( - self, - points: [impl Into>; 2], - ) -> Self { - let surface = self.surface(); - let vertices = points.map(|point| { - let surface_form = SurfaceVertex::partial() - .with_surface(surface.clone()) - .with_position(Some(point)); - - Vertex::partial().with_surface_form(Some(surface_form)) - }); - - self.with_vertices(Some(vertices)).update_as_line_segment() - } - - /// Update partial half-edge as a line segment, reusing existing vertices - pub fn update_as_line_segment(self) -> Self { - let [from, to] = self.vertices(); - let [from_surface, to_surface] = - [&from, &to].map(|vertex| vertex.surface_form()); - - let surface = self - .surface() - .or_else(|| from_surface.surface()) - .or_else(|| to_surface.surface()) - .expect("Can't infer line segment without a surface"); - let points = [&from_surface, &to_surface].map(|vertex| { - vertex - .position() - .expect("Can't infer line segment without surface position") - }); - - let curve = Curve::partial() - .with_global_form(Some(self.extract_global_curve())) - .with_surface(Some(surface)) - .update_as_line_from_points(points); - - let [back, front] = { - let vertices = [(from, 0.), (to, 1.)].map(|(vertex, position)| { - vertex.update_partial(|vertex| { - vertex - .with_position(Some([position])) - .with_curve(Some(curve.clone())) - }) - }); - - // The global vertices we extracted are in normalized order, which - // means we might need to switch their order here. This is a bit of - // a hack, but I can't think of something better. - let global_forms = { - let must_switch_order = { - let objects = Objects::new(); - let vertices = vertices.clone().map(|vertex| { - vertex - .into_full(&objects) - .unwrap() - .global_form() - .clone() - }); - - let (_, must_switch_order) = - VerticesInNormalizedOrder::new(vertices); - - must_switch_order - }; - - self.extract_global_vertices() - .map( - |[a, b]| { - if must_switch_order { - [b, a] - } else { - [a, b] - } - }, - ) - .map(|[a, b]| [Some(a), Some(b)]) - .unwrap_or([None, None]) - }; - - vertices.zip_ext(global_forms).map(|(vertex, global_form)| { - vertex.update_partial(|vertex| { - vertex.clone().with_surface_form(Some( - vertex.surface_form().update_partial( - |surface_vertex| { - surface_vertex.with_global_form(global_form) - }, - ), - )) - }) - }) - }; - - self.with_curve(Some(curve)) - .with_vertices(Some([back, front])) - } - /// Build a full [`HalfEdge`] from the partial half-edge pub fn build( self, diff --git a/crates/fj-kernel/src/validate/edge.rs b/crates/fj-kernel/src/validate/edge.rs index bf1a24982..3f2f2e3ad 100644 --- a/crates/fj-kernel/src/validate/edge.rs +++ b/crates/fj-kernel/src/validate/edge.rs @@ -196,7 +196,7 @@ mod tests { use fj_interop::ext::ArrayExt; use crate::{ - builder::VertexBuilder, + builder::{HalfEdgeBuilder, VertexBuilder}, objects::{GlobalCurve, HalfEdge, Objects}, partial::HasPartial, validate::Validate2, diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index e94d77ed2..0250d1184 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -2,6 +2,7 @@ use std::ops::Deref; use fj_interop::{debug::DebugInfo, mesh::Color}; use fj_kernel::{ + builder::HalfEdgeBuilder, objects::{Cycle, Face, HalfEdge, Objects, Sketch}, partial::HasPartial, validate::{Validate, Validated, ValidationConfig, ValidationError}, From d17d413ec95ac8b414758d751540b0b71fc11ae2 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 12:02:32 +0100 Subject: [PATCH 18/22] Make use of `PartialCycle` getters --- crates/fj-kernel/src/partial/objects/cycle.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/cycle.rs b/crates/fj-kernel/src/partial/objects/cycle.rs index 82791f33d..290257456 100644 --- a/crates/fj-kernel/src/partial/objects/cycle.rs +++ b/crates/fj-kernel/src/partial/objects/cycle.rs @@ -54,7 +54,7 @@ impl PartialCycle { vertices: impl IntoIterator>, ) -> Self { let iter = self - .half_edges + .half_edges() .last() .map(|half_edge| { let [_, last] = half_edge.vertices(); @@ -68,7 +68,7 @@ impl PartialCycle { for vertex_next in iter { if let Some(vertex_prev) = previous { let surface = self - .surface + .surface() .clone() .expect("Need surface to extend cycle with poly-chain"); @@ -132,8 +132,8 @@ impl PartialCycle { /// /// Builds a line segment from the last and first vertex, closing the cycle. pub fn close_with_line_segment(mut self) -> Self { - let first = self.half_edges.first(); - let last = self.half_edges.last(); + let first = self.half_edges().next(); + let last = self.half_edges().last(); let vertices = [first, last] .map(|option| option.map(|half_edge| half_edge.vertices())); @@ -145,8 +145,7 @@ impl PartialCycle { .position() .expect("Need surface position to close cycle") }); - let surface = - self.surface.clone().expect("Need surface to close cycle"); + let surface = self.surface().expect("Need surface to close cycle"); self.half_edges.push( HalfEdge::partial() From d47e15265136ec0ab3ec44ddf5fc230d30c120fa Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 12:03:14 +0100 Subject: [PATCH 19/22] Refactor --- crates/fj-kernel/src/partial/objects/cycle.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/cycle.rs b/crates/fj-kernel/src/partial/objects/cycle.rs index 290257456..b9dbc2b90 100644 --- a/crates/fj-kernel/src/partial/objects/cycle.rs +++ b/crates/fj-kernel/src/partial/objects/cycle.rs @@ -50,7 +50,7 @@ impl PartialCycle { /// Update the partial cycle with a polygonal chain from the provided points pub fn with_poly_chain( - mut self, + self, vertices: impl IntoIterator>, ) -> Self { let iter = self @@ -65,6 +65,7 @@ impl PartialCycle { let mut previous: Option> = None; + let mut half_edges = Vec::new(); for vertex_next in iter { if let Some(vertex_prev) = previous { let surface = self @@ -100,11 +101,10 @@ impl PartialCycle { .with_surface_form(Some(surface_form)) }); - self.half_edges.push( + half_edges.push( HalfEdge::partial() .with_curve(Some(curve)) - .with_vertices(Some([from, to])) - .into(), + .with_vertices(Some([from, to])), ); continue; @@ -113,7 +113,7 @@ impl PartialCycle { previous = Some(vertex_next); } - self + self.with_half_edges(half_edges) } /// Update the partial cycle with a polygonal chain from the provided points From 9a6c72caaf77bbedf6a2d4fc36ebd27fb8da211c Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 12:08:33 +0100 Subject: [PATCH 20/22] Refactor --- crates/fj-kernel/src/partial/objects/cycle.rs | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/cycle.rs b/crates/fj-kernel/src/partial/objects/cycle.rs index b9dbc2b90..0887f8d70 100644 --- a/crates/fj-kernel/src/partial/objects/cycle.rs +++ b/crates/fj-kernel/src/partial/objects/cycle.rs @@ -131,31 +131,30 @@ impl PartialCycle { /// Update the partial cycle by closing it with a line segment /// /// Builds a line segment from the last and first vertex, closing the cycle. - pub fn close_with_line_segment(mut self) -> Self { + pub fn close_with_line_segment(self) -> Self { let first = self.half_edges().next(); let last = self.half_edges().last(); let vertices = [first, last] .map(|option| option.map(|half_edge| half_edge.vertices())); - if let [Some([first, _]), Some([_, last])] = vertices { - let vertices = [last, first].map(|vertex| { - vertex - .surface_form() - .position() - .expect("Need surface position to close cycle") - }); - let surface = self.surface().expect("Need surface to close cycle"); + let [Some([first, _]), Some([_, last])] = vertices else { + return self; + }; - self.half_edges.push( - HalfEdge::partial() - .with_surface(Some(surface)) - .update_as_line_segment_from_points(vertices) - .into(), - ); - } + let vertices = [last, first].map(|vertex| { + vertex + .surface_form() + .position() + .expect("Need surface position to close cycle") + }); + let surface = self.surface().expect("Need surface to close cycle"); - self + self.with_half_edges(Some( + HalfEdge::partial() + .with_surface(Some(surface)) + .update_as_line_segment_from_points(vertices), + )) } /// Build a full [`Cycle`] from the partial cycle From f4bf0aa8cfb8a87be900c420bf36caf6498563fc Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 12:09:45 +0100 Subject: [PATCH 21/22] Extract builder methods from `PartialCycle` --- crates/fj-kernel/src/builder/cycle.rs | 134 ++++++++++++++++++ crates/fj-kernel/src/builder/face.rs | 2 + crates/fj-kernel/src/builder/mod.rs | 2 + crates/fj-kernel/src/iter.rs | 2 +- crates/fj-kernel/src/partial/objects/cycle.rs | 118 +-------------- 5 files changed, 141 insertions(+), 117 deletions(-) create mode 100644 crates/fj-kernel/src/builder/cycle.rs diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs new file mode 100644 index 000000000..5d5a62e87 --- /dev/null +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -0,0 +1,134 @@ +use fj_math::Point; + +use crate::{ + objects::{Curve, HalfEdge, SurfaceVertex, Vertex}, + partial::{HasPartial, MaybePartial, PartialCycle}, +}; + +use super::{CurveBuilder, HalfEdgeBuilder}; + +/// Builder API for [`PartialCycle`] +pub trait CycleBuilder { + /// Update the partial cycle with a polygonal chain from the provided points + fn with_poly_chain( + self, + vertices: impl IntoIterator>, + ) -> Self; + + /// Update the partial cycle with a polygonal chain from the provided points + fn with_poly_chain_from_points( + self, + points: impl IntoIterator>>, + ) -> Self; + + /// Update the partial cycle by closing it with a line segment + /// + /// Builds a line segment from the last and first vertex, closing the cycle. + fn close_with_line_segment(self) -> Self; +} + +impl CycleBuilder for PartialCycle { + fn with_poly_chain( + self, + vertices: impl IntoIterator>, + ) -> Self { + let iter = self + .half_edges() + .last() + .map(|half_edge| { + let [_, last] = half_edge.vertices(); + last.surface_form() + }) + .into_iter() + .chain(vertices); + + let mut previous: Option> = None; + + let mut half_edges = Vec::new(); + for vertex_next in iter { + if let Some(vertex_prev) = previous { + let surface = self + .surface() + .clone() + .expect("Need surface to extend cycle with poly-chain"); + + let position_prev = vertex_prev + .position() + .expect("Need surface position to extend cycle"); + let position_next = vertex_next + .position() + .expect("Need surface position to extend cycle"); + + let from = vertex_prev.update_partial(|partial| { + partial.with_surface(Some(surface.clone())) + }); + let to = vertex_next.update_partial(|partial| { + partial.with_surface(Some(surface.clone())) + }); + + previous = Some(to.clone()); + + let curve = Curve::partial() + .with_surface(Some(surface.clone())) + .update_as_line_from_points([position_prev, position_next]); + + let [from, to] = + [(0., from), (1., to)].map(|(position, surface_form)| { + Vertex::partial() + .with_curve(Some(curve.clone())) + .with_position(Some([position])) + .with_surface_form(Some(surface_form)) + }); + + half_edges.push( + HalfEdge::partial() + .with_curve(Some(curve)) + .with_vertices(Some([from, to])), + ); + + continue; + } + + previous = Some(vertex_next); + } + + self.with_half_edges(half_edges) + } + + fn with_poly_chain_from_points( + self, + points: impl IntoIterator>>, + ) -> Self { + self.with_poly_chain(points.into_iter().map(|position| { + SurfaceVertex::partial() + .with_position(Some(position)) + .into() + })) + } + + fn close_with_line_segment(self) -> Self { + let first = self.half_edges().next(); + let last = self.half_edges().last(); + + let vertices = [first, last] + .map(|option| option.map(|half_edge| half_edge.vertices())); + + let [Some([first, _]), Some([_, last])] = vertices else { + return self; + }; + + let vertices = [last, first].map(|vertex| { + vertex + .surface_form() + .position() + .expect("Need surface position to close cycle") + }); + let surface = self.surface().expect("Need surface to close cycle"); + + self.with_half_edges(Some( + HalfEdge::partial() + .with_surface(Some(surface)) + .update_as_line_segment_from_points(vertices), + )) + } +} diff --git a/crates/fj-kernel/src/builder/face.rs b/crates/fj-kernel/src/builder/face.rs index d68c4f88e..bb34c3768 100644 --- a/crates/fj-kernel/src/builder/face.rs +++ b/crates/fj-kernel/src/builder/face.rs @@ -7,6 +7,8 @@ use crate::{ storage::Handle, }; +use super::CycleBuilder; + /// API for building a [`Face`] /// /// Also see [`Face::builder`]. diff --git a/crates/fj-kernel/src/builder/mod.rs b/crates/fj-kernel/src/builder/mod.rs index 4cce10b4f..9dafd5326 100644 --- a/crates/fj-kernel/src/builder/mod.rs +++ b/crates/fj-kernel/src/builder/mod.rs @@ -10,11 +10,13 @@ mod solid; // These are new-style builders that build on top of the partial object API. mod curve; +mod cycle; mod edge; mod vertex; pub use self::{ curve::CurveBuilder, + cycle::CycleBuilder, edge::{GlobalEdgeBuilder, HalfEdgeBuilder}, face::FaceBuilder, shell::ShellBuilder, diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index 05ca0b96d..718f7c5f0 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, HalfEdgeBuilder}, + builder::{CurveBuilder, CycleBuilder, HalfEdgeBuilder}, objects::{ Curve, Cycle, Face, GlobalCurve, GlobalVertex, HalfEdge, Objects, Shell, Sketch, Solid, SurfaceVertex, Vertex, diff --git a/crates/fj-kernel/src/partial/objects/cycle.rs b/crates/fj-kernel/src/partial/objects/cycle.rs index 0887f8d70..fe2163112 100644 --- a/crates/fj-kernel/src/partial/objects/cycle.rs +++ b/crates/fj-kernel/src/partial/objects/cycle.rs @@ -1,11 +1,6 @@ -use fj_math::Point; - use crate::{ - builder::{CurveBuilder, HalfEdgeBuilder}, - objects::{ - Curve, Cycle, HalfEdge, Objects, Surface, SurfaceVertex, Vertex, - }, - partial::{HasPartial, MaybePartial}, + objects::{Cycle, HalfEdge, Objects, Surface}, + partial::MaybePartial, storage::Handle, validate::ValidationError, }; @@ -48,115 +43,6 @@ impl PartialCycle { self } - /// Update the partial cycle with a polygonal chain from the provided points - pub fn with_poly_chain( - self, - vertices: impl IntoIterator>, - ) -> Self { - let iter = self - .half_edges() - .last() - .map(|half_edge| { - let [_, last] = half_edge.vertices(); - last.surface_form() - }) - .into_iter() - .chain(vertices); - - let mut previous: Option> = None; - - let mut half_edges = Vec::new(); - for vertex_next in iter { - if let Some(vertex_prev) = previous { - let surface = self - .surface() - .clone() - .expect("Need surface to extend cycle with poly-chain"); - - let position_prev = vertex_prev - .position() - .expect("Need surface position to extend cycle"); - let position_next = vertex_next - .position() - .expect("Need surface position to extend cycle"); - - let from = vertex_prev.update_partial(|partial| { - partial.with_surface(Some(surface.clone())) - }); - let to = vertex_next.update_partial(|partial| { - partial.with_surface(Some(surface.clone())) - }); - - previous = Some(to.clone()); - - let curve = Curve::partial() - .with_surface(Some(surface.clone())) - .update_as_line_from_points([position_prev, position_next]); - - let [from, to] = - [(0., from), (1., to)].map(|(position, surface_form)| { - Vertex::partial() - .with_curve(Some(curve.clone())) - .with_position(Some([position])) - .with_surface_form(Some(surface_form)) - }); - - half_edges.push( - HalfEdge::partial() - .with_curve(Some(curve)) - .with_vertices(Some([from, to])), - ); - - continue; - } - - previous = Some(vertex_next); - } - - self.with_half_edges(half_edges) - } - - /// Update the partial cycle with a polygonal chain from the provided points - pub fn with_poly_chain_from_points( - self, - points: impl IntoIterator>>, - ) -> Self { - self.with_poly_chain(points.into_iter().map(|position| { - SurfaceVertex::partial() - .with_position(Some(position)) - .into() - })) - } - - /// Update the partial cycle by closing it with a line segment - /// - /// Builds a line segment from the last and first vertex, closing the cycle. - pub fn close_with_line_segment(self) -> Self { - let first = self.half_edges().next(); - let last = self.half_edges().last(); - - let vertices = [first, last] - .map(|option| option.map(|half_edge| half_edge.vertices())); - - let [Some([first, _]), Some([_, last])] = vertices else { - return self; - }; - - let vertices = [last, first].map(|vertex| { - vertex - .surface_form() - .position() - .expect("Need surface position to close cycle") - }); - let surface = self.surface().expect("Need surface to close cycle"); - - self.with_half_edges(Some( - HalfEdge::partial() - .with_surface(Some(surface)) - .update_as_line_segment_from_points(vertices), - )) - } - /// Build a full [`Cycle`] from the partial cycle pub fn build( mut self, From 32903edf301d19d806308f458ba7bebce04862ec Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 4 Nov 2022 12:11:37 +0100 Subject: [PATCH 22/22] Make method more convenient to call --- crates/fj-kernel/src/builder/cycle.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 5d5a62e87..04251a2fc 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -12,7 +12,7 @@ pub trait CycleBuilder { /// Update the partial cycle with a polygonal chain from the provided points fn with_poly_chain( self, - vertices: impl IntoIterator>, + vertices: impl IntoIterator>>, ) -> Self; /// Update the partial cycle with a polygonal chain from the provided points @@ -30,8 +30,10 @@ pub trait CycleBuilder { impl CycleBuilder for PartialCycle { fn with_poly_chain( self, - vertices: impl IntoIterator>, + vertices: impl IntoIterator>>, ) -> Self { + let vertices = vertices.into_iter().map(Into::into); + let iter = self .half_edges() .last() @@ -100,9 +102,7 @@ impl CycleBuilder for PartialCycle { points: impl IntoIterator>>, ) -> Self { self.with_poly_chain(points.into_iter().map(|position| { - SurfaceVertex::partial() - .with_position(Some(position)) - .into() + SurfaceVertex::partial().with_position(Some(position)) })) }