diff --git a/crates/fj-kernel/src/algorithms/approx/edge.rs b/crates/fj-kernel/src/algorithms/approx/edge.rs index 76988c7c4..7d5e467b5 100644 --- a/crates/fj-kernel/src/algorithms/approx/edge.rs +++ b/crates/fj-kernel/src/algorithms/approx/edge.rs @@ -338,22 +338,14 @@ mod tests { v: [0., 0., 1.].into(), }) .insert(&mut services.objects); - let half_edge = { - let mut cycle = PartialCycle::new(&mut services.objects); - - let [mut half_edge, _, _] = cycle.update_as_polygon_from_points( - [[0., 1.], [1., 1.], [1., 2.]], - &mut services.objects, - ); - - half_edge.write().boundary[0] = Some(range.boundary[0]); - half_edge.write().boundary[1] = Some(range.boundary[1]); - - let half_edge = half_edge.read().clone(); - half_edge - .build(&mut services.objects) - .insert(&mut services.objects) - }; + let half_edge = PartialHalfEdge::make_line_segment( + [[0., 1.], [TAU, 1.]], + Some(range.boundary), + None, + None, + &mut services.objects, + ) + .build(&mut services.objects); let tolerance = 1.; let approx = (&half_edge, surface.deref()).approx(tolerance); diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 155cf5db6..c3f0757ed 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -1,6 +1,5 @@ use std::ops::Deref; -use fj_interop::ext::ArrayExt; use fj_math::{Scalar, Vector}; use itertools::Itertools; @@ -64,13 +63,6 @@ impl Sweep for Handle { for (i, cycle) in bottom_face.all_cycles().cloned().enumerate() { let cycle = cycle.reverse(objects); - let mut top_cycle = if i == 0 { - top_face.exterior.clone() - } else { - top_face.add_interior(objects) - }; - - let mut original_edges = Vec::new(); let mut top_edges = Vec::new(); for (half_edge, next) in cycle.half_edges().cloned().circular_tuple_windows() @@ -85,26 +77,19 @@ impl Sweep for Handle { faces.push(face); - original_edges.push(half_edge); - top_edges.push(Partial::from(top_edge)); + top_edges.push(( + Partial::from(top_edge), + half_edge.curve(), + half_edge.boundary(), + )); } + let mut top_cycle = if i == 0 { + top_face.exterior.clone() + } else { + top_face.add_interior(objects) + }; top_cycle.write().connect_to_edges(top_edges, objects); - - for (bottom, top) in original_edges - .into_iter() - .zip(top_cycle.write().half_edges.iter_mut()) - { - top.write().curve = Some(bottom.curve()); - - let boundary = bottom.boundary(); - - for (top, bottom) in - top.write().boundary.each_mut_ext().zip_ext(boundary) - { - *top = Some(bottom); - } - } } let top_face = top_face.build(objects).insert(objects); diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 2ee669fec..758065f86 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -1,6 +1,7 @@ use fj_math::Point; use crate::{ + geometry::curve::Curve, objects::{HalfEdge, Objects}, partial::{Partial, PartialCycle, PartialHalfEdge}, services::Service, @@ -43,7 +44,7 @@ pub trait CycleBuilder { objects: &mut Service, ) -> O::SameSize> where - O: ObjectArgument>; + O: ObjectArgument<(Partial, Curve, [Point<1>; 2])>; } impl CycleBuilder for PartialCycle { @@ -81,15 +82,20 @@ impl CycleBuilder for PartialCycle { objects: &mut Service, ) -> O::SameSize> where - O: ObjectArgument>, + O: ObjectArgument<(Partial, Curve, [Point<1>; 2])>, { - edges.map_with_prev(|_, prev| { - let mut edge: Partial = Partial::new(objects); - edge.write().start_vertex = prev.read().start_vertex.clone(); + edges.map_with_prev(|(_, curve, boundary), (prev, _, _)| { + let half_edge = PartialHalfEdge::make_half_edge( + curve, + boundary, + Some(prev.read().start_vertex.clone()), + None, + objects, + ); - self.add_half_edge(edge.clone()); + self.add_half_edge(half_edge.clone()); - edge + half_edge }) } } diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 7eb5625b7..be395df81 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -112,8 +112,8 @@ impl HalfEdgeBuilder for PartialHalfEdge { objects: &mut Service, ) -> Partial { Partial::from_partial(PartialHalfEdge { - curve: Some(curve), - boundary: boundary.map(Some), + curve, + boundary, start_vertex: start_vertex .unwrap_or_else(|| Vertex::new().insert(objects)), global_form: global_form diff --git a/crates/fj-kernel/src/partial/objects/edge.rs b/crates/fj-kernel/src/partial/objects/edge.rs index ae6165fa4..7f637590e 100644 --- a/crates/fj-kernel/src/partial/objects/edge.rs +++ b/crates/fj-kernel/src/partial/objects/edge.rs @@ -2,7 +2,6 @@ use fj_math::Point; use crate::{ geometry::curve::Curve, - insert::Insert, objects::{GlobalEdge, HalfEdge, Objects, Vertex}, partial::{FullToPartialCache, PartialObject}, services::Service, @@ -13,10 +12,10 @@ use crate::{ #[derive(Clone, Debug)] pub struct PartialHalfEdge { /// The curve that the half-edge is defined in - pub curve: Option, + pub curve: Curve, /// The boundary of the half-edge on the curve - pub boundary: [Option>; 2], + pub boundary: [Point<1>; 2], /// The surface vertex where the half-edge starts pub start_vertex: Handle, @@ -25,48 +24,30 @@ pub struct PartialHalfEdge { pub global_form: Handle, } -impl PartialHalfEdge { - /// Compute the surface position where the half-edge starts - pub fn start_position(&self) -> Option> { - // Computing the surface position from the curve position is fine. - // `HalfEdge` "owns" its start position. There is no competing code that - // could compute the surface position from slightly different data. - - let [start, _] = self.boundary; - start.and_then(|start| { - let curve = self.curve?; - Some(curve.point_from_path_coords(start)) - }) - } -} - impl PartialObject for PartialHalfEdge { type Full = HalfEdge; - fn new(objects: &mut Service) -> Self { - Self { - curve: None, - boundary: [None; 2], - start_vertex: Vertex::new().insert(objects), - global_form: GlobalEdge::new().insert(objects), - } + fn new(_: &mut Service) -> Self { + // This method is no longer used, and since `PartialHalfEdge` will be + // replaced with `HalfEdge`, it will soon be removed. + unreachable!() } fn from_full(half_edge: &Self::Full, _: &mut FullToPartialCache) -> Self { Self { - curve: Some(half_edge.curve()), - boundary: half_edge.boundary().map(Some), + curve: half_edge.curve(), + boundary: half_edge.boundary(), start_vertex: half_edge.start_vertex().clone(), global_form: half_edge.global_form().clone(), } } fn build(self, _: &mut Service) -> Self::Full { - let curve = self.curve.expect("Need path to build curve"); - let boundary = self.boundary.map(|point| { - point.expect("Can't build `HalfEdge` without boundary positions") - }); - - HalfEdge::new(curve, boundary, self.start_vertex, self.global_form) + HalfEdge::new( + self.curve, + self.boundary, + self.start_vertex, + self.global_form, + ) } }