diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs index d59f5ae66..f52f1129d 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs @@ -72,18 +72,11 @@ impl CurveEdgeIntersection { #[cfg(test)] mod tests { - use std::array; - - use fj_interop::ext::ArrayExt; use fj_math::Point; use crate::{ builder::{CurveBuilder, HalfEdgeBuilder}, - objects::Vertex, - partial::{ - Partial, PartialCurve, PartialGlobalEdge, PartialHalfEdge, - PartialObject, - }, + partial::{Partial, PartialCurve, PartialHalfEdge, PartialObject}, services::Services, }; @@ -103,29 +96,13 @@ mod tests { curve.update_as_u_axis(); let curve = curve.build(&mut services.objects); let half_edge = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + surface, + [[1., -1.], [1., 1.]], + ); - half_edge - .update_as_line_segment_from_points( - surface, - [[1., -1.], [1., 1.]], - ) - .build(&mut services.objects) + half_edge.build(&mut services.objects) }; let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -152,29 +129,13 @@ mod tests { curve.update_as_u_axis(); let curve = curve.build(&mut services.objects); let half_edge = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + surface, + [[-1., -1.], [-1., 1.]], + ); - half_edge - .update_as_line_segment_from_points( - surface, - [[-1., -1.], [-1., 1.]], - ) - .build(&mut services.objects) + half_edge.build(&mut services.objects) }; let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -201,29 +162,13 @@ mod tests { curve.update_as_u_axis(); let curve = curve.build(&mut services.objects); let half_edge = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + surface, + [[-1., -1.], [1., -1.]], + ); - half_edge - .update_as_line_segment_from_points( - surface, - [[-1., -1.], [1., -1.]], - ) - .build(&mut services.objects) + half_edge.build(&mut services.objects) }; let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -245,29 +190,13 @@ mod tests { curve.update_as_u_axis(); let curve = curve.build(&mut services.objects); let half_edge = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + surface, + [[-1., 0.], [1., 0.]], + ); - half_edge - .update_as_line_segment_from_points( - surface, - [[-1., 0.], [1., 0.]], - ) - .build(&mut services.objects) + half_edge.build(&mut services.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 7ef4f6f63..df9e2c08a 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -185,20 +185,15 @@ impl Sweep for (Handle, Color) { #[cfg(test)] mod tests { - use std::array; - - use fj_interop::{ext::ArrayExt, mesh::Color}; + use fj_interop::mesh::Color; use pretty_assertions::assert_eq; use crate::{ algorithms::{reverse::Reverse, sweep::Sweep}, builder::HalfEdgeBuilder, insert::Insert, - objects::{Cycle, Vertex}, partial::{ - Partial, PartialCurve, PartialFace, PartialGlobalEdge, - PartialHalfEdge, PartialObject, PartialSurfaceVertex, - PartialVertex, + Partial, PartialCycle, PartialFace, PartialHalfEdge, PartialObject, }, services::Services, }; @@ -208,30 +203,15 @@ mod tests { let mut services = Services::new(); let half_edge = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + Partial::from_full_entry_point( + services.objects.surfaces.xy_plane(), + ), + [[0., 0.], [1., 0.]], + ); half_edge - .update_as_line_segment_from_points( - Partial::from_full_entry_point( - services.objects.surfaces.xy_plane(), - ), - [[0., 0.], [1., 0.]], - ) .build(&mut services.objects) .insert(&mut services.objects) }; @@ -245,182 +225,99 @@ mod tests { ); let bottom = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + surface.clone(), + [[0., 0.], [1., 0.]], + ); half_edge - .update_as_line_segment_from_points( - surface.clone(), - [[0., 0.], [1., 0.]], - ) - .build(&mut services.objects) - .insert(&mut services.objects) }; let side_up = { - let vertices = [ - PartialVertex { - curve: Partial::from_partial(PartialCurve { - surface: Partial::from_full_entry_point( - bottom.front().surface_form().surface().clone(), - ), - ..Default::default() - }), - surface_form: Partial::from_full_entry_point( - bottom.front().surface_form().clone(), - ), - ..Default::default() - }, - PartialVertex { - surface_form: Partial::from_partial( - PartialSurfaceVertex { - position: Some([1., 1.].into()), - surface: surface.clone(), - ..Default::default() - }, - ), - ..Default::default() - }, - ] - .map(Partial::::from_partial); - - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); + let mut side_up = PartialHalfEdge::default(); + side_up.curve().write().surface = surface.clone(); - let side_up = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; + { + let [back, front] = &mut side_up.vertices; + + back.write().surface_form = + bottom.vertices[1].read().surface_form.clone(); + side_up.global_form.write().vertices[0] = + back.read().surface_form.read().global_form.clone(); + + let mut front = front.write(); + let mut front = front.surface_form.write(); + front.position = Some([1., 1.].into()); + front.surface = surface.clone(); + } + + side_up.update_as_line_segment(); side_up - .update_as_line_segment() - .build(&mut services.objects) - .insert(&mut services.objects) }; let top = { - let vertices = [ - PartialVertex { - curve: Partial::from_partial(PartialCurve { - surface: Partial::from_full_entry_point( - side_up - .front() - .surface_form() - .surface() - .clone(), - ), - ..Default::default() - }), - surface_form: Partial::from_partial( - PartialSurfaceVertex { - position: Some([0., 1.].into()), - surface, - ..Default::default() - }, - ), - ..Default::default() - }, - PartialVertex { - surface_form: Partial::from_full_entry_point( - side_up.front().surface_form().clone(), - ), - ..Default::default() - }, - ] - .map(Partial::::from_partial); - - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); + let mut top = PartialHalfEdge::default(); + top.curve().write().surface = surface.clone(); + + { + let [back, front] = &mut top.vertices; + + let mut back = back.write(); + let mut back = back.surface_form.write(); + back.position = Some([0., 1.].into()); + back.surface = surface.clone(); + + front.write().surface_form = + side_up.vertices[1].read().surface_form.clone(); + top.global_form.write().vertices[1] = + front.read().surface_form.read().global_form.clone(); + } + + top.update_as_line_segment(); - let top = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; - - top.update_as_line_segment() - .build(&mut services.objects) - .insert(&mut services.objects) - .reverse(&mut services.objects) + Partial::from_full_entry_point( + top.build(&mut services.objects) + .insert(&mut services.objects) + .reverse(&mut services.objects), + ) + .read() + .clone() }; let side_down = { - let vertices = [ - PartialVertex { - curve: Partial::from_partial(PartialCurve { - surface: Partial::from_full_entry_point( - bottom.back().surface_form().surface().clone(), - ), - ..Default::default() - }), - surface_form: Partial::from_full_entry_point( - bottom.back().surface_form().clone(), - ), - ..Default::default() - }, - PartialVertex { - surface_form: Partial::from_full_entry_point( - top.front().surface_form().clone(), - ), - ..Default::default() - }, - ] - .map(Partial::::from_partial); - - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); + let mut side_down = PartialHalfEdge::default(); + side_down.curve().write().surface = surface; + + let [back, front] = &mut side_down.vertices; + + back.write().surface_form = + bottom.vertices[0].read().surface_form.clone(); + side_down.global_form.write().vertices[0] = + back.read().surface_form.read().global_form.clone(); - let side_down = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; - - side_down - .update_as_line_segment() - .build(&mut services.objects) - .insert(&mut services.objects) - .reverse(&mut services.objects) + front.write().surface_form = + top.vertices[1].read().surface_form.clone(); + side_down.global_form.write().vertices[1] = + front.read().surface_form.read().global_form.clone(); + + side_down.update_as_line_segment(); + + Partial::from_full_entry_point( + side_down + .build(&mut services.objects) + .insert(&mut services.objects) + .reverse(&mut services.objects), + ) + .read() + .clone() }; - let cycle = Cycle::new([bottom, side_up, top, side_down]) - .insert(&mut services.objects); + let mut cycle = PartialCycle::default(); + cycle.half_edges.extend( + [bottom, side_up, top, side_down].map(Partial::from_partial), + ); let face = PartialFace { - exterior: Partial::from_full_entry_point(cycle), + exterior: Partial::from_partial(cycle), ..Default::default() }; face.build(&mut services.objects) diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 688a24d37..0d0bb546a 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -80,22 +80,14 @@ impl Sweep for Handle { #[cfg(test)] mod tests { - use std::array; - - use fj_interop::{ - ext::{ArrayExt, SliceExt}, - mesh::Color, - }; + use fj_interop::{ext::SliceExt, mesh::Color}; use crate::{ algorithms::{reverse::Reverse, transform::TransformObject}, builder::{FaceBuilder, HalfEdgeBuilder}, insert::Insert, - objects::{Sketch, Vertex}, - partial::{ - Partial, PartialFace, PartialGlobalEdge, PartialHalfEdge, - PartialObject, - }, + objects::Sketch, + partial::{Partial, PartialFace, PartialHalfEdge, PartialObject}, services::Services, }; @@ -139,30 +131,15 @@ mod tests { let triangle = TRIANGLE.as_slice(); let side_faces = triangle.array_windows_ext().map(|&[a, b]| { let half_edge = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + Partial::from_full_entry_point( + services.objects.surfaces.xy_plane(), + ), + [a, b], + ); half_edge - .update_as_line_segment_from_points( - Partial::from_full_entry_point( - services.objects.surfaces.xy_plane(), - ), - [a, b], - ) .build(&mut services.objects) .insert(&mut services.objects) }; @@ -207,30 +184,15 @@ mod tests { let triangle = TRIANGLE.as_slice(); let side_faces = triangle.array_windows_ext().map(|&[a, b]| { let half_edge = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + Partial::from_full_entry_point( + services.objects.surfaces.xy_plane(), + ), + [a, b], + ); half_edge - .update_as_line_segment_from_points( - Partial::from_full_entry_point( - services.objects.surfaces.xy_plane(), - ), - [a, b], - ) .build(&mut services.objects) .insert(&mut services.objects) .reverse(&mut services.objects) diff --git a/crates/fj-kernel/src/algorithms/sweep/vertex.rs b/crates/fj-kernel/src/algorithms/sweep/vertex.rs index ae67900a2..249383eb0 100644 --- a/crates/fj-kernel/src/algorithms/sweep/vertex.rs +++ b/crates/fj-kernel/src/algorithms/sweep/vertex.rs @@ -157,19 +157,15 @@ impl Sweep for Handle { #[cfg(test)] mod tests { - use std::array; - - use fj_interop::ext::ArrayExt; use pretty_assertions::assert_eq; use crate::{ algorithms::sweep::Sweep, builder::{CurveBuilder, HalfEdgeBuilder}, insert::Insert, - objects::Vertex, partial::{ - Partial, PartialCurve, PartialGlobalEdge, PartialHalfEdge, - PartialObject, PartialSurfaceVertex, PartialVertex, + Partial, PartialCurve, PartialHalfEdge, PartialObject, + PartialSurfaceVertex, PartialVertex, }, services::Services, }; @@ -202,28 +198,13 @@ mod tests { .sweep([0., 0., 1.], &mut services.objects); let expected_half_edge = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + Partial::from_full_entry_point(surface), + [[0., 0.], [0., 1.]], + ); half_edge - .update_as_line_segment_from_points( - Partial::from_full_entry_point(surface), - [[0., 0.], [0., 1.]], - ) .build(&mut services.objects) .insert(&mut services.objects) }; diff --git a/crates/fj-kernel/src/builder/curve.rs b/crates/fj-kernel/src/builder/curve.rs index 85d71a63c..cc904b321 100644 --- a/crates/fj-kernel/src/builder/curve.rs +++ b/crates/fj-kernel/src/builder/curve.rs @@ -4,19 +4,19 @@ use crate::{geometry::path::SurfacePath, partial::PartialCurve}; /// Builder API for [`PartialCurve`] pub trait CurveBuilder { - /// Update partial curve to represent the u-axis + /// Update partial curve to represent the u-axis of the surface it is on fn update_as_u_axis(&mut self) -> &mut Self; - /// Update partial curve to represent the v-axis + /// Update partial curve to represent the v-axis of the surface it is on fn update_as_v_axis(&mut self) -> &mut Self; - /// Update partial curve as a circle, from the provided radius + /// Update partial curve to be a circle, from the provided radius fn update_as_circle_from_radius( &mut self, radius: impl Into, ) -> &mut Self; - /// Update partial curve as a line, from the provided points + /// Update partial curve to be a line, from the provided points fn update_as_line_from_points( &mut self, points: [impl Into>; 2], diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index c43a83c91..46e946dcd 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -2,15 +2,12 @@ use fj_interop::ext::ArrayExt; use fj_math::Point; use crate::{ - objects::{Curve, Surface, SurfaceVertex, Vertex}, - partial::{ - Partial, PartialCurve, PartialCycle, PartialGlobalEdge, - PartialHalfEdge, PartialSurfaceVertex, PartialVertex, - }, + objects::{Surface, SurfaceVertex}, + partial::{Partial, PartialCycle, PartialHalfEdge, PartialSurfaceVertex}, storage::Handle, }; -use super::{CurveBuilder, HalfEdgeBuilder}; +use super::HalfEdgeBuilder; /// Builder API for [`PartialCycle`] pub trait CycleBuilder { @@ -54,47 +51,29 @@ impl CycleBuilder for PartialCycle { if let Some(vertex_prev) = previous { let surface = vertex_prev.read().surface.clone(); - let [position_prev, position_next] = - [&vertex_prev, &vertex_next].map(|vertex| { - vertex - .read() - .position - .expect("Need surface position to extend cycle") - }); - previous = Some(vertex_next.clone()); + let surface_vertices = [vertex_prev, vertex_next]; + + let mut half_edge = PartialHalfEdge::default(); + half_edge.curve().write().surface = surface; + + { + let global_vertices = + &mut half_edge.global_form.write().vertices; + + for ((vertex, surface_form), global_form) in half_edge + .vertices + .each_mut_ext() + .zip_ext(surface_vertices) + .zip_ext(global_vertices.each_mut_ext()) + { + *global_form = surface_form.read().global_form.clone(); + vertex.write().surface_form = surface_form; + } + } - let mut curve: Partial = - Partial::from_partial(PartialCurve { - surface: surface.clone(), - ..Default::default() - }); - curve - .write() - .update_as_line_from_points([position_prev, position_next]); - - let vertices = [(0., vertex_prev), (1., vertex_next)].map( - |(position, surface_form)| { - Partial::from_partial(PartialVertex { - position: Some([position].into()), - curve: curve.clone(), - surface_form, - }) - }, - ); - - let global_vertices = - vertices.each_ref_ext().map(|vertex: &Partial| { - vertex.read().surface_form.read().global_form.clone() - }); - - half_edges.push(Partial::from_partial(PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: curve.read().global_form.clone(), - vertices: global_vertices, - }), - })); + half_edge.update_as_line_segment(); + half_edges.push(Partial::from_partial(half_edge)); continue; } @@ -125,44 +104,40 @@ impl CycleBuilder for PartialCycle { let last = self.half_edges.last(); let vertices = [first, last].map(|option| { - option.map(|half_edge| half_edge.read().vertices.clone()) + option.map(|half_edge| { + half_edge + .read() + .vertices + .each_ref_ext() + .map(|vertex| vertex.read().surface_form.clone()) + }) }); let [Some([first, _]), Some([_, last])] = vertices else { return self; }; - let surface = self.surface().expect("Need surface to close cycle"); - let vertices = [last, first].map(|vertex| { - Partial::::from_partial(PartialVertex { - curve: Partial::from_partial(PartialCurve { - surface: surface.clone(), - ..Default::default() - }), - surface_form: vertex.read().surface_form.clone(), - ..Default::default() - }) - }); - let curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = Partial::from_partial( - PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve, - vertices: global_vertices, - }), + let mut half_edge = PartialHalfEdge::default(); + half_edge.curve().write().surface = + self.surface().expect("Need surface to close cycle"); + + { + let global_vertices = &mut half_edge.global_form.write().vertices; + + for ((vertex, surface_form), global_form) in half_edge + .vertices + .each_mut_ext() + .zip_ext([last, first]) + .zip_ext(global_vertices.each_mut_ext()) + { + *global_form = surface_form.read().global_form.clone(); + vertex.write().surface_form = surface_form; } - .update_as_line_segment(), - ); + } + + half_edge.update_as_line_segment(); - self.half_edges.push(half_edge); + self.half_edges.push(Partial::from_partial(half_edge)); self } } diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 3efb4613e..9df0a0caf 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -2,55 +2,36 @@ use fj_interop::ext::ArrayExt; use fj_math::{Point, Scalar}; use crate::{ - objects::{Curve, Surface, Vertex}, + objects::Surface, partial::{Partial, PartialGlobalEdge, PartialHalfEdge}, - storage::Handle, }; use super::{CurveBuilder, SurfaceVertexBuilder}; /// Builder API for [`PartialHalfEdge`] -pub trait HalfEdgeBuilder: Sized { - /// Update the partial half-edge with the given back vertex - fn with_back_vertex(self, back: Partial) -> Self; - - /// Update the partial half-edge with the given front vertex - fn with_front_vertex(self, front: Partial) -> Self; - - /// Update partial half-edge as a circle, from the given radius - fn update_as_circle_from_radius(self, radius: impl Into) -> Self; +pub trait HalfEdgeBuilder { + /// Update partial half-edge to be a circle, from the given radius + fn update_as_circle_from_radius( + &mut self, + radius: impl Into, + ) -> &mut Self; - /// Update partial half-edge as a line segment, from the given points + /// Update partial half-edge to be a line segment, from the given points fn update_as_line_segment_from_points( - self, + &mut self, surface: Partial, points: [impl Into>; 2], - ) -> Self; + ) -> &mut Self; - /// Update partial half-edge as a line segment, reusing existing vertices - fn update_as_line_segment(self) -> Self; - - /// Infer the global form of the partial half-edge - fn infer_global_form(self) -> Self; + /// Update partial half-edge to be a line segment + fn update_as_line_segment(&mut self) -> &mut Self; } impl HalfEdgeBuilder for PartialHalfEdge { - fn with_back_vertex(mut self, back: Partial) -> Self { - let [_, front] = self.vertices.clone(); - self.vertices = [back, front]; - self - } - - fn with_front_vertex(mut self, front: Partial) -> Self { - let [back, _] = self.vertices.clone(); - self.vertices = [back, front]; - self - } - fn update_as_circle_from_radius( - mut self, + &mut self, radius: impl Into, - ) -> Self { + ) -> &mut Self { let mut curve = self.curve(); curve.write().update_as_circle_from_radius(radius); @@ -62,9 +43,10 @@ impl HalfEdgeBuilder for PartialHalfEdge { let [a_curve, b_curve] = [Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord])); - let [vertex, _] = &mut self.vertices; - - let mut surface_vertex = vertex.write().surface_form.clone(); + let mut surface_vertex = { + let [vertex, _] = &mut self.vertices; + vertex.write().surface_form.clone() + }; surface_vertex.write().position = Some(path.point_from_path_coords(a_curve)); @@ -84,13 +66,12 @@ impl HalfEdgeBuilder for PartialHalfEdge { } fn update_as_line_segment_from_points( - mut self, + &mut self, surface: Partial, points: [impl Into>; 2], - ) -> Self { + ) -> &mut Self { for (vertex, point) in self.vertices.each_mut_ext().zip_ext(points) { let mut vertex = vertex.write(); - vertex.curve.write().surface = surface.clone(); let mut surface_form = vertex.surface_form.write(); @@ -102,65 +83,35 @@ impl HalfEdgeBuilder for PartialHalfEdge { self.update_as_line_segment() } - fn update_as_line_segment(mut self) -> Self { - let [from, to] = self.vertices.clone(); - let [from_surface, to_surface] = - [&from, &to].map(|vertex| vertex.read().surface_form.clone()); - - let surface = self.curve().read().surface.clone(); - let points = [&from_surface, &to_surface].map(|vertex| { + fn update_as_line_segment(&mut self) -> &mut Self { + let points_surface = self.vertices.each_ref_ext().map(|vertex| { vertex + .read() + .surface_form .read() .position .expect("Can't infer line segment without surface position") }); let mut curve = self.curve(); - curve.write().surface = surface; - curve.write().update_as_line_from_points(points); - - let [back, front] = { - [(from, 0.), (to, 1.)].map(|(mut vertex, position)| { - vertex.write().position = Some([position].into()); - vertex.write().curve = self.curve(); - vertex - }) - }; + curve.write().update_as_line_from_points(points_surface); - self.vertices = [back, front]; + for (vertex, position) in self.vertices.each_mut_ext().zip_ext([0., 1.]) + { + vertex.write().position = Some([position].into()); + vertex.write().curve = curve.clone(); + } self.global_form.write().curve = curve.read().global_form.clone(); self } - - fn infer_global_form(mut self) -> Self { - self.global_form = Partial::new(); - self - } } /// Builder API for [`PartialGlobalEdge`] pub trait GlobalEdgeBuilder { - /// Update partial global edge from the given curve and vertices - fn update_from_curve_and_vertices( - self, - curve: &Curve, - vertices: &[Handle; 2], - ) -> Self; + // No methods are currently defined. This trait serves as a placeholder, to + // make it clear where to add such methods, once necessary. } -impl GlobalEdgeBuilder for PartialGlobalEdge { - fn update_from_curve_and_vertices( - mut self, - curve: &Curve, - vertices: &[Handle; 2], - ) -> Self { - self.curve = - Partial::from_full_entry_point(curve.global_form().clone()); - self.vertices = vertices.clone().map(|vertex| { - Partial::from_full_entry_point(vertex.global_form().clone()) - }); - self - } -} +impl GlobalEdgeBuilder for PartialGlobalEdge {} diff --git a/crates/fj-kernel/src/builder/shell.rs b/crates/fj-kernel/src/builder/shell.rs index 2f1dc1818..1b30d88de 100644 --- a/crates/fj-kernel/src/builder/shell.rs +++ b/crates/fj-kernel/src/builder/shell.rs @@ -89,41 +89,39 @@ impl ShellBuilder { .read() .clone(); - Partial::from_partial( - PartialHalfEdge { - vertices: global_edge.vertices.clone().map( - |global_vertex| { - Partial::from_partial(PartialVertex { - curve: Partial::from_partial( - PartialCurve { - global_form: global_edge - .curve - .clone(), - ..Default::default() - }, - ), - surface_form: Partial::from_partial( - PartialSurfaceVertex { - global_form: global_vertex, - ..Default::default() - }, - ), - ..Default::default() - }) - }, - ), - global_form: Partial::from_partial( - PartialGlobalEdge { - curve: global_edge.curve, - vertices: global_edge.vertices, - }, - ), - } - .update_as_line_segment_from_points( - Partial::from_full_entry_point(surface.clone()), - [[Z, Z], [edge_length, Z]], + let mut half_edge = PartialHalfEdge { + vertices: global_edge.vertices.clone().map( + |global_vertex| { + Partial::from_partial(PartialVertex { + curve: Partial::from_partial( + PartialCurve { + global_form: global_edge + .curve + .clone(), + ..Default::default() + }, + ), + surface_form: Partial::from_partial( + PartialSurfaceVertex { + global_form: global_vertex, + ..Default::default() + }, + ), + ..Default::default() + }) + }, ), - ) + global_form: Partial::from_partial(PartialGlobalEdge { + curve: global_edge.curve, + vertices: global_edge.vertices, + }), + }; + half_edge.update_as_line_segment_from_points( + Partial::from_full_entry_point(surface.clone()), + [[Z, Z], [edge_length, Z]], + ); + + Partial::from_partial(half_edge) }) .collect::>(); @@ -179,18 +177,16 @@ impl ShellBuilder { .clone() }); - Partial::from_partial( - PartialHalfEdge { - vertices, - global_form: Partial::from_partial( - PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }, - ), - } - .update_as_line_segment(), - ) + let mut half_edge = PartialHalfEdge { + vertices, + global_form: Partial::from_partial(PartialGlobalEdge { + curve: global_curve, + vertices: global_vertices, + }), + }; + half_edge.update_as_line_segment(); + + Partial::from_partial(half_edge) }) .collect::>(); @@ -273,18 +269,18 @@ impl ShellBuilder { .clone() }); - Partial::from_partial( - PartialHalfEdge { - vertices, - global_form: Partial::from_partial( - PartialGlobalEdge { - vertices: global_vertices, - curve: curve.global_form, - }, - ), - } - .update_as_line_segment(), - ) + let mut half_edge = PartialHalfEdge { + vertices, + global_form: Partial::from_partial( + PartialGlobalEdge { + vertices: global_vertices, + curve: curve.global_form, + }, + ), + }; + half_edge.update_as_line_segment(); + + Partial::from_partial(half_edge) }, ) .collect::>() @@ -334,18 +330,16 @@ impl ShellBuilder { .clone() }); - Partial::from_partial( - PartialHalfEdge { - vertices, - global_form: Partial::from_partial( - PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }, - ), - } - .update_as_line_segment(), - ) + let mut half_edge = PartialHalfEdge { + vertices, + global_form: Partial::from_partial(PartialGlobalEdge { + curve: global_curve, + vertices: global_vertices, + }), + }; + half_edge.update_as_line_segment(); + + Partial::from_partial(half_edge) }) .collect::>(); @@ -443,16 +437,16 @@ impl ShellBuilder { ), }); - edges.push(Partial::from_partial( - PartialHalfEdge { - vertices: vertices.map(Partial::from_partial), - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_edge.read().curve.clone(), - vertices: global_edge.read().vertices.clone(), - }), - } - .update_as_line_segment(), - )); + let mut half_edge = PartialHalfEdge { + vertices: vertices.map(Partial::from_partial), + global_form: Partial::from_partial(PartialGlobalEdge { + curve: global_edge.read().curve.clone(), + vertices: global_edge.read().vertices.clone(), + }), + }; + half_edge.update_as_line_segment(); + + edges.push(Partial::from_partial(half_edge)); } let face = PartialFace { diff --git a/crates/fj-kernel/src/builder/vertex.rs b/crates/fj-kernel/src/builder/vertex.rs index 2d12dd6d0..dcf1bac7a 100644 --- a/crates/fj-kernel/src/builder/vertex.rs +++ b/crates/fj-kernel/src/builder/vertex.rs @@ -1,33 +1,19 @@ -use fj_math::Point; - -use crate::{ - geometry::surface::SurfaceGeometry, - objects::Curve, - partial::{ - Partial, PartialGlobalVertex, PartialSurfaceVertex, PartialVertex, - }, +use crate::partial::{ + PartialGlobalVertex, PartialSurfaceVertex, PartialVertex, }; /// Builder API for [`PartialVertex`] pub trait VertexBuilder { - /// Remove the surface form of the partial vertex, inferring it on build - fn infer_surface_form(&mut self) -> &mut Self; + // No methods are currently defined. This trait serves as a placeholder, to + // make it clear where to add such methods, once necessary. } -impl VertexBuilder for PartialVertex { - fn infer_surface_form(&mut self) -> &mut Self { - self.surface_form = Partial::new(); - self - } -} +impl VertexBuilder for PartialVertex {} /// Builder API for [`PartialSurfaceVertex`] pub trait SurfaceVertexBuilder { /// Infer the position of the surface vertex' global form fn infer_global_position(&mut self) -> &mut Self; - - /// Infer the global form of the partial vertex - fn infer_global_form(&mut self) -> &mut Self; } impl SurfaceVertexBuilder for PartialSurfaceVertex { @@ -46,51 +32,12 @@ impl SurfaceVertexBuilder for PartialSurfaceVertex { self } - - fn infer_global_form(&mut self) -> &mut Self { - self.global_form = Partial::new(); - self - } } /// Builder API for [`PartialGlobalVertex`] -pub trait GlobalVertexBuilder { - /// Update partial global vertex from the given curve and position on it - fn from_curve_and_position( - curve: Partial, - position: impl Into>, - ) -> Self; - - /// Update partial global vertex from the given surface and position on it - fn from_surface_and_position( - surface: &SurfaceGeometry, - position: impl Into>, - ) -> Self; -} +pub trait GlobalVertexBuilder {} impl GlobalVertexBuilder for PartialGlobalVertex { - fn from_curve_and_position( - curve: Partial, - position: impl Into>, - ) -> Self { - let path = curve.read().path.expect( - "Need path to create `GlobalVertex` from curve and position", - ); - let surface = curve.read().surface.read().geometry.expect( - "Need surface to create `GlobalVertex` from curve and position", - ); - - let position_surface = path.point_from_path_coords(position); - - Self::from_surface_and_position(&surface, position_surface) - } - - fn from_surface_and_position( - surface: &SurfaceGeometry, - position: impl Into>, - ) -> Self { - Self { - position: Some(surface.point_from_surface_coords(position)), - } - } + // No methods are currently defined. This trait serves as a placeholder, to + // make it clear where to add such methods, once necessary. } diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index 6ec8de881..066f49c5b 100644 --- a/crates/fj-kernel/src/iter.rs +++ b/crates/fj-kernel/src/iter.rs @@ -359,10 +359,6 @@ impl Iterator for Iter { #[cfg(test)] mod tests { - use std::array; - - use fj_interop::ext::ArrayExt; - use crate::{ builder::{CurveBuilder, CycleBuilder, FaceBuilder, HalfEdgeBuilder}, insert::Insert, @@ -371,8 +367,8 @@ mod tests { SurfaceVertex, Vertex, }, partial::{ - Partial, PartialCurve, PartialCycle, PartialFace, - PartialGlobalEdge, PartialHalfEdge, PartialObject, + Partial, PartialCurve, PartialCycle, PartialFace, PartialHalfEdge, + PartialObject, }, services::Services, }; @@ -503,30 +499,15 @@ mod tests { let mut services = Services::new(); let object = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + Partial::from_full_entry_point( + services.objects.surfaces.xy_plane(), + ), + [[0., 0.], [1., 0.]], + ); half_edge - .update_as_line_segment_from_points( - Partial::from_full_entry_point( - services.objects.surfaces.xy_plane(), - ), - [[0., 0.], [1., 0.]], - ) .build(&mut services.objects) .insert(&mut services.objects) }; diff --git a/crates/fj-kernel/src/objects/full/edge.rs b/crates/fj-kernel/src/objects/full/edge.rs index e45c5176d..c79b0a539 100644 --- a/crates/fj-kernel/src/objects/full/edge.rs +++ b/crates/fj-kernel/src/objects/full/edge.rs @@ -144,15 +144,11 @@ impl VerticesInNormalizedOrder { #[cfg(test)] mod tests { - use std::array; - - use fj_interop::ext::ArrayExt; use pretty_assertions::assert_eq; use crate::{ builder::HalfEdgeBuilder, - objects::Vertex, - partial::{Partial, PartialGlobalEdge, PartialHalfEdge, PartialObject}, + partial::{Partial, PartialHalfEdge, PartialObject}, services::Services, }; @@ -168,47 +164,17 @@ mod tests { let b = [1., 0.]; let a_to_b = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; - + let mut half_edge = PartialHalfEdge::default(); half_edge - .update_as_line_segment_from_points(surface.clone(), [a, b]) - .build(&mut services.objects) + .update_as_line_segment_from_points(surface.clone(), [a, b]); + + half_edge.build(&mut services.objects) }; let b_to_a = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); - - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; - half_edge - .update_as_line_segment_from_points(surface, [b, a]) - .build(&mut services.objects) + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points(surface, [b, a]); + + half_edge.build(&mut services.objects) }; assert_eq!(a_to_b.global_form(), b_to_a.global_form()); diff --git a/crates/fj-kernel/src/validate/edge.rs b/crates/fj-kernel/src/validate/edge.rs index 8008fd674..7e79d4ef0 100644 --- a/crates/fj-kernel/src/validate/edge.rs +++ b/crates/fj-kernel/src/validate/edge.rs @@ -198,17 +198,13 @@ impl HalfEdgeValidationError { #[cfg(test)] mod tests { - use std::array; - - use fj_interop::ext::ArrayExt; - use crate::{ builder::HalfEdgeBuilder, insert::Insert, - objects::{GlobalCurve, HalfEdge, Vertex}, + objects::{GlobalCurve, HalfEdge}, partial::{ - Partial, PartialGlobalEdge, PartialHalfEdge, PartialObject, - PartialSurfaceVertex, PartialVertex, + Partial, PartialHalfEdge, PartialObject, PartialSurfaceVertex, + PartialVertex, }, services::Services, validate::Validate, @@ -219,31 +215,15 @@ mod tests { let mut services = Services::new(); let valid = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + Partial::from_full_entry_point( + services.objects.surfaces.xy_plane(), + ), + [[0., 0.], [1., 0.]], + ); - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; - - half_edge - .update_as_line_segment_from_points( - Partial::from_full_entry_point( - services.objects.surfaces.xy_plane(), - ), - [[0., 0.], [1., 0.]], - ) - .build(&mut services.objects) + half_edge.build(&mut services.objects) }; let invalid = { let mut vertices = valid.vertices().clone(); @@ -269,31 +249,15 @@ mod tests { let mut services = Services::new(); let valid = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + Partial::from_full_entry_point( + services.objects.surfaces.xy_plane(), + ), + [[0., 0.], [1., 0.]], + ); - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; - - half_edge - .update_as_line_segment_from_points( - Partial::from_full_entry_point( - services.objects.surfaces.xy_plane(), - ), - [[0., 0.], [1., 0.]], - ) - .build(&mut services.objects) + half_edge.build(&mut services.objects) }; let invalid = HalfEdge::new(valid.vertices().clone(), { let mut tmp = @@ -313,31 +277,15 @@ mod tests { let mut services = Services::new(); let valid = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + Partial::from_full_entry_point( + services.objects.surfaces.xy_plane(), + ), + [[0., 0.], [1., 0.]], + ); - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; - - half_edge - .update_as_line_segment_from_points( - Partial::from_full_entry_point( - services.objects.surfaces.xy_plane(), - ), - [[0., 0.], [1., 0.]], - ) - .build(&mut services.objects) + half_edge.build(&mut services.objects) }; let invalid = HalfEdge::new(valid.vertices().clone(), { let mut tmp = @@ -364,31 +312,15 @@ mod tests { let mut services = Services::new(); let valid = { - let vertices = array::from_fn(|_| Partial::::new()); - let global_curve = { - let [vertex, _] = &vertices; - vertex.read().curve.read().global_form.clone() - }; - let global_vertices = vertices.each_ref_ext().map(|vertex| { - vertex.read().surface_form.read().global_form.clone() - }); + let mut half_edge = PartialHalfEdge::default(); + half_edge.update_as_line_segment_from_points( + Partial::from_full_entry_point( + services.objects.surfaces.xy_plane(), + ), + [[0., 0.], [1., 0.]], + ); - let half_edge = PartialHalfEdge { - vertices, - global_form: Partial::from_partial(PartialGlobalEdge { - curve: global_curve, - vertices: global_vertices, - }), - }; - - half_edge - .update_as_line_segment_from_points( - Partial::from_full_entry_point( - services.objects.surfaces.xy_plane(), - ), - [[0., 0.], [1., 0.]], - ) - .build(&mut services.objects) + half_edge.build(&mut services.objects) }; let invalid = HalfEdge::new( valid.vertices().clone().map(|vertex| { diff --git a/crates/fj-kernel/src/validate/vertex.rs b/crates/fj-kernel/src/validate/vertex.rs index bfa1cc5bc..600e840cc 100644 --- a/crates/fj-kernel/src/validate/vertex.rs +++ b/crates/fj-kernel/src/validate/vertex.rs @@ -180,7 +180,7 @@ impl SurfaceVertexValidationError { #[cfg(test)] mod tests { use crate::{ - builder::{CurveBuilder, SurfaceVertexBuilder}, + builder::CurveBuilder, insert::Insert, objects::{GlobalVertex, SurfaceVertex, Vertex}, partial::{ @@ -256,7 +256,7 @@ mod tests { let mut surface_form = Partial::from_full_entry_point(valid.surface_form().clone()); surface_form.write().position = Some([1., 0.].into()); - surface_form.write().infer_global_form(); + surface_form.write().global_form = Partial::new(); let surface_form = surface_form.build(&mut services.objects); Vertex::new(valid.position(), valid.curve().clone(), surface_form) diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index e92e3addf..7409fe863 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -59,16 +59,16 @@ impl Shape for fj::Sketch { }, ); - let half_edge = PartialHalfEdge { + let mut half_edge = PartialHalfEdge { vertices, global_form: Partial::from_partial(PartialGlobalEdge { curve: curve.read().global_form.clone(), vertices: global_vertices, }), }; - Partial::from_partial( - half_edge.update_as_circle_from_radius(circle.radius()), - ) + half_edge.update_as_circle_from_radius(circle.radius()); + + Partial::from_partial(half_edge) }; let cycle = Partial::from_partial(PartialCycle::new(vec![half_edge]));