From 71912fcf835a4efa4616a3936880254ff1131fe3 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 13:30:11 +0100 Subject: [PATCH 01/42] Split `surface_vertices` field of `HalfEdge` This is preparation for removing `end_vertex`. --- crates/fj-kernel/src/objects/full/edge.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/fj-kernel/src/objects/full/edge.rs b/crates/fj-kernel/src/objects/full/edge.rs index c023738cc..e269cb60d 100644 --- a/crates/fj-kernel/src/objects/full/edge.rs +++ b/crates/fj-kernel/src/objects/full/edge.rs @@ -1,4 +1,3 @@ -use fj_interop::ext::ArrayExt; use fj_math::Point; use crate::{ @@ -47,7 +46,8 @@ use crate::{ pub struct HalfEdge { curve: Curve, boundary: [Point<1>; 2], - surface_vertices: [Handle; 2], + start_vertex: Handle, + end_vertex: Handle, global_form: Handle, } @@ -59,10 +59,13 @@ impl HalfEdge { surface_vertices: [Handle; 2], global_form: Handle, ) -> Self { + let [start_vertex, end_vertex] = surface_vertices; + Self { curve, boundary, - surface_vertices, + start_vertex, + end_vertex, global_form, } } @@ -79,13 +82,12 @@ impl HalfEdge { /// Access the vertex from where this half-edge starts pub fn start_vertex(&self) -> &Handle { - let [vertex, _] = self.surface_vertices.each_ref_ext(); - vertex + &self.start_vertex } /// Access the surface vertices that bound the half-edge pub fn surface_vertices(&self) -> [&Handle; 2] { - self.surface_vertices.each_ref_ext() + [&self.start_vertex, &self.end_vertex] } /// Access the global form of the half-edge From 71993b82725b05989ed52ee7cd527b9f86aa2936 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 13:31:13 +0100 Subject: [PATCH 02/42] Add `HalfEdge::end_vertex` --- crates/fj-kernel/src/objects/full/edge.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/fj-kernel/src/objects/full/edge.rs b/crates/fj-kernel/src/objects/full/edge.rs index e269cb60d..380186168 100644 --- a/crates/fj-kernel/src/objects/full/edge.rs +++ b/crates/fj-kernel/src/objects/full/edge.rs @@ -85,6 +85,11 @@ impl HalfEdge { &self.start_vertex } + /// Access the vertex from where this half-edge ends + pub fn end_vertex(&self) -> &Handle { + &self.end_vertex + } + /// Access the surface vertices that bound the half-edge pub fn surface_vertices(&self) -> [&Handle; 2] { [&self.start_vertex, &self.end_vertex] From 2831f0d9f3dd3380a51324b19c1729b20bb890ba Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 13:43:56 +0100 Subject: [PATCH 03/42] Update arguments of `HalfEdge::new` --- crates/fj-kernel/src/algorithms/reverse/cycle.rs | 5 +++-- crates/fj-kernel/src/algorithms/transform/edge.rs | 13 +++++++------ crates/fj-kernel/src/objects/full/edge.rs | 5 ++--- crates/fj-kernel/src/partial/objects/edge.rs | 4 ++-- crates/fj-kernel/src/validate/edge.rs | 6 ++++-- crates/fj-kernel/src/validate/face.rs | 5 ++++- 6 files changed, 22 insertions(+), 16 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/reverse/cycle.rs b/crates/fj-kernel/src/algorithms/reverse/cycle.rs index 84150209f..6af6e9a44 100644 --- a/crates/fj-kernel/src/algorithms/reverse/cycle.rs +++ b/crates/fj-kernel/src/algorithms/reverse/cycle.rs @@ -20,14 +20,15 @@ impl Reverse for Handle { let [a, b] = current.boundary(); [b, a] }; - let surface_vertices = + let [start_vertex, end_vertex] = [next.start_vertex(), current.start_vertex()] .map(Clone::clone); HalfEdge::new( current.curve(), boundary, - surface_vertices, + start_vertex, + end_vertex, current.global_form().clone(), ) .insert(objects) diff --git a/crates/fj-kernel/src/algorithms/transform/edge.rs b/crates/fj-kernel/src/algorithms/transform/edge.rs index eeea338a6..618f107df 100644 --- a/crates/fj-kernel/src/algorithms/transform/edge.rs +++ b/crates/fj-kernel/src/algorithms/transform/edge.rs @@ -18,17 +18,18 @@ impl TransformObject for HalfEdge { // coordinates. let curve = self.curve(); let boundary = self.boundary(); - let surface_vertices = self.surface_vertices().map(|surface_vertex| { - surface_vertex - .clone() - .transform_with_cache(transform, objects, cache) - }); + let [start_vertex, end_vertex] = + self.surface_vertices().map(|surface_vertex| { + surface_vertex + .clone() + .transform_with_cache(transform, objects, cache) + }); let global_form = self .global_form() .clone() .transform_with_cache(transform, objects, cache); - Self::new(curve, boundary, surface_vertices, global_form) + Self::new(curve, boundary, start_vertex, end_vertex, global_form) } } diff --git a/crates/fj-kernel/src/objects/full/edge.rs b/crates/fj-kernel/src/objects/full/edge.rs index 380186168..fc38f6c60 100644 --- a/crates/fj-kernel/src/objects/full/edge.rs +++ b/crates/fj-kernel/src/objects/full/edge.rs @@ -56,11 +56,10 @@ impl HalfEdge { pub fn new( curve: Curve, boundary: [Point<1>; 2], - surface_vertices: [Handle; 2], + start_vertex: Handle, + end_vertex: Handle, global_form: Handle, ) -> Self { - let [start_vertex, end_vertex] = surface_vertices; - Self { curve, boundary, diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 694ec5789..9a6f90904 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -59,12 +59,12 @@ impl PartialObject for PartialHalfEdge { let boundary = self.boundary.map(|point| { point.expect("Can't build `HalfEdge` without boundary positions") }); - let surface_vertices = self + let [start_vertex, end_vertex] = self .surface_vertices .map(|surface_vertex| surface_vertex.build(objects)); let global_form = self.global_form.build(objects); - HalfEdge::new(curve, boundary, surface_vertices, global_form) + HalfEdge::new(curve, boundary, start_vertex, end_vertex, global_form) } } diff --git a/crates/fj-kernel/src/validate/edge.rs b/crates/fj-kernel/src/validate/edge.rs index fef6db70f..f3fe68a33 100644 --- a/crates/fj-kernel/src/validate/edge.rs +++ b/crates/fj-kernel/src/validate/edge.rs @@ -183,7 +183,8 @@ mod tests { HalfEdge::new( valid.curve(), valid.boundary(), - valid.surface_vertices().map(Clone::clone), + valid.start_vertex().clone(), + valid.end_vertex().clone(), global_form, ) }; @@ -213,7 +214,8 @@ mod tests { HalfEdge::new( valid.curve(), boundary, - valid.surface_vertices().map(Clone::clone), + valid.start_vertex().clone(), + valid.end_vertex().clone(), valid.global_form().clone(), ) }; diff --git a/crates/fj-kernel/src/validate/face.rs b/crates/fj-kernel/src/validate/face.rs index 70bdd2c98..371fdf8d5 100644 --- a/crates/fj-kernel/src/validate/face.rs +++ b/crates/fj-kernel/src/validate/face.rs @@ -288,10 +288,13 @@ mod tests { *surface_vertex = invalid.clone(); } + let [start_vertex, end_vertex] = surface_vertices; + HalfEdge::new( half_edge.curve(), boundary, - surface_vertices, + start_vertex, + end_vertex, half_edge.global_form().clone(), ) .insert(&mut services.objects) From aea4d4f62fe2a32a5645b559c9299ec6f09e62d0 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 13:45:03 +0100 Subject: [PATCH 04/42] Refactor --- crates/fj-kernel/src/algorithms/reverse/cycle.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/reverse/cycle.rs b/crates/fj-kernel/src/algorithms/reverse/cycle.rs index 6af6e9a44..09178ff0e 100644 --- a/crates/fj-kernel/src/algorithms/reverse/cycle.rs +++ b/crates/fj-kernel/src/algorithms/reverse/cycle.rs @@ -20,15 +20,12 @@ impl Reverse for Handle { let [a, b] = current.boundary(); [b, a] }; - let [start_vertex, end_vertex] = - [next.start_vertex(), current.start_vertex()] - .map(Clone::clone); HalfEdge::new( current.curve(), boundary, - start_vertex, - end_vertex, + next.start_vertex().clone(), + current.start_vertex().clone(), current.global_form().clone(), ) .insert(objects) From 299c6a2823595c6b2f6ecad718a05b4a6db7a69e Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 13:46:11 +0100 Subject: [PATCH 05/42] Replace use of `HalfEdge::surface_vertices` --- crates/fj-kernel/src/algorithms/transform/edge.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/transform/edge.rs b/crates/fj-kernel/src/algorithms/transform/edge.rs index 618f107df..e57320baa 100644 --- a/crates/fj-kernel/src/algorithms/transform/edge.rs +++ b/crates/fj-kernel/src/algorithms/transform/edge.rs @@ -18,12 +18,14 @@ impl TransformObject for HalfEdge { // coordinates. let curve = self.curve(); let boundary = self.boundary(); - let [start_vertex, end_vertex] = - self.surface_vertices().map(|surface_vertex| { - surface_vertex - .clone() - .transform_with_cache(transform, objects, cache) - }); + let start_vertex = self + .start_vertex() + .clone() + .transform_with_cache(transform, objects, cache); + let end_vertex = self + .end_vertex() + .clone() + .transform_with_cache(transform, objects, cache); let global_form = self .global_form() .clone() From 8a6eb38d02aa4d76bac5adf700d76b6a3df99083 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 13:47:49 +0100 Subject: [PATCH 06/42] Replace use of `HalfEdge::surface_vertices` --- crates/fj-kernel/src/partial/objects/edge.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index 9a6f90904..f640542cd 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -35,11 +35,10 @@ impl PartialObject for PartialHalfEdge { Self { curve: Some(half_edge.curve().into()), boundary: half_edge.boundary().map(Some), - surface_vertices: half_edge.surface_vertices().map( - |surface_vertex| { - Partial::from_full(surface_vertex.clone(), cache) - }, - ), + surface_vertices: [ + Partial::from_full(half_edge.start_vertex().clone(), cache), + Partial::from_full(half_edge.end_vertex().clone(), cache), + ], global_form: Partial::from_full( half_edge.global_form().clone(), cache, From 8d27d27e92a61fa7e581ffd7fbc8572320ea9010 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 13:48:57 +0100 Subject: [PATCH 07/42] Replace uses of `HalfEdge::surface_vertices` --- crates/fj-kernel/src/validate/cycle.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/validate/cycle.rs b/crates/fj-kernel/src/validate/cycle.rs index 247c72d23..3093b21a2 100644 --- a/crates/fj-kernel/src/validate/cycle.rs +++ b/crates/fj-kernel/src/validate/cycle.rs @@ -74,8 +74,8 @@ impl CycleValidationError { errors: &mut Vec, ) { for (a, b) in cycle.half_edges().circular_tuple_windows() { - let [_, prev] = a.surface_vertices(); - let [next, _] = b.surface_vertices(); + let prev = a.end_vertex(); + let next = b.start_vertex(); if prev.id() != next.id() { errors.push( From dd9d40bececf60dd6055f1a8601005aa7de2b74d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 13:50:19 +0100 Subject: [PATCH 08/42] Replace use of `HalfEdge::surface_vertices` --- crates/fj-kernel/src/validate/face.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/validate/face.rs b/crates/fj-kernel/src/validate/face.rs index 371fdf8d5..b12fa63ac 100644 --- a/crates/fj-kernel/src/validate/face.rs +++ b/crates/fj-kernel/src/validate/face.rs @@ -112,7 +112,9 @@ impl FaceValidationError { ) { for cycle in face.all_cycles() { for half_edge in cycle.half_edges() { - for surface_vertex in half_edge.surface_vertices() { + for surface_vertex in + [half_edge.start_vertex(), half_edge.end_vertex()] + { let surface_position_as_global = face .surface() .geometry() From d2b34c759c56e8aa453389843e1c3d1479b8d00b Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 13:51:21 +0100 Subject: [PATCH 09/42] Replace use of `HalfEdge::surface_vertices` --- crates/fj-kernel/src/validate/face.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/validate/face.rs b/crates/fj-kernel/src/validate/face.rs index b12fa63ac..2a06ea8c8 100644 --- a/crates/fj-kernel/src/validate/face.rs +++ b/crates/fj-kernel/src/validate/face.rs @@ -276,7 +276,8 @@ mod tests { .map(|point| point + Vector::from([Scalar::PI / 2.])); let mut surface_vertices = - half_edge.surface_vertices().map(Clone::clone); + [half_edge.start_vertex(), half_edge.end_vertex()] + .map(Clone::clone); let mut invalid = None; for surface_vertex in surface_vertices.each_mut_ext() { From b5589f636ba28fd87ecfdad6165da042dbc839bd Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 13:52:01 +0100 Subject: [PATCH 10/42] Remove `HalfEdge::surface_vertices` --- crates/fj-kernel/src/objects/full/edge.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/fj-kernel/src/objects/full/edge.rs b/crates/fj-kernel/src/objects/full/edge.rs index fc38f6c60..d57fded0f 100644 --- a/crates/fj-kernel/src/objects/full/edge.rs +++ b/crates/fj-kernel/src/objects/full/edge.rs @@ -89,11 +89,6 @@ impl HalfEdge { &self.end_vertex } - /// Access the surface vertices that bound the half-edge - pub fn surface_vertices(&self) -> [&Handle; 2] { - [&self.start_vertex, &self.end_vertex] - } - /// Access the global form of the half-edge pub fn global_form(&self) -> &Handle { &self.global_form From 1cc4f5b46837c879dfe6b47d8e71c32dd9ef33f2 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 13:56:28 +0100 Subject: [PATCH 11/42] Prepare code for follow-on change --- crates/fj-kernel/src/algorithms/sweep/face.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 40b98a0df..78d61a52a 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -95,7 +95,9 @@ impl Sweep for Handle { .connect_to_closed_edges(top_edges, &top_surface.geometry()); for half_edge in &mut top_cycle.write().half_edges { - for surface_vertex in &mut half_edge.write().surface_vertices { + let mut half_edge = half_edge.write(); + + for surface_vertex in &mut half_edge.surface_vertices { let mut surface_vertex = surface_vertex.write(); let global_point = surface_vertex.global_form.read().position; From 628cb9f4ec03d51edb98b3313562c4d40ecfa5e4 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 14:27:23 +0100 Subject: [PATCH 12/42] Prepare code for follow-on change --- crates/fj-kernel/src/builder/edge.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index a8740be4f..a3d3c501e 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -335,10 +335,12 @@ impl HalfEdgeBuilder for PartialHalfEdge { } }); + let other = other.read(); + for (this, other) in self .surface_vertices .iter_mut() - .zip(other.read().surface_vertices.iter().rev()) + .zip(other.surface_vertices.iter().rev()) { this.write().global_form.write().position = other.read().global_form.read().position; From 62e2bfc9e6f18b203e1e96531b7c65c79e7b1433 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 14:35:00 +0100 Subject: [PATCH 13/42] Splify `PartialHalfEdge`'s `surface_vertices` This is preparation for removing `end_vertex`. --- crates/fj-kernel/src/algorithms/sweep/edge.rs | 2 +- crates/fj-kernel/src/algorithms/sweep/face.rs | 7 +++- crates/fj-kernel/src/builder/cycle.rs | 12 +++--- crates/fj-kernel/src/builder/edge.rs | 37 +++++++++---------- crates/fj-kernel/src/builder/face.rs | 13 +++---- crates/fj-kernel/src/partial/objects/edge.rs | 27 +++++++++----- crates/fj-kernel/src/validate/cycle.rs | 3 +- 7 files changed, 55 insertions(+), 46 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index d0f08d3f9..5b9b83e18 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -106,7 +106,7 @@ impl Sweep for (Handle, &Handle, &Surface, Color) { // Writing to the start vertices is enough. Neighboring half- // edges share surface vertices, so writing the start vertex of // each half-edge writes to all vertices. - let mut vertex = half_edge.surface_vertices[0].write(); + let mut vertex = half_edge.start_vertex.write(); vertex.position = Some(surface_point); vertex.global_form = Partial::from(global_vertex); }, diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 78d61a52a..840989429 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -95,9 +95,12 @@ impl Sweep for Handle { .connect_to_closed_edges(top_edges, &top_surface.geometry()); for half_edge in &mut top_cycle.write().half_edges { - let mut half_edge = half_edge.write(); + let half_edge = half_edge.write(); - for surface_vertex in &mut half_edge.surface_vertices { + let start_vertex = &mut half_edge.start_vertex.clone(); + let end_vertex = &mut half_edge.end_vertex.clone(); + + for surface_vertex in [start_vertex, end_vertex] { let mut surface_vertex = surface_vertex.write(); let global_point = surface_vertex.global_form.read().position; diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 50ea25b31..0ce954f71 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -103,26 +103,26 @@ impl CycleBuilder for PartialCycle { { let shared_surface_vertex = { - let [vertex, _] = &new_half_edge.read().surface_vertices; + let vertex = &new_half_edge.read().start_vertex; vertex.clone() }; let mut last_half_edge = last_half_edge.write(); - let [_, vertex] = &mut last_half_edge.surface_vertices; + let vertex = &mut last_half_edge.end_vertex; *vertex = shared_surface_vertex; last_half_edge.infer_global_form(); } { let shared_surface_vertex = { - let [vertex, _] = &first_half_edge.read().surface_vertices; + let vertex = &first_half_edge.read().start_vertex; vertex.clone() }; let mut new_half_edge = new_half_edge.write(); - let [_, vertex] = &mut new_half_edge.surface_vertices; + let vertex = &mut new_half_edge.end_vertex; *vertex = shared_surface_vertex; new_half_edge.infer_global_form(); } @@ -138,7 +138,7 @@ impl CycleBuilder for PartialCycle { let mut half_edge = self.add_half_edge(); { - let [vertex, _] = &mut half_edge.write().surface_vertices; + let vertex = &mut half_edge.write().start_vertex; vertex.write().position = Some(point.into()); } @@ -152,7 +152,7 @@ impl CycleBuilder for PartialCycle { let mut half_edge = self.add_half_edge(); { - let [vertex, _] = &mut half_edge.write().surface_vertices; + let vertex = &mut half_edge.write().start_vertex; vertex.write().global_form.write().position = Some(point.into()); } diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index a3d3c501e..2b55766ff 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -97,7 +97,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { [Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord])); let mut surface_vertex = { - let [vertex, _] = &mut self.surface_vertices; + let vertex = &mut self.start_vertex; vertex.clone() }; surface_vertex.write().position = @@ -106,7 +106,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { for (vertex, point_curve) in self .boundary .each_mut_ext() - .zip_ext(self.surface_vertices.each_mut_ext()) + .zip_ext([&mut self.start_vertex, &mut self.end_vertex]) .zip_ext([a_curve, b_curve]) { *vertex.0 = Some(point_curve); @@ -123,12 +123,13 @@ impl HalfEdgeBuilder for PartialHalfEdge { if angle_rad <= -Scalar::TAU || angle_rad >= Scalar::TAU { panic!("arc angle must be in the range (-2pi, 2pi) radians"); } - let [start, end] = self.surface_vertices.each_ref_ext().map(|vertex| { - vertex - .read() - .position - .expect("Can't infer arc without surface position") - }); + let [start, end] = + [&self.start_vertex, &self.end_vertex].map(|vertex| { + vertex + .read() + .position + .expect("Can't infer arc without surface position") + }); let arc = fj_math::Arc::from_endpoints_and_angle(start, end, angle_rad); @@ -141,7 +142,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { for (vertex, point_curve) in self .boundary .each_mut_ext() - .zip_ext(self.surface_vertices.each_mut_ext()) + .zip_ext([&mut self.start_vertex, &mut self.end_vertex]) .zip_ext([a_curve, b_curve]) { *vertex.0 = Some(point_curve); @@ -157,7 +158,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { points: [impl Into>; 2], ) -> Curve { for (vertex, point) in - self.surface_vertices.each_mut_ext().zip_ext(points) + [&mut self.start_vertex, &mut self.end_vertex].zip_ext(points) { let mut surface_form = vertex.write(); surface_form.position = Some(point.into()); @@ -169,7 +170,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { fn update_as_line_segment(&mut self) -> Curve { let boundary = self.boundary; let points_surface = - self.surface_vertices.each_ref_ext().map(|vertex| { + [&self.start_vertex, &self.end_vertex].map(|vertex| { vertex .read() .position @@ -202,10 +203,9 @@ impl HalfEdgeBuilder for PartialHalfEdge { } fn infer_global_form(&mut self) -> Partial { - self.global_form.write().vertices = self - .surface_vertices - .each_ref_ext() - .map(|vertex| vertex.read().global_form.clone()); + self.global_form.write().vertices = + [&self.start_vertex, &self.end_vertex] + .map(|vertex| vertex.read().global_form.clone()); self.global_form.clone() } @@ -224,7 +224,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { for vertex in self .boundary .each_mut_ext() - .zip_ext(self.surface_vertices.each_mut_ext()) + .zip_ext([&mut self.start_vertex, &mut self.end_vertex]) { let position_curve = vertex .0 @@ -337,10 +337,9 @@ impl HalfEdgeBuilder for PartialHalfEdge { let other = other.read(); - for (this, other) in self - .surface_vertices + for (this, other) in [&mut self.start_vertex, &mut self.end_vertex] .iter_mut() - .zip(other.surface_vertices.iter().rev()) + .zip([&other.end_vertex, &other.start_vertex]) { this.write().global_form.write().position = other.read().global_form.read().position; diff --git a/crates/fj-kernel/src/builder/face.rs b/crates/fj-kernel/src/builder/face.rs index 02f52a667..d6d061428 100644 --- a/crates/fj-kernel/src/builder/face.rs +++ b/crates/fj-kernel/src/builder/face.rs @@ -44,7 +44,7 @@ impl FaceBuilder for PartialFace { .half_edges .iter() .map(|half_edge| { - let [surface_vertex, _] = &half_edge.read().surface_vertices; + let surface_vertex = &half_edge.read().start_vertex; let global_position = surface_vertex .read() .global_form @@ -107,14 +107,13 @@ impl FaceBuilder for PartialFace { "Inferring undefined circles is not supported yet" ), MaybeCurve::UndefinedLine => { - let points_surface = half_edge - .surface_vertices - .each_ref_ext() - .map(|vertex| { - vertex.read().position.expect( + let points_surface = + [&half_edge.start_vertex, &half_edge.end_vertex] + .map(|vertex| { + vertex.read().position.expect( "Can't infer curve without surface points", ) - }); + }); let (line, points_curve) = Curve::line_from_points(points_surface); diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index f640542cd..8811c7496 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -18,8 +18,11 @@ pub struct PartialHalfEdge { /// The boundary of the half-edge on the curve pub boundary: [Option>; 2], - /// The surface vertices that bound the half-edge - pub surface_vertices: [Partial; 2], + /// The surface vertex where the half-edge starts + pub start_vertex: Partial, + + /// The surface vertex where the half-edge ends + pub end_vertex: Partial, /// The global form of the half-edge pub global_form: Partial, @@ -35,10 +38,14 @@ impl PartialObject for PartialHalfEdge { Self { curve: Some(half_edge.curve().into()), boundary: half_edge.boundary().map(Some), - surface_vertices: [ - Partial::from_full(half_edge.start_vertex().clone(), cache), - Partial::from_full(half_edge.end_vertex().clone(), cache), - ], + start_vertex: Partial::from_full( + half_edge.start_vertex().clone(), + cache, + ), + end_vertex: Partial::from_full( + half_edge.end_vertex().clone(), + cache, + ), global_form: Partial::from_full( half_edge.global_form().clone(), cache, @@ -58,8 +65,7 @@ impl PartialObject for PartialHalfEdge { let boundary = self.boundary.map(|point| { point.expect("Can't build `HalfEdge` without boundary positions") }); - let [start_vertex, end_vertex] = self - .surface_vertices + let [start_vertex, end_vertex] = [self.start_vertex, self.end_vertex] .map(|surface_vertex| surface_vertex.build(objects)); let global_form = self.global_form.build(objects); @@ -84,10 +90,13 @@ impl Default for PartialHalfEdge { vertices: global_vertices, }); + let [start_vertex, end_vertex] = surface_vertices; + Self { curve, boundary: [None; 2], - surface_vertices, + start_vertex, + end_vertex, global_form, } } diff --git a/crates/fj-kernel/src/validate/cycle.rs b/crates/fj-kernel/src/validate/cycle.rs index 3093b21a2..5996824fc 100644 --- a/crates/fj-kernel/src/validate/cycle.rs +++ b/crates/fj-kernel/src/validate/cycle.rs @@ -160,8 +160,7 @@ mod tests { // cycle. { let first_half_edge = half_edges.first_mut().unwrap(); - let [first_vertex, _] = - &mut first_half_edge.write().surface_vertices; + let first_vertex = &mut first_half_edge.write().start_vertex; let surface_vertex = Partial::from_partial(first_vertex.read().clone()); *first_vertex = surface_vertex; From 74d710ed7325f1d308a5269523d86d348b20c3db Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 14:36:50 +0100 Subject: [PATCH 14/42] Simplify assignments --- crates/fj-kernel/src/builder/cycle.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 0ce954f71..74fb8f0f8 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -102,10 +102,8 @@ impl CycleBuilder for PartialCycle { }; { - let shared_surface_vertex = { - let vertex = &new_half_edge.read().start_vertex; - vertex.clone() - }; + let shared_surface_vertex = + new_half_edge.read().start_vertex.clone(); let mut last_half_edge = last_half_edge.write(); @@ -115,10 +113,8 @@ impl CycleBuilder for PartialCycle { } { - let shared_surface_vertex = { - let vertex = &first_half_edge.read().start_vertex; - vertex.clone() - }; + let shared_surface_vertex = + first_half_edge.read().start_vertex.clone(); let mut new_half_edge = new_half_edge.write(); From c0371279f104247ff773ed2eac35914eb4b0f81e Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 14:38:40 +0100 Subject: [PATCH 15/42] Simplify assignments --- crates/fj-kernel/src/builder/cycle.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 74fb8f0f8..56ce47d52 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -107,8 +107,7 @@ impl CycleBuilder for PartialCycle { let mut last_half_edge = last_half_edge.write(); - let vertex = &mut last_half_edge.end_vertex; - *vertex = shared_surface_vertex; + last_half_edge.end_vertex = shared_surface_vertex; last_half_edge.infer_global_form(); } @@ -118,8 +117,7 @@ impl CycleBuilder for PartialCycle { let mut new_half_edge = new_half_edge.write(); - let vertex = &mut new_half_edge.end_vertex; - *vertex = shared_surface_vertex; + new_half_edge.end_vertex = shared_surface_vertex; new_half_edge.infer_global_form(); } From 9f29b88353f69a6021e019ae62d23b674e967664 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 14:47:39 +0100 Subject: [PATCH 16/42] Simplify builder methods --- crates/fj-kernel/src/builder/cycle.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 56ce47d52..3c10c6617 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -130,12 +130,7 @@ impl CycleBuilder for PartialCycle { point: impl Into>, ) -> Partial { let mut half_edge = self.add_half_edge(); - - { - let vertex = &mut half_edge.write().start_vertex; - vertex.write().position = Some(point.into()); - } - + half_edge.write().start_vertex.write().position = Some(point.into()); half_edge } @@ -144,12 +139,13 @@ impl CycleBuilder for PartialCycle { point: impl Into>, ) -> Partial { let mut half_edge = self.add_half_edge(); - - { - let vertex = &mut half_edge.write().start_vertex; - vertex.write().global_form.write().position = Some(point.into()); - } - + half_edge + .write() + .start_vertex + .write() + .global_form + .write() + .position = Some(point.into()); half_edge } From 896fe7be20d9bf545da42f8d00eb9985db05d9f8 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 14:49:55 +0100 Subject: [PATCH 17/42] Simplify assignment --- crates/fj-kernel/src/builder/edge.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 2b55766ff..7cfd68dbf 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -96,10 +96,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { let [a_curve, b_curve] = [Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord])); - let mut surface_vertex = { - let vertex = &mut self.start_vertex; - vertex.clone() - }; + let mut surface_vertex = self.start_vertex.clone(); surface_vertex.write().position = Some(path.point_from_path_coords(a_curve)); From 900af58cf26c25580e50cde3750972137dd74c8c Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 14:54:43 +0100 Subject: [PATCH 18/42] Remove redundant write to end vertex We're writing to the whole cycle, so writing to each start vertex covers them all. --- crates/fj-kernel/src/algorithms/sweep/face.rs | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 840989429..972775083 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -95,24 +95,18 @@ impl Sweep for Handle { .connect_to_closed_edges(top_edges, &top_surface.geometry()); for half_edge in &mut top_cycle.write().half_edges { - let half_edge = half_edge.write(); - - let start_vertex = &mut half_edge.start_vertex.clone(); - let end_vertex = &mut half_edge.end_vertex.clone(); - - for surface_vertex in [start_vertex, end_vertex] { - let mut surface_vertex = surface_vertex.write(); - let global_point = - surface_vertex.global_form.read().position; - - if surface_vertex.position.is_none() { - if let Some(global_point) = global_point { - surface_vertex.position = Some( - top_surface - .geometry() - .project_global_point(global_point), - ); - } + let mut half_edge = half_edge.write(); + + let mut start_vertex = half_edge.start_vertex.write(); + let global_point = start_vertex.global_form.read().position; + + if start_vertex.position.is_none() { + if let Some(global_point) = global_point { + start_vertex.position = Some( + top_surface + .geometry() + .project_global_point(global_point), + ); } } } From 510a6cef52b033b81e411de9eb5618367cb51f86 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 14:58:13 +0100 Subject: [PATCH 19/42] Simplify surface vertex setup for circle --- crates/fj-kernel/src/builder/edge.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 7cfd68dbf..49e06b37e 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -99,15 +99,12 @@ impl HalfEdgeBuilder for PartialHalfEdge { let mut surface_vertex = self.start_vertex.clone(); surface_vertex.write().position = Some(path.point_from_path_coords(a_curve)); + self.end_vertex = surface_vertex; - for (vertex, point_curve) in self - .boundary - .each_mut_ext() - .zip_ext([&mut self.start_vertex, &mut self.end_vertex]) - .zip_ext([a_curve, b_curve]) + for (vertex, point_curve) in + self.boundary.each_mut_ext().zip_ext([a_curve, b_curve]) { - *vertex.0 = Some(point_curve); - *vertex.1 = surface_vertex.clone(); + *vertex = Some(point_curve); } self.infer_global_form(); From d9a9031b5a7f9443f0f17c3caa23e2d1d97e6484 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 14:59:10 +0100 Subject: [PATCH 20/42] Inline redundant variable --- crates/fj-kernel/src/builder/edge.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 49e06b37e..3ec8a1de7 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -96,10 +96,9 @@ impl HalfEdgeBuilder for PartialHalfEdge { let [a_curve, b_curve] = [Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord])); - let mut surface_vertex = self.start_vertex.clone(); - surface_vertex.write().position = + self.start_vertex.write().position = Some(path.point_from_path_coords(a_curve)); - self.end_vertex = surface_vertex; + self.end_vertex = self.start_vertex.clone(); for (vertex, point_curve) in self.boundary.each_mut_ext().zip_ext([a_curve, b_curve]) From c51103474c5024f2ff5739d50094004ed7f5c43d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 14:59:55 +0100 Subject: [PATCH 21/42] Make variable name more explicit --- crates/fj-kernel/src/builder/edge.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 3ec8a1de7..e2edcdff5 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -100,10 +100,10 @@ impl HalfEdgeBuilder for PartialHalfEdge { Some(path.point_from_path_coords(a_curve)); self.end_vertex = self.start_vertex.clone(); - for (vertex, point_curve) in + for (point_boundary, point_curve) in self.boundary.each_mut_ext().zip_ext([a_curve, b_curve]) { - *vertex = Some(point_curve); + *point_boundary = Some(point_curve); } self.infer_global_form(); From f73f9fe2dc0ba105160e402522297777f022df8d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:02:35 +0100 Subject: [PATCH 22/42] Split tuple --- crates/fj-kernel/src/builder/edge.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index e2edcdff5..94d52d6aa 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -132,14 +132,14 @@ impl HalfEdgeBuilder for PartialHalfEdge { let [a_curve, b_curve] = [arc.start_angle, arc.end_angle].map(|coord| Point::from([coord])); - for (vertex, point_curve) in self + for ((point_boundary, surface_vertex), point_curve) in self .boundary .each_mut_ext() .zip_ext([&mut self.start_vertex, &mut self.end_vertex]) .zip_ext([a_curve, b_curve]) { - *vertex.0 = Some(point_curve); - vertex.1.write().position = + *point_boundary = Some(point_curve); + surface_vertex.write().position = Some(path.point_from_path_coords(point_curve)); } From 1f72b5667e387708485ae3576067a32f9dd4e391 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:04:07 +0100 Subject: [PATCH 23/42] Improve formatting --- crates/fj-operations/src/sketch.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 6754fb6ec..71a7037bb 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -57,8 +57,10 @@ impl Shape for fj::Sketch { let exterior = { let mut cycle = PartialCycle::default(); + let mut line_segments = vec![]; let mut arcs = vec![]; + poly_chain.to_segments().into_iter().for_each( |fj::SketchSegment { endpoint, route }| { let endpoint = Point::from(endpoint); @@ -83,12 +85,14 @@ impl Shape for fj::Sketch { } }, ); + line_segments.into_iter().for_each(|mut half_edge| { half_edge.write().update_as_line_segment(); }); arcs.into_iter().for_each(|(mut half_edge, angle)| { half_edge.write().update_as_arc(angle.rad()) }); + Partial::from_partial(cycle) }; From 03984c70e23b2ffdde996c6865b8ab734834db49 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:11:11 +0100 Subject: [PATCH 24/42] Prepare code for follow-on change --- crates/fj-operations/src/sketch.rs | 41 ++++++++++-------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 71a7037bb..49b757754 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -58,40 +58,27 @@ impl Shape for fj::Sketch { let exterior = { let mut cycle = PartialCycle::default(); - let mut line_segments = vec![]; - let mut arcs = vec![]; + let mut half_edges = Vec::new(); poly_chain.to_segments().into_iter().for_each( |fj::SketchSegment { endpoint, route }| { let endpoint = Point::from(endpoint); - match route { - fj::SketchSegmentRoute::Direct => { - line_segments.push( - cycle - .add_half_edge_from_point_to_start( - endpoint, - ), - ); - } - fj::SketchSegmentRoute::Arc { angle } => { - arcs.push(( - cycle - .add_half_edge_from_point_to_start( - endpoint, - ), - angle, - )); - } - } + let half_edge = cycle + .add_half_edge_from_point_to_start(endpoint); + half_edges.push((half_edge, route)); }, ); - line_segments.into_iter().for_each(|mut half_edge| { - half_edge.write().update_as_line_segment(); - }); - arcs.into_iter().for_each(|(mut half_edge, angle)| { - half_edge.write().update_as_arc(angle.rad()) - }); + for (mut half_edge, route) in half_edges { + match route { + fj::SketchSegmentRoute::Direct => { + half_edge.write().update_as_line_segment(); + } + fj::SketchSegmentRoute::Arc { angle } => { + half_edge.write().update_as_arc(angle.rad()); + } + } + } Partial::from_partial(cycle) }; From 6a3e546ad1c7cc2fa3fdd7dbb1088400ce073b44 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:19:00 +0100 Subject: [PATCH 25/42] Refactor --- crates/fj-operations/src/sketch.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 49b757754..3dce85437 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -58,16 +58,16 @@ impl Shape for fj::Sketch { let exterior = { let mut cycle = PartialCycle::default(); - let mut half_edges = Vec::new(); - - poly_chain.to_segments().into_iter().for_each( - |fj::SketchSegment { endpoint, route }| { + let half_edges = poly_chain + .to_segments() + .into_iter() + .map(|fj::SketchSegment { endpoint, route }| { let endpoint = Point::from(endpoint); let half_edge = cycle .add_half_edge_from_point_to_start(endpoint); - half_edges.push((half_edge, route)); - }, - ); + (half_edge, route) + }) + .collect::>(); for (mut half_edge, route) in half_edges { match route { From 9c6613f8c17ea83d0f5083cf6692f64e3d970173 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:22:19 +0100 Subject: [PATCH 26/42] Add dependency on `itertools` to `fj-operations` --- Cargo.lock | 1 + crates/fj-operations/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index df3b4511e..81a5f43a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1137,6 +1137,7 @@ dependencies = [ "fj-interop", "fj-kernel", "fj-math", + "itertools", "thiserror", ] diff --git a/crates/fj-operations/Cargo.toml b/crates/fj-operations/Cargo.toml index 7cc1a9cb4..cdefd2e5f 100644 --- a/crates/fj-operations/Cargo.toml +++ b/crates/fj-operations/Cargo.toml @@ -15,4 +15,5 @@ fj.workspace = true fj-interop.workspace = true fj-kernel.workspace = true fj-math.workspace = true +itertools = "0.10.5" thiserror = "1.0.35" From b2d3cb6ca3f88b8a1ddd945cc3c32748358ec069 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:23:52 +0100 Subject: [PATCH 27/42] Replace use of `PartialHalfEdge`'s `end_vertex` --- crates/fj-kernel/src/builder/edge.rs | 29 +++++++++++++++++----------- crates/fj-operations/src/sketch.rs | 10 ++++++++-- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 94d52d6aa..dd492cf55 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -6,7 +6,7 @@ use crate::{ curve::{Curve, GlobalPath}, surface::SurfaceGeometry, }, - objects::{GlobalEdge, HalfEdge}, + objects::{GlobalEdge, HalfEdge, SurfaceVertex}, partial::{MaybeCurve, Partial, PartialGlobalEdge, PartialHalfEdge}, }; @@ -34,7 +34,11 @@ pub trait HalfEdgeBuilder { /// # Panics /// /// Panics if the given angle is not within the range (-2pi, 2pi) radians. - fn update_as_arc(&mut self, angle_rad: impl Into); + fn update_as_arc( + &mut self, + angle_rad: impl Into, + next_vertex: Partial, + ); /// Update partial half-edge to be a line segment, from the given points fn update_as_line_segment_from_points( @@ -111,18 +115,21 @@ impl HalfEdgeBuilder for PartialHalfEdge { path } - fn update_as_arc(&mut self, angle_rad: impl Into) { + fn update_as_arc( + &mut self, + angle_rad: impl Into, + mut next_vertex: Partial, + ) { let angle_rad = angle_rad.into(); if angle_rad <= -Scalar::TAU || angle_rad >= Scalar::TAU { panic!("arc angle must be in the range (-2pi, 2pi) radians"); } - let [start, end] = - [&self.start_vertex, &self.end_vertex].map(|vertex| { - vertex - .read() - .position - .expect("Can't infer arc without surface position") - }); + let [start, end] = [&self.start_vertex, &next_vertex].map(|vertex| { + vertex + .read() + .position + .expect("Can't infer arc without surface position") + }); let arc = fj_math::Arc::from_endpoints_and_angle(start, end, angle_rad); @@ -135,7 +142,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { for ((point_boundary, surface_vertex), point_curve) in self .boundary .each_mut_ext() - .zip_ext([&mut self.start_vertex, &mut self.end_vertex]) + .zip_ext([&mut self.start_vertex, &mut next_vertex]) .zip_ext([a_curve, b_curve]) { *point_boundary = Some(point_curve); diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 3dce85437..d8cf88ba5 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -12,6 +12,7 @@ use fj_kernel::{ services::Service, }; use fj_math::{Aabb, Point}; +use itertools::Itertools; use super::Shape; @@ -69,13 +70,18 @@ impl Shape for fj::Sketch { }) .collect::>(); - for (mut half_edge, route) in half_edges { + for ((mut half_edge, route), (next_half_edge, _)) in + half_edges.into_iter().circular_tuple_windows() + { match route { fj::SketchSegmentRoute::Direct => { half_edge.write().update_as_line_segment(); } fj::SketchSegmentRoute::Arc { angle } => { - half_edge.write().update_as_arc(angle.rad()); + half_edge.write().update_as_arc( + angle.rad(), + next_half_edge.read().start_vertex.clone(), + ); } } } From 8c839beb207a4d402c098d36ef29d521777f61a7 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:23:52 +0100 Subject: [PATCH 28/42] Replace use of `PartialHalfEdge`'s `end_vertex` --- .../fj-kernel/src/algorithms/approx/edge.rs | 15 ++++++++++--- .../src/algorithms/intersect/curve_edge.rs | 22 ++++++++++++++----- crates/fj-kernel/src/builder/edge.rs | 4 +++- crates/fj-kernel/src/objects/full/edge.rs | 10 +++++++-- crates/fj-kernel/src/validate/edge.rs | 10 +++++++-- 5 files changed, 47 insertions(+), 14 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/edge.rs b/crates/fj-kernel/src/algorithms/approx/edge.rs index 3258b35f6..86d123c1b 100644 --- a/crates/fj-kernel/src/algorithms/approx/edge.rs +++ b/crates/fj-kernel/src/algorithms/approx/edge.rs @@ -246,7 +246,10 @@ mod tests { let half_edge = { let mut half_edge = PartialHalfEdge::default(); - half_edge.update_as_line_segment_from_points([[1., 1.], [2., 1.]]); + half_edge.update_as_line_segment_from_points( + [[1., 1.], [2., 1.]], + half_edge.end_vertex.clone(), + ); half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); half_edge @@ -273,7 +276,10 @@ mod tests { let half_edge = { let mut half_edge = PartialHalfEdge::default(); - half_edge.update_as_line_segment_from_points([[1., 1.], [2., 1.]]); + half_edge.update_as_line_segment_from_points( + [[1., 1.], [2., 1.]], + half_edge.end_vertex.clone(), + ); half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); half_edge @@ -300,7 +306,10 @@ mod tests { let half_edge = { let mut half_edge = PartialHalfEdge::default(); - half_edge.update_as_line_segment_from_points([[0., 1.], [1., 1.]]); + half_edge.update_as_line_segment_from_points( + [[0., 1.], [1., 1.]], + half_edge.end_vertex.clone(), + ); half_edge.boundary[0] = Some(range.boundary[0]); half_edge.boundary[1] = Some(range.boundary[1]); diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs index 8fea643fa..81601c778 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs @@ -88,7 +88,10 @@ mod tests { let curve = Curve::u_axis(); let half_edge = { let mut half_edge = PartialHalfEdge::default(); - half_edge.update_as_line_segment_from_points([[1., -1.], [1., 1.]]); + half_edge.update_as_line_segment_from_points( + [[1., -1.], [1., 1.]], + half_edge.end_vertex.clone(), + ); half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); half_edge.build(&mut services.objects) @@ -112,8 +115,10 @@ mod tests { let curve = Curve::u_axis(); let half_edge = { let mut half_edge = PartialHalfEdge::default(); - half_edge - .update_as_line_segment_from_points([[-1., -1.], [-1., 1.]]); + half_edge.update_as_line_segment_from_points( + [[-1., -1.], [-1., 1.]], + half_edge.end_vertex.clone(), + ); half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); half_edge.build(&mut services.objects) @@ -137,8 +142,10 @@ mod tests { let curve = Curve::u_axis(); let half_edge = { let mut half_edge = PartialHalfEdge::default(); - half_edge - .update_as_line_segment_from_points([[-1., -1.], [1., -1.]]); + half_edge.update_as_line_segment_from_points( + [[-1., -1.], [1., -1.]], + half_edge.end_vertex.clone(), + ); half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); half_edge.build(&mut services.objects) @@ -157,7 +164,10 @@ mod tests { let curve = Curve::u_axis(); let half_edge = { let mut half_edge = PartialHalfEdge::default(); - half_edge.update_as_line_segment_from_points([[-1., 0.], [1., 0.]]); + half_edge.update_as_line_segment_from_points( + [[-1., 0.], [1., 0.]], + half_edge.end_vertex.clone(), + ); half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); half_edge.build(&mut services.objects) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index dd492cf55..67f1aa559 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -44,6 +44,7 @@ pub trait HalfEdgeBuilder { fn update_as_line_segment_from_points( &mut self, points: [impl Into>; 2], + next_vertex: Partial, ) -> Curve; /// Update partial half-edge to be a line segment @@ -156,9 +157,10 @@ impl HalfEdgeBuilder for PartialHalfEdge { fn update_as_line_segment_from_points( &mut self, points: [impl Into>; 2], + mut next_vertex: Partial, ) -> Curve { for (vertex, point) in - [&mut self.start_vertex, &mut self.end_vertex].zip_ext(points) + [&mut self.start_vertex, &mut next_vertex].zip_ext(points) { let mut surface_form = vertex.write(); surface_form.position = Some(point.into()); diff --git a/crates/fj-kernel/src/objects/full/edge.rs b/crates/fj-kernel/src/objects/full/edge.rs index d57fded0f..b3d1cf005 100644 --- a/crates/fj-kernel/src/objects/full/edge.rs +++ b/crates/fj-kernel/src/objects/full/edge.rs @@ -183,14 +183,20 @@ mod tests { let a_to_b = { let mut half_edge = PartialHalfEdge::default(); - half_edge.update_as_line_segment_from_points([a, b]); + half_edge.update_as_line_segment_from_points( + [a, b], + half_edge.end_vertex.clone(), + ); half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); half_edge.build(&mut services.objects) }; let b_to_a = { let mut half_edge = PartialHalfEdge::default(); - half_edge.update_as_line_segment_from_points([b, a]); + half_edge.update_as_line_segment_from_points( + [b, a], + half_edge.end_vertex.clone(), + ); half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); half_edge.build(&mut services.objects) diff --git a/crates/fj-kernel/src/validate/edge.rs b/crates/fj-kernel/src/validate/edge.rs index f3fe68a33..645c5f7fe 100644 --- a/crates/fj-kernel/src/validate/edge.rs +++ b/crates/fj-kernel/src/validate/edge.rs @@ -158,7 +158,10 @@ mod tests { let surface = services.objects.surfaces.xy_plane(); let mut half_edge = PartialHalfEdge::default(); - half_edge.update_as_line_segment_from_points([[0., 0.], [1., 0.]]); + half_edge.update_as_line_segment_from_points( + [[0., 0.], [1., 0.]], + half_edge.end_vertex.clone(), + ); half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); half_edge.build(&mut services.objects) @@ -203,7 +206,10 @@ mod tests { let surface = services.objects.surfaces.xy_plane(); let mut half_edge = PartialHalfEdge::default(); - half_edge.update_as_line_segment_from_points([[0., 0.], [1., 0.]]); + half_edge.update_as_line_segment_from_points( + [[0., 0.], [1., 0.]], + half_edge.end_vertex.clone(), + ); half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); half_edge.build(&mut services.objects) From 53104aa5f800b96596a148e8eae66792b2a1e6a4 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:34:09 +0100 Subject: [PATCH 29/42] Prepare code for follow-on change --- crates/fj-kernel/src/algorithms/sweep/edge.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index 5b9b83e18..44b81bfad 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -119,12 +119,12 @@ impl Sweep for (Handle, &Handle, &Surface, Color) { // when projected into the new surface. For the side edges, because // we're sweeping along a straight path. for mut edge in [ - edge_bottom.write(), - edge_up.write(), - edge_top.write(), - edge_down.write(), + edge_bottom.clone(), + edge_up.clone(), + edge_top.clone(), + edge_down.clone(), ] { - edge.update_as_line_segment(); + edge.write().update_as_line_segment(); } // Finally, we can make sure that all edges refer to the correct global From 0276b5b5908d2c6af07e4853f5b610e78ebb3337 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:35:42 +0100 Subject: [PATCH 30/42] Prepare code for follow-on change --- crates/fj-kernel/src/builder/cycle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 3c10c6617..cd4ab2929 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -164,7 +164,7 @@ impl CycleBuilder for PartialCycle { } fn update_as_polygon(&mut self) { - for half_edge in &mut self.half_edges { + for mut half_edge in self.half_edges.iter().cloned() { half_edge.write().update_as_line_segment(); } } From 74188f973f47cd81155540402c951492e8766c76 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:37:02 +0100 Subject: [PATCH 31/42] Prepare code for follow-on change --- crates/fj-operations/src/sketch.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index d8cf88ba5..9dbc6b86a 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -73,15 +73,17 @@ impl Shape for fj::Sketch { for ((mut half_edge, route), (next_half_edge, _)) in half_edges.into_iter().circular_tuple_windows() { + let next_vertex = + next_half_edge.read().start_vertex.clone(); + match route { fj::SketchSegmentRoute::Direct => { half_edge.write().update_as_line_segment(); } fj::SketchSegmentRoute::Arc { angle } => { - half_edge.write().update_as_arc( - angle.rad(), - next_half_edge.read().start_vertex.clone(), - ); + half_edge + .write() + .update_as_arc(angle.rad(), next_vertex); } } } From 3ea6ce0567988e3c70928db2dd8d64ae61ce8ca8 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:23:52 +0100 Subject: [PATCH 32/42] Replace use of `PartialHalfEdge`'s `end_vertex` --- crates/fj-kernel/src/algorithms/sweep/edge.rs | 11 +++++--- crates/fj-kernel/src/builder/cycle.rs | 9 +++++-- crates/fj-kernel/src/builder/edge.rs | 25 +++++++++++-------- crates/fj-operations/src/sketch.rs | 4 ++- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index 44b81bfad..d3de6176a 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -1,5 +1,6 @@ use fj_interop::{ext::ArrayExt, mesh::Color}; use fj_math::{Point, Scalar, Vector}; +use itertools::Itertools; use crate::{ builder::{CycleBuilder, HalfEdgeBuilder}, @@ -118,13 +119,17 @@ impl Sweep for (Handle, &Handle, &Surface, Color) { // even if the original edge was a circle, it's still going to be a line // when projected into the new surface. For the side edges, because // we're sweeping along a straight path. - for mut edge in [ + for (mut edge, next) in [ edge_bottom.clone(), edge_up.clone(), edge_top.clone(), edge_down.clone(), - ] { - edge.write().update_as_line_segment(); + ] + .into_iter() + .circular_tuple_windows() + { + edge.write() + .update_as_line_segment(next.read().start_vertex.clone()); } // Finally, we can make sure that all edges refer to the correct global diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index cd4ab2929..73de83259 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -1,4 +1,5 @@ use fj_math::Point; +use itertools::Itertools; use crate::{ geometry::surface::SurfaceGeometry, @@ -164,8 +165,12 @@ impl CycleBuilder for PartialCycle { } fn update_as_polygon(&mut self) { - for mut half_edge in self.half_edges.iter().cloned() { - half_edge.write().update_as_line_segment(); + for (mut half_edge, next) in + self.half_edges.iter().cloned().circular_tuple_windows() + { + half_edge + .write() + .update_as_line_segment(next.read().start_vertex.clone()); } } diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 67f1aa559..ddc673767 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -48,7 +48,10 @@ pub trait HalfEdgeBuilder { ) -> Curve; /// Update partial half-edge to be a line segment - fn update_as_line_segment(&mut self) -> Curve; + fn update_as_line_segment( + &mut self, + next_vertex: Partial, + ) -> Curve; /// Infer the global form of the half-edge /// @@ -166,18 +169,20 @@ impl HalfEdgeBuilder for PartialHalfEdge { surface_form.position = Some(point.into()); } - self.update_as_line_segment() + self.update_as_line_segment(next_vertex) } - fn update_as_line_segment(&mut self) -> Curve { + fn update_as_line_segment( + &mut self, + next_vertex: Partial, + ) -> Curve { let boundary = self.boundary; - let points_surface = - [&self.start_vertex, &self.end_vertex].map(|vertex| { - vertex - .read() - .position - .expect("Can't infer line segment without surface position") - }); + let points_surface = [&self.start_vertex, &next_vertex].map(|vertex| { + vertex + .read() + .position + .expect("Can't infer line segment without surface position") + }); let path = if let [Some(start), Some(end)] = boundary { let points = [start, end].zip_ext(points_surface); diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 9dbc6b86a..6a1acbec2 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -78,7 +78,9 @@ impl Shape for fj::Sketch { match route { fj::SketchSegmentRoute::Direct => { - half_edge.write().update_as_line_segment(); + half_edge + .write() + .update_as_line_segment(next_vertex); } fj::SketchSegmentRoute::Arc { angle } => { half_edge From 0d5e713022a7cddc86290b2b3ace945acffe0cc7 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:23:52 +0100 Subject: [PATCH 33/42] Replace use of `PartialHalfEdge`'s `end_vertex` --- crates/fj-kernel/src/builder/cycle.rs | 8 ++++---- crates/fj-kernel/src/builder/edge.rs | 21 +++++++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 73de83259..9d00466bf 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -108,8 +108,8 @@ impl CycleBuilder for PartialCycle { let mut last_half_edge = last_half_edge.write(); - last_half_edge.end_vertex = shared_surface_vertex; - last_half_edge.infer_global_form(); + last_half_edge.end_vertex = shared_surface_vertex.clone(); + last_half_edge.infer_global_form(shared_surface_vertex); } { @@ -118,8 +118,8 @@ impl CycleBuilder for PartialCycle { let mut new_half_edge = new_half_edge.write(); - new_half_edge.end_vertex = shared_surface_vertex; - new_half_edge.infer_global_form(); + new_half_edge.end_vertex = shared_surface_vertex.clone(); + new_half_edge.infer_global_form(shared_surface_vertex); } self.half_edges.push(new_half_edge.clone()); diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index ddc673767..b6839b498 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -57,7 +57,10 @@ pub trait HalfEdgeBuilder { /// /// Updates the global form referenced by this half-edge, and also returns /// it. - fn infer_global_form(&mut self) -> Partial; + fn infer_global_form( + &mut self, + next_vertex: Partial, + ) -> Partial; /// Infer the vertex positions (surface and global), if not already set fn infer_vertex_positions_if_necessary( @@ -114,7 +117,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { *point_boundary = Some(point_curve); } - self.infer_global_form(); + self.infer_global_form(self.start_vertex.clone()); path } @@ -154,7 +157,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { Some(path.point_from_path_coords(point_curve)); } - self.infer_global_form(); + self.infer_global_form(next_vertex); } fn update_as_line_segment_from_points( @@ -204,15 +207,17 @@ impl HalfEdgeBuilder for PartialHalfEdge { path }; - self.infer_global_form(); + self.infer_global_form(next_vertex); path } - fn infer_global_form(&mut self) -> Partial { - self.global_form.write().vertices = - [&self.start_vertex, &self.end_vertex] - .map(|vertex| vertex.read().global_form.clone()); + fn infer_global_form( + &mut self, + next_vertex: Partial, + ) -> Partial { + self.global_form.write().vertices = [&self.start_vertex, &next_vertex] + .map(|vertex| vertex.read().global_form.clone()); self.global_form.clone() } From 5c3bc7459eaf76b017d5a36c8cbe38e6a290c15c Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:46:16 +0100 Subject: [PATCH 34/42] Split tuple --- crates/fj-kernel/src/builder/edge.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index b6839b498..52e218e28 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -233,16 +233,15 @@ impl HalfEdgeBuilder for PartialHalfEdge { panic!("Can't infer vertex positions with undefined path"); }; - for vertex in self + for (boundary_point, surface_vertex) in self .boundary .each_mut_ext() .zip_ext([&mut self.start_vertex, &mut self.end_vertex]) { - let position_curve = vertex - .0 + let position_curve = boundary_point .expect("Can't infer surface position without curve position"); - let position_surface = vertex.1.read().position; + let position_surface = surface_vertex.read().position; // Infer surface position, if not available. let position_surface = match position_surface { @@ -251,18 +250,19 @@ impl HalfEdgeBuilder for PartialHalfEdge { let position_surface = path.point_from_path_coords(position_curve); - vertex.1.write().position = Some(position_surface); + surface_vertex.write().position = Some(position_surface); position_surface } }; // Infer global position, if not available. - let position_global = vertex.1.read().global_form.read().position; + let position_global = + surface_vertex.read().global_form.read().position; if position_global.is_none() { let position_global = surface.point_from_surface_coords(position_surface); - vertex.1.write().global_form.write().position = + surface_vertex.write().global_form.write().position = Some(position_global); } } From 375e271818d7e921215bbc07c3cb0007195de647 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:47:12 +0100 Subject: [PATCH 35/42] Remove redundant line --- crates/fj-kernel/src/builder/edge.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 52e218e28..3cb29f308 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -235,7 +235,6 @@ impl HalfEdgeBuilder for PartialHalfEdge { for (boundary_point, surface_vertex) in self .boundary - .each_mut_ext() .zip_ext([&mut self.start_vertex, &mut self.end_vertex]) { let position_curve = boundary_point From 3b354c16fceaf0c2791ca4f8f5212334232c162e Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:23:52 +0100 Subject: [PATCH 36/42] Replace use of `PartialHalfEdge`'s `end_vertex` --- .../fj-kernel/src/algorithms/approx/edge.rs | 20 +++++++++++++++---- .../src/algorithms/intersect/curve_edge.rs | 20 +++++++++++++++---- crates/fj-kernel/src/builder/cycle.rs | 3 ++- crates/fj-kernel/src/builder/edge.rs | 4 +++- crates/fj-kernel/src/objects/full/edge.rs | 10 ++++++++-- crates/fj-kernel/src/validate/edge.rs | 10 ++++++++-- crates/fj-kernel/src/validate/face.rs | 8 +++++--- 7 files changed, 58 insertions(+), 17 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/approx/edge.rs b/crates/fj-kernel/src/algorithms/approx/edge.rs index 86d123c1b..a3542dbb4 100644 --- a/crates/fj-kernel/src/algorithms/approx/edge.rs +++ b/crates/fj-kernel/src/algorithms/approx/edge.rs @@ -250,7 +250,10 @@ mod tests { [[1., 1.], [2., 1.]], half_edge.end_vertex.clone(), ); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge .build(&mut services.objects) @@ -280,7 +283,10 @@ mod tests { [[1., 1.], [2., 1.]], half_edge.end_vertex.clone(), ); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge .build(&mut services.objects) @@ -314,7 +320,10 @@ mod tests { half_edge.boundary[0] = Some(range.boundary[0]); half_edge.boundary[1] = Some(range.boundary[1]); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge .build(&mut services.objects) @@ -347,7 +356,10 @@ mod tests { let mut half_edge = PartialHalfEdge::default(); half_edge.update_as_circle_from_radius(1.); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge .build(&mut services.objects) diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs index 81601c778..05f5f363c 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs @@ -92,7 +92,10 @@ mod tests { [[1., -1.], [1., 1.]], half_edge.end_vertex.clone(), ); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge.build(&mut services.objects) }; @@ -119,7 +122,10 @@ mod tests { [[-1., -1.], [-1., 1.]], half_edge.end_vertex.clone(), ); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge.build(&mut services.objects) }; @@ -146,7 +152,10 @@ mod tests { [[-1., -1.], [1., -1.]], half_edge.end_vertex.clone(), ); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge.build(&mut services.objects) }; @@ -168,7 +177,10 @@ mod tests { [[-1., 0.], [1., 0.]], half_edge.end_vertex.clone(), ); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge.build(&mut services.objects) }; diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 9d00466bf..fc405ff6f 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -194,9 +194,10 @@ impl CycleBuilder for PartialCycle { surface: &SurfaceGeometry, ) { for half_edge in &mut self.half_edges { + let next_vertex = half_edge.read().end_vertex.clone(); half_edge .write() - .infer_vertex_positions_if_necessary(surface); + .infer_vertex_positions_if_necessary(surface, next_vertex); } } } diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 3cb29f308..499ef479a 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -66,6 +66,7 @@ pub trait HalfEdgeBuilder { fn infer_vertex_positions_if_necessary( &mut self, surface: &SurfaceGeometry, + next_vertex: Partial, ); /// Update this edge from another @@ -225,6 +226,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { fn infer_vertex_positions_if_necessary( &mut self, surface: &SurfaceGeometry, + mut next_vertex: Partial, ) { let path = self .curve @@ -235,7 +237,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { for (boundary_point, surface_vertex) in self .boundary - .zip_ext([&mut self.start_vertex, &mut self.end_vertex]) + .zip_ext([&mut self.start_vertex, &mut next_vertex]) { let position_curve = boundary_point .expect("Can't infer surface position without curve position"); diff --git a/crates/fj-kernel/src/objects/full/edge.rs b/crates/fj-kernel/src/objects/full/edge.rs index b3d1cf005..f0a0a4915 100644 --- a/crates/fj-kernel/src/objects/full/edge.rs +++ b/crates/fj-kernel/src/objects/full/edge.rs @@ -187,7 +187,10 @@ mod tests { [a, b], half_edge.end_vertex.clone(), ); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge.build(&mut services.objects) }; @@ -197,7 +200,10 @@ mod tests { [b, a], half_edge.end_vertex.clone(), ); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge.build(&mut services.objects) }; diff --git a/crates/fj-kernel/src/validate/edge.rs b/crates/fj-kernel/src/validate/edge.rs index 645c5f7fe..cd8709ad1 100644 --- a/crates/fj-kernel/src/validate/edge.rs +++ b/crates/fj-kernel/src/validate/edge.rs @@ -162,7 +162,10 @@ mod tests { [[0., 0.], [1., 0.]], half_edge.end_vertex.clone(), ); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge.build(&mut services.objects) }; @@ -210,7 +213,10 @@ mod tests { [[0., 0.], [1., 0.]], half_edge.end_vertex.clone(), ); - half_edge.infer_vertex_positions_if_necessary(&surface.geometry()); + half_edge.infer_vertex_positions_if_necessary( + &surface.geometry(), + half_edge.end_vertex.clone(), + ); half_edge.build(&mut services.objects) }; diff --git a/crates/fj-kernel/src/validate/face.rs b/crates/fj-kernel/src/validate/face.rs index 2a06ea8c8..b8b38002f 100644 --- a/crates/fj-kernel/src/validate/face.rs +++ b/crates/fj-kernel/src/validate/face.rs @@ -261,9 +261,11 @@ mod tests { let mut half_edge = face.exterior.write().add_half_edge(); half_edge.write().update_as_circle_from_radius(1.); - half_edge - .write() - .infer_vertex_positions_if_necessary(&surface.geometry()); + let next_vertex = half_edge.read().end_vertex.clone(); + half_edge.write().infer_vertex_positions_if_necessary( + &surface.geometry(), + next_vertex, + ); face.build(&mut services.objects) }; From 2eb6ea8546fb811dbc65d0e441b9820b02c7c2d7 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:54:32 +0100 Subject: [PATCH 37/42] Prepare code for follow-on change --- crates/fj-kernel/src/builder/cycle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index fc405ff6f..43ac06a0a 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -193,7 +193,7 @@ impl CycleBuilder for PartialCycle { &mut self, surface: &SurfaceGeometry, ) { - for half_edge in &mut self.half_edges { + for mut half_edge in self.half_edges.iter().cloned() { let next_vertex = half_edge.read().end_vertex.clone(); half_edge .write() From ed6e008a5c66000d10b473af93bfb6b2099f71e8 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:23:52 +0100 Subject: [PATCH 38/42] Replace use of `PartialHalfEdge`'s `end_vertex` --- crates/fj-kernel/src/builder/cycle.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 43ac06a0a..2247f9c1e 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -193,8 +193,10 @@ impl CycleBuilder for PartialCycle { &mut self, surface: &SurfaceGeometry, ) { - for mut half_edge in self.half_edges.iter().cloned() { - let next_vertex = half_edge.read().end_vertex.clone(); + for (mut half_edge, next_half_edge) in + self.half_edges.iter().cloned().circular_tuple_windows() + { + let next_vertex = next_half_edge.read().start_vertex.clone(); half_edge .write() .infer_vertex_positions_if_necessary(surface, next_vertex); From 910bdf1297f81eadef89e6eb5ef59033f51598d1 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 16:02:33 +0100 Subject: [PATCH 39/42] Prepare code for follow-on change --- crates/fj-kernel/src/builder/face.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/builder/face.rs b/crates/fj-kernel/src/builder/face.rs index d6d061428..5e9e5c452 100644 --- a/crates/fj-kernel/src/builder/face.rs +++ b/crates/fj-kernel/src/builder/face.rs @@ -93,7 +93,7 @@ impl FaceBuilder for PartialFace { } fn infer_curves(&mut self) { - for half_edge in &mut self.exterior.write().half_edges { + for mut half_edge in self.exterior.read().half_edges.iter().cloned() { let mut half_edge = half_edge.write(); let mut curve = half_edge.curve; From 93e3adadd8d76eda873d0a7d572a59285b51b6d3 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 15:23:52 +0100 Subject: [PATCH 40/42] Replace use of `PartialHalfEdge`'s `end_vertex` --- crates/fj-kernel/src/builder/face.rs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/crates/fj-kernel/src/builder/face.rs b/crates/fj-kernel/src/builder/face.rs index 5e9e5c452..89037ca7f 100644 --- a/crates/fj-kernel/src/builder/face.rs +++ b/crates/fj-kernel/src/builder/face.rs @@ -1,6 +1,7 @@ use std::{array, collections::VecDeque}; use fj_interop::ext::ArrayExt; +use itertools::Itertools; use crate::{ geometry::curve::Curve, @@ -93,7 +94,14 @@ impl FaceBuilder for PartialFace { } fn infer_curves(&mut self) { - for mut half_edge in self.exterior.read().half_edges.iter().cloned() { + for (mut half_edge, next_half_edge) in self + .exterior + .read() + .half_edges + .iter() + .cloned() + .circular_tuple_windows() + { let mut half_edge = half_edge.write(); let mut curve = half_edge.curve; @@ -107,13 +115,15 @@ impl FaceBuilder for PartialFace { "Inferring undefined circles is not supported yet" ), MaybeCurve::UndefinedLine => { - let points_surface = - [&half_edge.start_vertex, &half_edge.end_vertex] - .map(|vertex| { - vertex.read().position.expect( - "Can't infer curve without surface points", - ) - }); + let points_surface = [ + &half_edge.start_vertex, + &next_half_edge.read().start_vertex, + ] + .map(|vertex| { + vertex.read().position.expect( + "Can't infer curve without surface points", + ) + }); let (line, points_curve) = Curve::line_from_points(points_surface); From d2763cfc2a15021d6eda1a7f8b287e870b90a513 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 16:04:59 +0100 Subject: [PATCH 41/42] Prepare code for follow-on change --- crates/fj-kernel/src/partial/objects/edge.rs | 4 ++-- 1 file 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 8811c7496..d9dbb1e97 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -65,8 +65,8 @@ impl PartialObject for PartialHalfEdge { let boundary = self.boundary.map(|point| { point.expect("Can't build `HalfEdge` without boundary positions") }); - let [start_vertex, end_vertex] = [self.start_vertex, self.end_vertex] - .map(|surface_vertex| surface_vertex.build(objects)); + let start_vertex = self.start_vertex.build(objects); + let end_vertex = self.end_vertex.build(objects); let global_form = self.global_form.build(objects); HalfEdge::new(curve, boundary, start_vertex, end_vertex, global_form) From 9d258871ec1616acfac2303153c0ca6e1569928a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 28 Feb 2023 16:06:35 +0100 Subject: [PATCH 42/42] Prepare code for follow-on change --- crates/fj-kernel/src/partial/objects/edge.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index d9dbb1e97..5c4ad3c8b 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -1,6 +1,3 @@ -use std::array; - -use fj_interop::ext::ArrayExt; use fj_math::Point; use crate::{ @@ -76,9 +73,10 @@ impl PartialObject for PartialHalfEdge { impl Default for PartialHalfEdge { fn default() -> Self { let curve = None; - let surface_vertices = array::from_fn(|_| Partial::default()); + let start_vertex = Partial::default(); + let end_vertex = Partial::default(); - let global_vertices = surface_vertices.each_ref_ext().map( + let global_vertices = [&start_vertex, &end_vertex].map( |vertex: &Partial| { let surface_vertex = vertex.clone(); let global_vertex = surface_vertex.read().global_form.clone(); @@ -90,8 +88,6 @@ impl Default for PartialHalfEdge { vertices: global_vertices, }); - let [start_vertex, end_vertex] = surface_vertices; - Self { curve, boundary: [None; 2],