diff --git a/crates/fj-kernel/src/algorithms/sweep/edge.rs b/crates/fj-kernel/src/algorithms/sweep/edge.rs index e3b90745a..c370e01c0 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -173,7 +173,7 @@ impl Sweep for (Handle, Color) { #[cfg(test)] mod tests { - use fj_interop::mesh::Color; + use fj_interop::{ext::ArrayExt, mesh::Color}; use pretty_assertions::assert_eq; use crate::{ @@ -222,11 +222,14 @@ mod tests { side_up.curve.write().surface = surface.clone(); { - let [back, front] = &mut side_up.vertices; + let [back, front] = side_up + .vertices + .each_mut_ext() + .map(|(_, surface_vertex)| surface_vertex); - back.surface_form = bottom.vertices[1].surface_form.clone(); + *back = bottom.vertices[1].1.clone(); - let mut front = front.surface_form.write(); + let mut front = front.write(); front.position = Some([1., 1.].into()); front.surface = surface.clone(); } @@ -241,14 +244,16 @@ mod tests { top.curve.write().surface = surface.clone(); { - let [back, front] = &mut top.vertices; + let [back, front] = top + .vertices + .each_mut_ext() + .map(|(_, surface_vertex)| surface_vertex); - let mut back = back.surface_form.write(); + let mut back = back.write(); back.position = Some([0., 1.].into()); back.surface = surface.clone(); - front.surface_form = - side_up.vertices[1].surface_form.clone(); + *front = side_up.vertices[1].1.clone(); } top.infer_global_form(); @@ -266,10 +271,13 @@ mod tests { let mut side_down = PartialHalfEdge::default(); side_down.curve.write().surface = surface; - let [back, front] = &mut side_down.vertices; + let [back, front] = side_down + .vertices + .each_mut_ext() + .map(|(_, surface_vertex)| surface_vertex); - back.surface_form = bottom.vertices[0].surface_form.clone(); - front.surface_form = top.vertices[1].surface_form.clone(); + *back = bottom.vertices[0].1.clone(); + *front = top.vertices[1].1.clone(); side_down.infer_global_form(); side_down.update_as_line_segment(); diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index a6dc84c92..c0eb39796 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -98,22 +98,28 @@ impl CycleBuilder for PartialCycle { }; { - let shared_surface_vertex = - new_half_edge.read().back().surface_form.clone(); + let shared_surface_vertex = { + let [vertex, _] = &new_half_edge.read().vertices; + vertex.1.clone() + }; let mut last_half_edge = last_half_edge.write(); - last_half_edge.front_mut().surface_form = shared_surface_vertex; + let [_, vertex] = &mut last_half_edge.vertices; + vertex.1 = shared_surface_vertex; last_half_edge.infer_global_form(); } { - let shared_surface_vertex = - first_half_edge.read().back().surface_form.clone(); + let shared_surface_vertex = { + let [vertex, _] = &first_half_edge.read().vertices; + vertex.1.clone() + }; let mut new_half_edge = new_half_edge.write(); - new_half_edge.front_mut().surface_form = shared_surface_vertex; + let [_, vertex] = &mut new_half_edge.vertices; + vertex.1 = shared_surface_vertex; new_half_edge.replace_surface(self.surface.clone()); new_half_edge.infer_global_form(); } @@ -128,8 +134,10 @@ impl CycleBuilder for PartialCycle { ) -> Partial { let mut half_edge = self.add_half_edge(); - half_edge.write().back_mut().surface_form.write().position = - Some(point.into()); + { + let [vertex, _] = &mut half_edge.write().vertices; + vertex.1.write().position = Some(point.into()); + } half_edge } @@ -140,14 +148,10 @@ impl CycleBuilder for PartialCycle { ) -> Partial { let mut half_edge = self.add_half_edge(); - half_edge - .write() - .back_mut() - .surface_form - .write() - .global_form - .write() - .position = Some(point.into()); + { + let [vertex, _] = &mut half_edge.write().vertices; + vertex.1.write().global_form.write().position = Some(point.into()); + } half_edge } @@ -187,14 +191,8 @@ impl CycleBuilder for PartialCycle { for (mut half_edge, point) in half_edges.clone().zip_ext(points_global) { - half_edge - .write() - .back_mut() - .surface_form - .write() - .global_form - .write() - .position = Some(point); + let [vertex, _] = &mut half_edge.write().vertices; + vertex.1.write().global_form.write().position = Some(point); } half_edges diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 31ba4642f..3f608935f 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -6,7 +6,7 @@ use crate::{ partial::{MaybeSurfacePath, Partial, PartialGlobalEdge, PartialHalfEdge}, }; -use super::{CurveBuilder, VertexBuilder}; +use super::CurveBuilder; /// Builder API for [`PartialHalfEdge`] pub trait HalfEdgeBuilder { @@ -61,7 +61,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { self.curve.write().surface = surface.clone(); for vertex in &mut self.vertices { - vertex.replace_surface(surface.clone()); + vertex.1.write().surface = surface.clone(); } } @@ -73,7 +73,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { let mut surface_vertex = { let [vertex, _] = &mut self.vertices; - vertex.surface_form.clone() + vertex.1.clone() }; surface_vertex.write().position = Some(path.point_from_path_coords(a_curve)); @@ -82,8 +82,8 @@ impl HalfEdgeBuilder for PartialHalfEdge { self.vertices.each_mut_ext().zip_ext([a_curve, b_curve]) { let mut vertex = vertex; - vertex.position = Some(point_curve); - vertex.surface_form = surface_vertex.clone(); + vertex.0 = Some(point_curve); + vertex.1 = surface_vertex.clone(); } self.infer_global_form(); @@ -96,7 +96,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { } let points_surface = self.vertices.each_ref_ext().map(|vertex| { vertex - .surface_form + .1 .read() .position .expect("Can't infer arc without surface position") @@ -123,8 +123,8 @@ impl HalfEdgeBuilder for PartialHalfEdge { for (vertex, point_curve) in self.vertices.each_mut_ext().zip_ext([a_curve, b_curve]) { - vertex.position = Some(point_curve); - vertex.surface_form.write().position = + vertex.0 = Some(point_curve); + vertex.1.write().position = Some(path.point_from_path_coords(point_curve)); } @@ -141,7 +141,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { self.curve.write().surface = surface.clone(); for (vertex, point) in self.vertices.each_mut_ext().zip_ext(points) { - let mut surface_form = vertex.surface_form.write(); + let mut surface_form = vertex.1.write(); surface_form.position = Some(point.into()); surface_form.surface = surface.clone(); } @@ -152,7 +152,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { fn update_as_line_segment(&mut self) { let points_surface = self.vertices.each_ref_ext().map(|vertex| { vertex - .surface_form + .1 .read() .position .expect("Can't infer line segment without surface position") @@ -164,7 +164,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { for (vertex, position) in self.vertices.each_mut_ext().zip_ext([0., 1.]) { - vertex.position = Some([position].into()); + vertex.0 = Some([position].into()); } self.infer_global_form(); @@ -175,7 +175,7 @@ impl HalfEdgeBuilder for PartialHalfEdge { self.global_form.write().vertices = self .vertices .each_ref_ext() - .map(|vertex| vertex.surface_form.read().global_form.clone()); + .map(|vertex| vertex.1.read().global_form.clone()); self.global_form.clone() } @@ -198,8 +198,8 @@ impl HalfEdgeBuilder for PartialHalfEdge { .iter_mut() .zip(other.read().vertices.iter().rev()) { - this.surface_form.write().global_form.write().position = - other.surface_form.read().global_form.read().position; + this.1.write().global_form.write().position = + other.1.read().global_form.read().position; } } } diff --git a/crates/fj-kernel/src/builder/face.rs b/crates/fj-kernel/src/builder/face.rs index e89149c03..294cd8350 100644 --- a/crates/fj-kernel/src/builder/face.rs +++ b/crates/fj-kernel/src/builder/face.rs @@ -109,10 +109,10 @@ impl FaceBuilder for PartialFace { fn update_surface_as_plane(&mut self) -> Partial { let mut exterior = self.exterior.write(); - let mut vertices = exterior - .half_edges - .iter() - .map(|half_edge| half_edge.read().back().surface_form.clone()); + let mut vertices = exterior.half_edges.iter().map(|half_edge| { + let [vertex, _] = &half_edge.read().vertices; + vertex.1.clone() + }); let vertices = { let array = [ @@ -165,7 +165,7 @@ impl FaceBuilder for PartialFace { MaybeSurfacePath::UndefinedLine => { let points_surface = half_edge.vertices.each_ref_ext().map(|vertex| { - vertex.surface_form.read().position.expect( + vertex.1.read().position.expect( "Can't infer curve without surface points", ) }); @@ -178,7 +178,7 @@ impl FaceBuilder for PartialFace { .each_mut_ext() .zip_ext(points_curve) { - vertex.position = Some(point); + vertex.0 = Some(point); } } } diff --git a/crates/fj-kernel/src/builder/mod.rs b/crates/fj-kernel/src/builder/mod.rs index 9fd19b034..9568fd64f 100644 --- a/crates/fj-kernel/src/builder/mod.rs +++ b/crates/fj-kernel/src/builder/mod.rs @@ -22,7 +22,7 @@ pub use self::{ sketch::SketchBuilder, solid::SolidBuilder, surface::SurfaceBuilder, - vertex::{GlobalVertexBuilder, SurfaceVertexBuilder, VertexBuilder}, + vertex::{GlobalVertexBuilder, SurfaceVertexBuilder}, }; /// Pass objects to a builder method @@ -44,7 +44,7 @@ pub trait ObjectArgument: IntoIterator { /// is generic. type SameSize; - /// A return value that has one more element thatn the argument + /// A return value that has one more element than the argument type SizePlusOne; /// Return the number of objects diff --git a/crates/fj-kernel/src/builder/vertex.rs b/crates/fj-kernel/src/builder/vertex.rs index 2b3dda16a..298bd88c4 100644 --- a/crates/fj-kernel/src/builder/vertex.rs +++ b/crates/fj-kernel/src/builder/vertex.rs @@ -1,31 +1,6 @@ use fj_math::Point; -use crate::{ - objects::Surface, - partial::{ - Partial, PartialGlobalVertex, PartialSurfaceVertex, PartialVertex, - }, -}; - -/// Builder API for [`PartialVertex`] -pub trait VertexBuilder { - /// Completely replace the surface in this vertex' object graph - /// - /// Please note that this operation will write to every partial object that - /// the vertex references. If any of them were created from full objects, - /// this will break the connection to those, meaning that building the - /// partial objects won't result in those full objects again. This will be - /// the case, even if those full objects already referenced the provided - /// surface. - fn replace_surface(&mut self, surface: impl Into>); -} - -impl VertexBuilder for PartialVertex { - fn replace_surface(&mut self, surface: impl Into>) { - let surface = surface.into(); - self.surface_form.write().surface = surface; - } -} +use crate::partial::{PartialGlobalVertex, PartialSurfaceVertex}; /// Builder API for [`PartialSurfaceVertex`] pub trait SurfaceVertexBuilder { diff --git a/crates/fj-kernel/src/partial/mod.rs b/crates/fj-kernel/src/partial/mod.rs index b67103567..f6209de04 100644 --- a/crates/fj-kernel/src/partial/mod.rs +++ b/crates/fj-kernel/src/partial/mod.rs @@ -24,7 +24,7 @@ pub use self::{ sketch::PartialSketch, solid::PartialSolid, surface::PartialSurface, - vertex::{PartialGlobalVertex, PartialSurfaceVertex, PartialVertex}, + vertex::{PartialGlobalVertex, PartialSurfaceVertex}, }, traits::{HasPartial, PartialObject}, wrapper::{FullToPartialCache, Partial}, diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index b7dbcb117..6eda1fe16 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -1,12 +1,16 @@ use std::array; use fj_interop::ext::ArrayExt; +use fj_math::Point; use crate::{ objects::{ Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects, + SurfaceVertex, + }, + partial::{ + FullToPartialCache, Partial, PartialObject, PartialSurfaceVertex, }, - partial::{FullToPartialCache, Partial, PartialObject, PartialVertex}, services::Service, }; @@ -17,38 +21,12 @@ pub struct PartialHalfEdge { pub curve: Partial, /// The vertices that bound the half-edge on the curve - pub vertices: [PartialVertex; 2], + pub vertices: [(Option>, Partial); 2], /// The global form of the half-edge pub global_form: Partial, } -impl PartialHalfEdge { - /// Access a reference to the half-edge's back vertex - pub fn back(&self) -> &PartialVertex { - let [back, _] = &self.vertices; - back - } - - /// Access a reference to the half-edge's front vertex - pub fn front(&self) -> &PartialVertex { - let [_, front] = &self.vertices; - front - } - - /// Access a mutable reference to the half-edge's back vertex - pub fn back_mut(&mut self) -> &mut PartialVertex { - let [back, _] = &mut self.vertices; - back - } - - /// Access a mutable reference to the half-edge's front vertex - pub fn front_mut(&mut self) -> &mut PartialVertex { - let [_, front] = &mut self.vertices; - front - } -} - impl PartialObject for PartialHalfEdge { type Full = HalfEdge; @@ -61,12 +39,11 @@ impl PartialObject for PartialHalfEdge { vertices: half_edge .boundary() .zip_ext(half_edge.surface_vertices()) - .map(|(position, surface_vertex)| PartialVertex { - position: Some(position), - surface_form: Partial::from_full( - surface_vertex.clone(), - cache, - ), + .map(|(position, surface_vertex)| { + ( + Some(position), + Partial::from_full(surface_vertex.clone(), cache), + ) }), global_form: Partial::from_full( half_edge.global_form().clone(), @@ -78,41 +55,38 @@ impl PartialObject for PartialHalfEdge { fn build(self, objects: &mut Service) -> Self::Full { let curve = self.curve.build(objects); let vertices = self.vertices.map(|mut vertex| { - let position_surface = vertex.surface_form.read().position; + let position_surface = vertex.1.read().position; // Infer surface position, if not available. let position_surface = match position_surface { Some(position_surface) => position_surface, None => { - let position_curve = vertex.position.expect( + let position_curve = vertex.0.expect( "Can't infer surface position without curve position", ); let position_surface = curve.path().point_from_path_coords(position_curve); - vertex.surface_form.write().position = - Some(position_surface); + vertex.1.write().position = Some(position_surface); position_surface } }; // Infer global position, if not available. - let position_global = - vertex.surface_form.read().global_form.read().position; + let position_global = vertex.1.read().global_form.read().position; if position_global.is_none() { let surface = curve.surface().geometry(); let position_global = surface.point_from_surface_coords(position_surface); - vertex.surface_form.write().global_form.write().position = + vertex.1.write().global_form.write().position = Some(position_global); } - let position = vertex - .position - .expect("Can't build `Vertex` without position"); - let surface_form = vertex.surface_form.build(objects); + let position = + vertex.0.expect("Can't build `Vertex` without position"); + let surface_form = vertex.1.build(objects); (position, surface_form) }); @@ -125,15 +99,25 @@ impl PartialObject for PartialHalfEdge { impl Default for PartialHalfEdge { fn default() -> Self { let curve = Partial::::new(); - let vertices = array::from_fn(|_| PartialVertex::default()); + let vertices = array::from_fn(|_| { + let surface = Partial::new(); + + let surface_form = Partial::from_partial(PartialSurfaceVertex { + surface, + ..Default::default() + }); + + (None, surface_form) + }); let global_curve = curve.read().global_form.clone(); - let global_vertices = - vertices.each_ref_ext().map(|vertex: &PartialVertex| { - let surface_vertex = vertex.surface_form.clone(); + let global_vertices = vertices.each_ref_ext().map( + |vertex: &(Option>, Partial)| { + let surface_vertex = vertex.1.clone(); let global_vertex = surface_vertex.read().global_form.clone(); global_vertex - }); + }, + ); let global_form = Partial::from_partial(PartialGlobalEdge { curve: global_curve, diff --git a/crates/fj-kernel/src/partial/objects/vertex.rs b/crates/fj-kernel/src/partial/objects/vertex.rs index 7ce785a90..74c0694e4 100644 --- a/crates/fj-kernel/src/partial/objects/vertex.rs +++ b/crates/fj-kernel/src/partial/objects/vertex.rs @@ -6,37 +6,6 @@ use crate::{ services::Service, }; -/// A partial vertex -/// -/// # Implementation Note -/// -/// This type is a hold-over from when there was still a `Vertex` object. It -/// will be remove too, at some point. -#[derive(Clone, Debug)] -pub struct PartialVertex { - /// The position of the vertex on the curve - pub position: Option>, - - /// The surface form of the vertex - pub surface_form: Partial, -} - -impl Default for PartialVertex { - fn default() -> Self { - let surface = Partial::new(); - - let surface_form = Partial::from_partial(PartialSurfaceVertex { - surface, - ..Default::default() - }); - - Self { - position: None, - surface_form, - } - } -} - /// A partial [`SurfaceVertex`] #[derive(Clone, Debug, Default)] pub struct PartialSurfaceVertex { diff --git a/crates/fj-kernel/src/validate/cycle.rs b/crates/fj-kernel/src/validate/cycle.rs index b3fb9bde8..3e253c009 100644 --- a/crates/fj-kernel/src/validate/cycle.rs +++ b/crates/fj-kernel/src/validate/cycle.rs @@ -94,10 +94,9 @@ mod tests { { let first_half_edge = half_edges.first_mut().unwrap(); let [first_vertex, _] = &mut first_half_edge.write().vertices; - let surface_vertex = Partial::from_partial( - first_vertex.surface_form.read().clone(), - ); - first_vertex.surface_form = surface_vertex; + let surface_vertex = + Partial::from_partial(first_vertex.1.read().clone()); + first_vertex.1 = surface_vertex; } let half_edges = half_edges diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index 00243f3aa..03f89119e 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -35,7 +35,7 @@ impl Shape for fj::Sketch { half_edge.curve.write().surface = surface.clone(); for vertex in &mut half_edge.vertices { - vertex.surface_form.write().surface = surface.clone(); + vertex.1.write().surface = surface.clone(); } half_edge.update_as_circle_from_radius(circle.radius());