diff --git a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs index 76cf88a13..a8c6e99f3 100644 --- a/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs +++ b/crates/fj-kernel/src/algorithms/intersect/curve_edge.rs @@ -90,9 +90,9 @@ mod tests { .with_surface(surface) .as_u_axis() .build(&stores); - let half_edge = HalfEdge::builder(&stores, surface) - .as_line_segment_from_points([[1., -1.], [1., 1.]]) - .build(); + let half_edge = HalfEdge::partial() + .as_line_segment_from_points(surface, [[1., -1.], [1., 1.]]) + .build(&stores); let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -113,9 +113,9 @@ mod tests { .with_surface(surface) .as_u_axis() .build(&stores); - let half_edge = HalfEdge::builder(&stores, surface) - .as_line_segment_from_points([[-1., -1.], [-1., 1.]]) - .build(); + let half_edge = HalfEdge::partial() + .as_line_segment_from_points(surface, [[-1., -1.], [-1., 1.]]) + .build(&stores); let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -136,9 +136,9 @@ mod tests { .with_surface(surface) .as_u_axis() .build(&stores); - let half_edge = HalfEdge::builder(&stores, surface) - .as_line_segment_from_points([[-1., -1.], [1., -1.]]) - .build(); + let half_edge = HalfEdge::partial() + .as_line_segment_from_points(surface, [[-1., -1.], [1., -1.]]) + .build(&stores); let intersection = CurveEdgeIntersection::compute(&curve, &half_edge); @@ -154,9 +154,9 @@ mod tests { .with_surface(surface) .as_u_axis() .build(&stores); - let half_edge = HalfEdge::builder(&stores, surface) - .as_line_segment_from_points([[-1., 0.], [1., 0.]]) - .build(); + let half_edge = HalfEdge::partial() + .as_line_segment_from_points(surface, [[-1., 0.], [1., 0.]]) + .build(&stores); 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 bbb680784..420883466 100644 --- a/crates/fj-kernel/src/algorithms/sweep/edge.rs +++ b/crates/fj-kernel/src/algorithms/sweep/edge.rs @@ -191,29 +191,32 @@ mod tests { fn sweep() { let stores = Stores::new(); - let half_edge = HalfEdge::builder(&stores, Surface::xy_plane()) - .as_line_segment_from_points([[0., 0.], [1., 0.]]) - .build(); + let half_edge = HalfEdge::partial() + .as_line_segment_from_points( + Surface::xy_plane(), + [[0., 0.], [1., 0.]], + ) + .build(&stores); let face = (half_edge, Color::default()).sweep([0., 0., 1.], &stores); let expected_face = { let surface = Surface::xz_plane(); - let bottom = HalfEdge::builder(&stores, surface) - .as_line_segment_from_points([[0., 0.], [1., 0.]]) - .build(); - let top = HalfEdge::builder(&stores, surface) - .as_line_segment_from_points([[0., 1.], [1., 1.]]) - .build() + let bottom = HalfEdge::partial() + .as_line_segment_from_points(surface, [[0., 0.], [1., 0.]]) + .build(&stores); + let top = HalfEdge::partial() + .as_line_segment_from_points(surface, [[0., 1.], [1., 1.]]) + .build(&stores) .reverse(); - let left = HalfEdge::builder(&stores, surface) - .as_line_segment_from_points([[0., 0.], [0., 1.]]) - .build() + let left = HalfEdge::partial() + .as_line_segment_from_points(surface, [[0., 0.], [0., 1.]]) + .build(&stores) .reverse(); - let right = HalfEdge::builder(&stores, surface) - .as_line_segment_from_points([[1., 0.], [1., 1.]]) - .build(); + let right = HalfEdge::partial() + .as_line_segment_from_points(surface, [[1., 0.], [1., 1.]]) + .build(&stores); let cycle = Cycle::new(surface, [bottom, right, top, left]); diff --git a/crates/fj-kernel/src/algorithms/sweep/face.rs b/crates/fj-kernel/src/algorithms/sweep/face.rs index 9872e0466..68a9300c5 100644 --- a/crates/fj-kernel/src/algorithms/sweep/face.rs +++ b/crates/fj-kernel/src/algorithms/sweep/face.rs @@ -112,9 +112,9 @@ mod tests { // https://doc.rust-lang.org/std/primitive.slice.html#method.array_windows let [a, b] = [window[0], window[1]]; - let half_edge = HalfEdge::builder(&stores, Surface::xy_plane()) - .as_line_segment_from_points([a, b]) - .build(); + let half_edge = HalfEdge::partial() + .as_line_segment_from_points(Surface::xy_plane(), [a, b]) + .build(&stores); (half_edge, Color::default()).sweep(UP, &stores) }); @@ -148,9 +148,9 @@ mod tests { // https://doc.rust-lang.org/std/primitive.slice.html#method.array_windows let [a, b] = [window[0], window[1]]; - let half_edge = HalfEdge::builder(&stores, Surface::xy_plane()) - .as_line_segment_from_points([a, b]) - .build() + let half_edge = HalfEdge::partial() + .as_line_segment_from_points(Surface::xy_plane(), [a, b]) + .build(&stores) .reverse(); (half_edge, Color::default()).sweep(DOWN, &stores) }); diff --git a/crates/fj-kernel/src/algorithms/sweep/vertex.rs b/crates/fj-kernel/src/algorithms/sweep/vertex.rs index cb99bd323..81b12cc8d 100644 --- a/crates/fj-kernel/src/algorithms/sweep/vertex.rs +++ b/crates/fj-kernel/src/algorithms/sweep/vertex.rs @@ -172,9 +172,9 @@ mod tests { let half_edge = (vertex, surface).sweep([0., 0., 1.], &stores); - let expected_half_edge = HalfEdge::builder(&stores, surface) - .as_line_segment_from_points([[0., 0.], [0., 1.]]) - .build(); + let expected_half_edge = HalfEdge::partial() + .as_line_segment_from_points(surface, [[0., 0.], [0., 1.]]) + .build(&stores); assert_eq!(half_edge, expected_half_edge); } diff --git a/crates/fj-kernel/src/algorithms/validate/mod.rs b/crates/fj-kernel/src/algorithms/validate/mod.rs index 20f880c8f..6966f8683 100644 --- a/crates/fj-kernel/src/algorithms/validate/mod.rs +++ b/crates/fj-kernel/src/algorithms/validate/mod.rs @@ -236,8 +236,9 @@ mod tests { ); let vertices = [a, b]; - let global_edge = GlobalEdge::builder() - .build_from_curve_and_vertices(&curve, &vertices); + let global_edge = GlobalEdge::partial() + .from_curve_and_vertices(&curve, &vertices) + .build(&stores); let half_edge = HalfEdge::new(curve, vertices, global_edge); let result = diff --git a/crates/fj-kernel/src/builder/cycle.rs b/crates/fj-kernel/src/builder/cycle.rs index 346caef0a..d3e3a95c6 100644 --- a/crates/fj-kernel/src/builder/cycle.rs +++ b/crates/fj-kernel/src/builder/cycle.rs @@ -1,7 +1,7 @@ use fj_math::Point; use crate::{ - objects::{Cycle, HalfEdge, Surface}, + objects::{Curve, Cycle, HalfEdge, Surface, SurfaceVertex, Vertex}, stores::Stores, }; @@ -34,28 +34,64 @@ impl<'a> CycleBuilder<'a> { mut self, points: impl IntoIterator>>, ) -> Self { - let points = self + let iter = self .half_edges .last() .map(|half_edge| { let [_, last] = half_edge.vertices(); - last.surface_form().position() + + let vertex = *last.surface_form(); + let position = last.surface_form().position(); + + (position, Some(vertex)) }) .into_iter() - .chain(points.into_iter().map(Into::into)) - .collect::>(); + .chain(points.into_iter().map(|point| (point.into(), None))); - for points in points.windows(2) { - // Can't panic, as we passed `2` to `windows`. - // - // Can be cleaned up, once `array_windows` is stable. - let points = [points[0], points[1]]; + let mut previous: Option<(Point<2>, Option)> = None; - self.half_edges.push( - HalfEdge::builder(self.stores, self.surface) - .as_line_segment_from_points(points) - .build(), - ); + for (position, vertex) in iter { + if let Some((previous_position, previous_vertex)) = previous { + let from = previous_vertex.unwrap_or_else(|| { + SurfaceVertex::partial() + .with_surface(self.surface) + .with_position(previous_position) + .build(self.stores) + }); + let to = vertex.unwrap_or_else(|| { + SurfaceVertex::partial() + .with_surface(self.surface) + .with_position(position) + .build(self.stores) + }); + + previous = Some((position, Some(to))); + + let curve = Curve::partial() + .with_surface(self.surface) + .as_line_from_points([previous_position, position]) + .build(self.stores); + + let [from, to] = + [(0., from), (1., to)].map(|(position, surface_form)| { + Vertex::partial() + .with_curve(curve.clone()) + .with_position([position]) + .with_surface_form(surface_form) + .build(self.stores) + }); + + self.half_edges.push( + HalfEdge::partial() + .with_curve(curve) + .with_vertices([from, to]) + .build(self.stores), + ); + + continue; + } + + previous = Some((position, vertex)); } self @@ -74,9 +110,9 @@ impl<'a> CycleBuilder<'a> { let vertices = [last, first].map(|vertex| vertex.surface_form().position()); self.half_edges.push( - HalfEdge::builder(self.stores, self.surface) - .as_line_segment_from_points(vertices) - .build(), + HalfEdge::partial() + .as_line_segment_from_points(self.surface, vertices) + .build(self.stores), ); } diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs deleted file mode 100644 index e5262dd70..000000000 --- a/crates/fj-kernel/src/builder/edge.rs +++ /dev/null @@ -1,197 +0,0 @@ -use fj_math::{Line, Point, Scalar}; - -use crate::{ - objects::{ - Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Surface, - SurfaceVertex, Vertex, - }, - path::{GlobalPath, SurfacePath}, - stores::Stores, -}; - -/// API for building a [`HalfEdge`] -/// -/// Also see [`HalfEdge::builder`]. -pub struct HalfEdgeBuilder<'a> { - /// The stores that the created objects are put in - pub stores: &'a Stores, - - /// The surface that the [`HalfEdge`]'s [`Curve`] is defined in - pub surface: Surface, - - /// The curve that the [`HalfEdge`] is defined in - pub curve: Option, - - /// The vertices that bound this [`HalfEdge`] in the [`Curve`] - pub vertices: Option<[Vertex; 2]>, - - /// The global form of the [`HalfEdge`] - /// - /// Can be provided to the builder, if available, or computed by one of the - /// build methods. - pub global_form: Option, -} - -impl<'a> HalfEdgeBuilder<'a> { - /// Build the [`HalfEdge`] with the given curve - pub fn with_curve(mut self, curve: Curve) -> Self { - self.curve = Some(curve); - self - } - - /// Build the [`HalfEdge`] with the given vertices - pub fn with_vertices(mut self, vertices: [Vertex; 2]) -> Self { - self.vertices = Some(vertices); - self - } - - /// Build the [`HalfEdge`] with the provided global form - pub fn with_global_form(mut self, global_form: GlobalEdge) -> Self { - self.global_form = Some(global_form); - self - } - - /// Build the [`HalfEdge`] as a circle from the given radius - pub fn as_circle_from_radius(mut self, radius: impl Into) -> Self { - let curve = Curve::partial() - .with_surface(self.surface) - .as_circle_from_radius(radius) - .build(self.stores); - - let vertices = { - let [a_curve, b_curve] = - [Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord])); - - let global_vertex = GlobalVertex::partial() - .from_curve_and_position(curve.clone(), a_curve) - .build(self.stores); - - let surface_vertices = [a_curve, b_curve].map(|point_curve| { - let point_surface = - curve.path().point_from_path_coords(point_curve); - SurfaceVertex::new(point_surface, self.surface, global_vertex) - }); - - // Can be cleaned up, once `zip` is stable: - // https://doc.rust-lang.org/std/primitive.array.html#method.zip - let [a_surface, b_surface] = surface_vertices; - [(a_curve, a_surface), (b_curve, b_surface)].map( - |(point_curve, surface_vertex)| { - Vertex::new( - point_curve, - curve.clone(), - surface_vertex, - global_vertex, - ) - }, - ) - }; - - self.curve = Some(curve); - self.vertices = Some(vertices); - - self - } - - /// Build the [`HalfEdge`] as a line segment from the given points - pub fn as_line_segment_from_points( - mut self, - points: [impl Into>; 2], - ) -> Self { - let points = points.map(Into::into); - - let global_vertices = points.map(|position| { - GlobalVertex::partial() - .from_surface_and_position(&self.surface, position) - .build(self.stores) - }); - - let surface_vertices = { - // Can be cleaned up, once `zip` is stable: - // https://doc.rust-lang.org/std/primitive.array.html#method.zip - let [a_surface, b_surface] = points; - let [a_global, b_global] = global_vertices; - [(a_surface, a_global), (b_surface, b_global)].map( - |(point_surface, vertex_global)| { - SurfaceVertex::new( - point_surface, - self.surface, - vertex_global, - ) - }, - ) - }; - - let curve = { - let path = SurfacePath::Line(Line::from_points(points)); - let global_form = { - let points = global_vertices - .map(|global_vertex| global_vertex.position()); - self.stores.global_curves.insert(GlobalCurve::from_path( - GlobalPath::Line(Line::from_points(points)), - )) - }; - - Curve::new(self.surface, path, global_form) - }; - - let vertices = { - let [a_global, b_global] = global_vertices; - let [a_surface, b_surface] = surface_vertices; - - [ - Vertex::new( - Point::from([0.]), - curve.clone(), - a_surface, - a_global, - ), - Vertex::new( - Point::from([1.]), - curve.clone(), - b_surface, - b_global, - ), - ] - }; - - self.curve = Some(curve); - self.vertices = Some(vertices); - - self - } - - /// Finish building the [`HalfEdge`] - pub fn build(self) -> HalfEdge { - let curve = self.curve.expect("Can't build `HalfEdge` without curve"); - let vertices = self - .vertices - .expect("Can't build `HalfEdge` without vertices"); - - let global_form = self.global_form.unwrap_or_else(|| { - GlobalEdge::builder() - .build_from_curve_and_vertices(&curve, &vertices) - }); - - HalfEdge::new(curve, vertices, global_form) - } -} - -/// API for building a [`GlobalEdge`] -/// -/// Also see [`GlobalEdge::builder`]. -pub struct GlobalEdgeBuilder; - -impl GlobalEdgeBuilder { - /// Build a [`GlobalEdge`] from the provided curve and vertices - pub fn build_from_curve_and_vertices( - self, - curve: &Curve, - vertices: &[Vertex; 2], - ) -> GlobalEdge { - GlobalEdge::new( - curve.global_form().clone(), - vertices.clone().map(|vertex| *vertex.global_form()), - ) - } -} diff --git a/crates/fj-kernel/src/builder/mod.rs b/crates/fj-kernel/src/builder/mod.rs index f71b4b476..f8e4aa1fb 100644 --- a/crates/fj-kernel/src/builder/mod.rs +++ b/crates/fj-kernel/src/builder/mod.rs @@ -1,17 +1,12 @@ //! API for building objects mod cycle; -mod edge; mod face; mod shell; mod sketch; mod solid; pub use self::{ - cycle::CycleBuilder, - edge::{GlobalEdgeBuilder, HalfEdgeBuilder}, - face::FaceBuilder, - shell::ShellBuilder, - sketch::SketchBuilder, - solid::SolidBuilder, + cycle::CycleBuilder, face::FaceBuilder, shell::ShellBuilder, + sketch::SketchBuilder, solid::SolidBuilder, }; diff --git a/crates/fj-kernel/src/iter.rs b/crates/fj-kernel/src/iter.rs index aff05ce1c..3a23b9bd2 100644 --- a/crates/fj-kernel/src/iter.rs +++ b/crates/fj-kernel/src/iter.rs @@ -464,9 +464,12 @@ mod tests { fn half_edge() { let stores = Stores::new(); - let object = HalfEdge::builder(&stores, Surface::xy_plane()) - .as_line_segment_from_points([[0., 0.], [1., 0.]]) - .build(); + let object = HalfEdge::partial() + .as_line_segment_from_points( + Surface::xy_plane(), + [[0., 0.], [1., 0.]], + ) + .build(&stores); assert_eq!(1, object.curve_iter().count()); assert_eq!(0, object.cycle_iter().count()); diff --git a/crates/fj-kernel/src/objects/edge.rs b/crates/fj-kernel/src/objects/edge.rs index b435d5584..06ca67168 100644 --- a/crates/fj-kernel/src/objects/edge.rs +++ b/crates/fj-kernel/src/objects/edge.rs @@ -1,11 +1,11 @@ use std::fmt; use crate::{ - builder::{GlobalEdgeBuilder, HalfEdgeBuilder}, - stores::{Handle, Stores}, + partial::{PartialGlobalEdge, PartialHalfEdge}, + stores::Handle, }; -use super::{Curve, GlobalCurve, GlobalVertex, Surface, Vertex}; +use super::{Curve, GlobalCurve, GlobalVertex, Vertex}; /// A half-edge #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] @@ -16,15 +16,12 @@ pub struct HalfEdge { } impl HalfEdge { - /// Build a `HalfEdge` using [`HalfEdgeBuilder`] - pub fn builder(stores: &Stores, surface: Surface) -> HalfEdgeBuilder { - HalfEdgeBuilder { - stores, - surface, - curve: None, - vertices: None, - global_form: None, - } + /// Create a [`PartialHalfEdge`] + /// + /// This function exists just for convenience, and will just return a + /// default [`PartialHalfEdge`]. + pub fn partial() -> PartialHalfEdge { + PartialHalfEdge::default() } /// Create a new instance of `HalfEdge` @@ -120,9 +117,12 @@ pub struct GlobalEdge { } impl GlobalEdge { - /// Build a `GlobalEdge` using [`GlobalEdgeBuilder`] - pub fn builder() -> GlobalEdgeBuilder { - GlobalEdgeBuilder + /// Create a [`PartialGlobalEdge`] + /// + /// This function exists just for convenience, and will just return a + /// default [`PartialGlobalEdge`]. + pub fn partial() -> PartialGlobalEdge { + PartialGlobalEdge::default() } /// Create a new instance diff --git a/crates/fj-kernel/src/partial/edge.rs b/crates/fj-kernel/src/partial/edge.rs new file mode 100644 index 000000000..aefe4865e --- /dev/null +++ b/crates/fj-kernel/src/partial/edge.rs @@ -0,0 +1,204 @@ +use fj_math::{Point, Scalar}; + +use crate::{ + objects::{ + Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Surface, Vertex, + }, + stores::{Handle, Stores}, +}; + +use super::MaybePartial; + +/// A partial [`HalfEdge`] +/// +/// See [`crate::partial`] for more information. +#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct PartialHalfEdge { + /// The curve that the [`HalfEdge`] is defined in + pub curve: Option>, + + /// The vertices that bound this [`HalfEdge`] in the [`Curve`] + pub vertices: [Option>; 2], + + /// The global form of the [`HalfEdge`] + /// + /// Can be computed by [`PartialHalfEdge::build`], if not available. + pub global_form: Option, +} + +impl PartialHalfEdge { + /// Update the partial half-edge with the given curve + pub fn with_curve(mut self, curve: impl Into>) -> Self { + self.curve = Some(curve.into()); + self + } + + /// Update the partial half-edge with the given vertices + pub fn with_vertices( + mut self, + vertices: [impl Into>; 2], + ) -> Self { + self.vertices = vertices.map(Into::into).map(Some); + self + } + + /// Update the partial half-edge, starting it from the given vertex + pub fn with_from_vertex( + mut self, + vertex: impl Into>, + ) -> Self { + self.vertices[0] = Some(vertex.into()); + self + } + + /// Update the partial half-edge with the given end vertex + pub fn with_to_vertex( + mut self, + vertex: impl Into>, + ) -> Self { + self.vertices[1] = Some(vertex.into()); + self + } + + /// Update the partial half-edge with the given global form + pub fn with_global_form(mut self, global_form: GlobalEdge) -> Self { + self.global_form = Some(global_form); + self + } + + /// Update partial half-edge as a circle, from the given radius + pub fn as_circle_from_radius( + mut self, + surface: Surface, + radius: impl Into, + ) -> Self { + let curve = Curve::partial() + .with_surface(surface) + .as_circle_from_radius(radius); + + let vertices = { + let [a_curve, b_curve] = + [Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord])); + + let global_vertex = GlobalVertex::partial() + .from_curve_and_position(curve.clone(), a_curve); + + [a_curve, b_curve].map(|point_curve| { + Vertex::partial() + .with_position(point_curve) + .with_curve(curve.clone()) + .with_global_form(global_vertex.clone()) + }) + }; + + self.curve = Some(curve.into()); + self.vertices = vertices.map(Into::into).map(Some); + + self + } + + /// Update partial half-edge as a line segment, from the given points + pub fn as_line_segment_from_points( + mut self, + surface: Surface, + points: [impl Into>; 2], + ) -> Self { + let curve = Curve::partial() + .with_surface(surface) + .as_line_from_points(points); + + let vertices = [0., 1.].map(|position| { + Vertex::partial() + .with_position([position]) + .with_curve(curve.clone()) + }); + + self.curve = Some(curve.into()); + self.vertices = vertices.map(Into::into).map(Some); + + self + } + + /// Build a full [`HalfEdge`] from the partial half-edge + pub fn build(self, stores: &Stores) -> HalfEdge { + let curve = self + .curve + .expect("Can't build `HalfEdge` without curve") + .into_full(stores); + let vertices = self.vertices.map(|vertex| { + vertex + .expect("Can't build `HalfEdge` without vertices") + .into_full(stores) + }); + + let global_form = self.global_form.unwrap_or_else(|| { + GlobalEdge::partial() + .from_curve_and_vertices(&curve, &vertices) + .build(stores) + }); + + HalfEdge::new(curve, vertices, global_form) + } +} + +impl From for PartialHalfEdge { + fn from(half_edge: HalfEdge) -> Self { + Self { + curve: Some(half_edge.curve().clone().into()), + vertices: half_edge.vertices().clone().map(Into::into).map(Some), + global_form: Some(half_edge.global_form().clone()), + } + } +} + +/// A partial [`GlobalEdge`] +/// +/// See [`crate::partial`] for more information. +#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub struct PartialGlobalEdge { + /// The curve that the [`GlobalEdge`] is defined in + /// + /// Must be provided before [`PartialGlobalEdge::build`] is called. + pub curve: Option>, + + /// The vertices that bound the [`GlobalEdge`] in the curve + /// + /// Must be provided before [`PartialGlobalEdge::build`] is called. + pub vertices: Option<[GlobalVertex; 2]>, +} + +impl PartialGlobalEdge { + /// Update partial global edge from the given curve and vertices + pub fn from_curve_and_vertices( + mut self, + curve: &Curve, + vertices: &[Vertex; 2], + ) -> Self { + self.curve = Some(curve.global_form().clone()); + self.vertices = + Some(vertices.clone().map(|vertex| *vertex.global_form())); + + self + } + + /// Build a full [`GlobalEdge`] from the partial global edge + pub fn build(self, _: &Stores) -> GlobalEdge { + let curve = self + .curve + .expect("Can't build `GlobalEdge` without `GlobalCurve`"); + let vertices = self + .vertices + .expect("Can't build `GlobalEdge` without vertices"); + + GlobalEdge::new(curve, vertices) + } +} + +impl From for PartialGlobalEdge { + fn from(global_edge: GlobalEdge) -> Self { + Self { + curve: Some(global_edge.curve().clone()), + vertices: Some(*global_edge.vertices()), + } + } +} diff --git a/crates/fj-kernel/src/partial/mod.rs b/crates/fj-kernel/src/partial/mod.rs index 6877e5943..6b8fca4fb 100644 --- a/crates/fj-kernel/src/partial/mod.rs +++ b/crates/fj-kernel/src/partial/mod.rs @@ -26,15 +26,20 @@ //! convenient API. mod curve; +mod edge; mod vertex; pub use self::{ curve::{PartialCurve, PartialGlobalCurve}, + edge::{PartialGlobalEdge, PartialHalfEdge}, vertex::{PartialGlobalVertex, PartialSurfaceVertex, PartialVertex}, }; use crate::{ - objects::{Curve, GlobalCurve, GlobalVertex, SurfaceVertex, Vertex}, + objects::{ + Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, SurfaceVertex, + Vertex, + }, stores::{Handle, Stores}, }; @@ -113,7 +118,9 @@ macro_rules! impl_traits { impl_traits!( Curve, PartialCurve; + GlobalEdge, PartialGlobalEdge; GlobalVertex, PartialGlobalVertex; + HalfEdge, PartialHalfEdge; SurfaceVertex, PartialSurfaceVertex; Vertex, PartialVertex; diff --git a/crates/fj-operations/src/sketch.rs b/crates/fj-operations/src/sketch.rs index eab95e706..1c174367a 100644 --- a/crates/fj-operations/src/sketch.rs +++ b/crates/fj-operations/src/sketch.rs @@ -26,9 +26,9 @@ impl Shape for fj::Sketch { // Circles have just a single round edge with no vertices. So // none need to be added here. - let half_edge = HalfEdge::builder(stores, surface) - .as_circle_from_radius(circle.radius()) - .build(); + let half_edge = HalfEdge::partial() + .as_circle_from_radius(surface, circle.radius()) + .build(stores); let cycle = Cycle::new(surface, [half_edge]); Face::from_exterior(cycle).with_color(Color(self.color()))