From 91bd997b29b1360f706f80b8ab2bb72a26383f69 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 23 Sep 2022 14:15:42 +0200 Subject: [PATCH 1/6] Derive more traits for partial objects --- crates/fj-kernel/src/partial/curve.rs | 4 ++-- crates/fj-kernel/src/partial/vertex.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/fj-kernel/src/partial/curve.rs b/crates/fj-kernel/src/partial/curve.rs index f56a5c953..83572d014 100644 --- a/crates/fj-kernel/src/partial/curve.rs +++ b/crates/fj-kernel/src/partial/curve.rs @@ -9,7 +9,7 @@ use crate::{ /// A partial [`Curve`] /// /// See [`crate::partial`] for more information. -#[derive(Default)] +#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct PartialCurve { /// The path that defines the [`Curve`] /// @@ -104,7 +104,7 @@ impl PartialCurve { /// A partial [`GlobalCurve`] /// /// See [`crate::partial`] for more information. -#[derive(Default)] +#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct PartialGlobalCurve { /// The path that defines the [`GlobalCurve`] /// diff --git a/crates/fj-kernel/src/partial/vertex.rs b/crates/fj-kernel/src/partial/vertex.rs index 80f61cfc0..53e77f410 100644 --- a/crates/fj-kernel/src/partial/vertex.rs +++ b/crates/fj-kernel/src/partial/vertex.rs @@ -5,7 +5,7 @@ use crate::objects::{Curve, GlobalVertex, Surface, SurfaceVertex, Vertex}; /// A partial [`Vertex`] /// /// See [`crate::partial`] for more information. -#[derive(Default)] +#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct PartialVertex { /// The position of the [`Vertex`] on the [`Curve`] /// @@ -86,7 +86,7 @@ impl PartialVertex { /// A partial [`SurfaceVertex`] /// /// See [`crate::partial`] for more information. -#[derive(Default)] +#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct PartialSurfaceVertex { /// The position of the [`SurfaceVertex`] in the [`Surface`] /// @@ -152,7 +152,7 @@ impl PartialSurfaceVertex { /// A partial [`GlobalVertex`] /// /// See [`crate::partial`] for more information. -#[derive(Default)] +#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct PartialGlobalVertex { /// The position of the [`GlobalVertex`] /// From 5360a635faf95f60dfc27b3c8f0d9b6ad40caa40 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 23 Sep 2022 12:44:49 +0200 Subject: [PATCH 2/6] Simplify field of `PartialCurve` --- crates/fj-kernel/src/partial/curve.rs | 37 +++++++++++++-------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/crates/fj-kernel/src/partial/curve.rs b/crates/fj-kernel/src/partial/curve.rs index 83572d014..04d03fc78 100644 --- a/crates/fj-kernel/src/partial/curve.rs +++ b/crates/fj-kernel/src/partial/curve.rs @@ -25,7 +25,7 @@ pub struct PartialCurve { /// /// Will be computed from `path` and `surface` in [`PartialCurve::build`], /// if not provided. - pub global_form: Option, + pub global_form: Option>, } impl PartialCurve { @@ -42,7 +42,10 @@ impl PartialCurve { } /// Provide a global form for the partial curve - pub fn with_global_form(mut self, global_form: PartialGlobalCurve) -> Self { + pub fn with_global_form( + mut self, + global_form: Handle, + ) -> Self { self.global_form = Some(global_form); self } @@ -79,23 +82,19 @@ impl PartialCurve { let surface = self.surface.expect("Can't build `Curve` without surface"); - let global_form = self - .global_form - .unwrap_or_else(|| { - let path = match path { - SurfacePath::Circle(circle) => { - GlobalPath::circle_from_radius(circle.radius()) - } - SurfacePath::Line(line) => GlobalPath::line_from_points( - [line.origin(), line.origin() + line.direction()].map( - |point| surface.point_from_surface_coords(point), - ), - ), - }; - - GlobalCurve::partial().with_path(path) - }) - .build(stores); + let global_form = self.global_form.unwrap_or_else(|| { + let path = match path { + SurfacePath::Circle(circle) => { + GlobalPath::circle_from_radius(circle.radius()) + } + SurfacePath::Line(line) => GlobalPath::line_from_points( + [line.origin(), line.origin() + line.direction()] + .map(|point| surface.point_from_surface_coords(point)), + ), + }; + + GlobalCurve::partial().with_path(path).build(stores) + }); Curve::new(surface, path, global_form) } From 4382bf9dabdb5da7c67c1a67f8ea0cb3a5416be5 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 23 Sep 2022 12:01:01 +0200 Subject: [PATCH 3/6] Pass `&Stores` into partial object `build` methods This creates consistency among those `build` methods, and sooner or later they will be needed in all of them anyway. In addition, this change has the immediate benefit of allowing me to define a trait to abstract over partial objects. --- crates/fj-kernel/src/algorithms/sweep/vertex.rs | 2 +- crates/fj-kernel/src/builder/edge.rs | 4 ++-- crates/fj-kernel/src/partial/vertex.rs | 15 +++++++++------ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/crates/fj-kernel/src/algorithms/sweep/vertex.rs b/crates/fj-kernel/src/algorithms/sweep/vertex.rs index d0dcf535f..cb99bd323 100644 --- a/crates/fj-kernel/src/algorithms/sweep/vertex.rs +++ b/crates/fj-kernel/src/algorithms/sweep/vertex.rs @@ -168,7 +168,7 @@ mod tests { let vertex = Vertex::partial() .with_position([0.]) .with_curve(curve) - .build(); + .build(&stores); let half_edge = (vertex, surface).sweep([0., 0., 1.], &stores); diff --git a/crates/fj-kernel/src/builder/edge.rs b/crates/fj-kernel/src/builder/edge.rs index 983706969..fa66b983d 100644 --- a/crates/fj-kernel/src/builder/edge.rs +++ b/crates/fj-kernel/src/builder/edge.rs @@ -64,7 +64,7 @@ impl<'a> HalfEdgeBuilder<'a> { let global_vertex = GlobalVertex::partial() .from_curve_and_position(&curve, a_curve) - .build(); + .build(self.stores); let surface_vertices = [a_curve, b_curve].map(|point_curve| { let point_surface = @@ -103,7 +103,7 @@ impl<'a> HalfEdgeBuilder<'a> { let global_vertices = points.map(|position| { GlobalVertex::partial() .from_surface_and_position(&self.surface, position) - .build() + .build(self.stores) }); let surface_vertices = { diff --git a/crates/fj-kernel/src/partial/vertex.rs b/crates/fj-kernel/src/partial/vertex.rs index 53e77f410..fef22adfc 100644 --- a/crates/fj-kernel/src/partial/vertex.rs +++ b/crates/fj-kernel/src/partial/vertex.rs @@ -1,6 +1,9 @@ use fj_math::Point; -use crate::objects::{Curve, GlobalVertex, Surface, SurfaceVertex, Vertex}; +use crate::{ + objects::{Curve, GlobalVertex, Surface, SurfaceVertex, Vertex}, + stores::Stores, +}; /// A partial [`Vertex`] /// @@ -62,7 +65,7 @@ impl PartialVertex { /// Panics, if no position has been provided. /// /// Panics, if no curve has been provided. - pub fn build(self) -> Vertex { + pub fn build(self, stores: &Stores) -> Vertex { let position = self .position .expect("Cant' build `Vertex` without position"); @@ -74,7 +77,7 @@ impl PartialVertex { surface: Some(*curve.surface()), global_form: self.global_form, } - .build() + .build(stores) }); let global_form = *surface_form.global_form(); @@ -131,7 +134,7 @@ impl PartialSurfaceVertex { /// Panics, if no position has been provided. /// /// Panics, if no surface has been provided. - pub fn build(self) -> SurfaceVertex { + pub fn build(self, stores: &Stores) -> SurfaceVertex { let position = self .position .expect("Can't build `SurfaceVertex` without position"); @@ -142,7 +145,7 @@ impl PartialSurfaceVertex { let global_form = self.global_form.unwrap_or_else(|| { GlobalVertex::partial() .from_surface_and_position(&surface, position) - .build() + .build(stores) }); SurfaceVertex::new(position, surface, global_form) @@ -188,7 +191,7 @@ impl PartialGlobalVertex { } /// Build a full [`GlobalVertex`] from the partial global vertex - pub fn build(self) -> GlobalVertex { + pub fn build(self, _: &Stores) -> GlobalVertex { let position = self .position .expect("Can't build a `GlobalVertex` without a position"); From 119e06c68717ead7ae5c81cfcce69cf232e13d17 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 23 Sep 2022 12:50:11 +0200 Subject: [PATCH 4/6] Implement conversions from full to partial objects This provides some more opportunities to build abstractions on top of partial objects. --- crates/fj-kernel/src/partial/curve.rs | 18 ++++++++++++++++ crates/fj-kernel/src/partial/vertex.rs | 29 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/crates/fj-kernel/src/partial/curve.rs b/crates/fj-kernel/src/partial/curve.rs index 04d03fc78..58f411286 100644 --- a/crates/fj-kernel/src/partial/curve.rs +++ b/crates/fj-kernel/src/partial/curve.rs @@ -100,6 +100,16 @@ impl PartialCurve { } } +impl From for PartialCurve { + fn from(curve: Curve) -> Self { + Self { + path: Some(curve.path()), + surface: Some(*curve.surface()), + global_form: Some(curve.global_form().clone()), + } + } +} + /// A partial [`GlobalCurve`] /// /// See [`crate::partial`] for more information. @@ -153,3 +163,11 @@ impl PartialGlobalCurve { stores.global_curves.insert(GlobalCurve::from_path(path)) } } + +impl From> for PartialGlobalCurve { + fn from(global_curve: Handle) -> Self { + Self { + path: Some(global_curve.path()), + } + } +} diff --git a/crates/fj-kernel/src/partial/vertex.rs b/crates/fj-kernel/src/partial/vertex.rs index fef22adfc..49f1eab76 100644 --- a/crates/fj-kernel/src/partial/vertex.rs +++ b/crates/fj-kernel/src/partial/vertex.rs @@ -86,6 +86,17 @@ impl PartialVertex { } } +impl From for PartialVertex { + fn from(vertex: Vertex) -> Self { + Self { + position: Some(vertex.position()), + curve: Some(vertex.curve().clone()), + surface_form: Some(*vertex.surface_form()), + global_form: Some(*vertex.global_form()), + } + } +} + /// A partial [`SurfaceVertex`] /// /// See [`crate::partial`] for more information. @@ -152,6 +163,16 @@ impl PartialSurfaceVertex { } } +impl From for PartialSurfaceVertex { + fn from(surface_vertex: SurfaceVertex) -> Self { + Self { + position: Some(surface_vertex.position()), + surface: Some(*surface_vertex.surface()), + global_form: Some(*surface_vertex.global_form()), + } + } +} + /// A partial [`GlobalVertex`] /// /// See [`crate::partial`] for more information. @@ -199,3 +220,11 @@ impl PartialGlobalVertex { GlobalVertex::from_position(position) } } + +impl From for PartialGlobalVertex { + fn from(global_vertex: GlobalVertex) -> Self { + Self { + position: Some(global_vertex.position()), + } + } +} From 702f0ef7d3f50b72a8bc035748ec0794b621d299 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 23 Sep 2022 11:48:57 +0200 Subject: [PATCH 5/6] Add `HasPartialForm` trait --- crates/fj-kernel/src/partial/mod.rs | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/crates/fj-kernel/src/partial/mod.rs b/crates/fj-kernel/src/partial/mod.rs index 6ffa28d08..60bf4e70a 100644 --- a/crates/fj-kernel/src/partial/mod.rs +++ b/crates/fj-kernel/src/partial/mod.rs @@ -32,3 +32,50 @@ pub use self::{ curve::{PartialCurve, PartialGlobalCurve}, vertex::{PartialGlobalVertex, PartialSurfaceVertex, PartialVertex}, }; + +use crate::{ + objects::{Curve, GlobalCurve, GlobalVertex, SurfaceVertex, Vertex}, + stores::{Handle, Stores}, +}; + +/// Implemented for types that are partial objects +/// +/// # Implementation Note +/// +/// It would be nicer to require a conversion from `&Self` into the partial +/// form, but I think we need a `where` clause on the associated type to specify +/// that, which is unstable. It should become stable soon though, together with +/// generic associated types: +/// +pub trait HasPartialForm: Into { + /// The full version of this partial object + type PartialForm; + + /// Build a full object from the partial object + fn from_partial(partial: Self::PartialForm, stores: &Stores) -> Self; +} + +macro_rules! impl_traits { + ($($full:ty, $partial:ty;)*) => { + $( + impl HasPartialForm for $full { + type PartialForm = $partial; + + fn from_partial(partial: Self::PartialForm, stores: &Stores) + -> Self + { + partial.build(stores) + } + } + )* + }; +} + +impl_traits!( + Curve, PartialCurve; + GlobalVertex, PartialGlobalVertex; + SurfaceVertex, PartialSurfaceVertex; + Vertex, PartialVertex; + + Handle, PartialGlobalCurve; +); From 4a72095c162ed94d481447ecb1c857feb2275e5a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Fri, 23 Sep 2022 12:14:35 +0200 Subject: [PATCH 6/6] Add `MaybePartial` enum --- crates/fj-kernel/src/partial/mod.rs | 40 +++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/crates/fj-kernel/src/partial/mod.rs b/crates/fj-kernel/src/partial/mod.rs index 60bf4e70a..6877e5943 100644 --- a/crates/fj-kernel/src/partial/mod.rs +++ b/crates/fj-kernel/src/partial/mod.rs @@ -38,6 +38,34 @@ use crate::{ stores::{Handle, Stores}, }; +/// Either a partial object or a full one +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub enum MaybePartial { + /// A full object + Full(T), + + /// A partial object + Partial(T::PartialForm), +} + +impl MaybePartial { + /// Return the full object, either directly or by building it + pub fn into_full(self, stores: &Stores) -> T { + match self { + Self::Partial(partial) => T::from_partial(partial, stores), + Self::Full(full) => full, + } + } + + /// Return the partial object, either directly or via conversion + pub fn into_partial(self) -> T::PartialForm { + match self { + Self::Partial(partial) => partial, + Self::Full(full) => full.into(), + } + } +} + /// Implemented for types that are partial objects /// /// # Implementation Note @@ -67,6 +95,18 @@ macro_rules! impl_traits { partial.build(stores) } } + + impl From<$full> for MaybePartial<$full> { + fn from(full: $full) -> Self { + Self::Full(full) + } + } + + impl From<$partial> for MaybePartial<$full> { + fn from(partial: $partial) -> Self { + Self::Partial(partial) + } + } )* }; }