From d5c25971ba92e36e73b8dd05544133e03b729f38 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 26 Sep 2022 16:37:48 +0200 Subject: [PATCH 01/11] Move `MaybePartial` to dedicated module --- crates/fj-kernel/src/partial/maybe_partial.rs | 31 +++++++++++++++++++ crates/fj-kernel/src/partial/mod.rs | 30 ++---------------- 2 files changed, 33 insertions(+), 28 deletions(-) create mode 100644 crates/fj-kernel/src/partial/maybe_partial.rs diff --git a/crates/fj-kernel/src/partial/maybe_partial.rs b/crates/fj-kernel/src/partial/maybe_partial.rs new file mode 100644 index 000000000..38a2b26de --- /dev/null +++ b/crates/fj-kernel/src/partial/maybe_partial.rs @@ -0,0 +1,31 @@ +use crate::stores::Stores; + +use super::HasPartialForm; + +/// 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(), + } + } +} diff --git a/crates/fj-kernel/src/partial/mod.rs b/crates/fj-kernel/src/partial/mod.rs index 6b8fca4fb..4bce8b36b 100644 --- a/crates/fj-kernel/src/partial/mod.rs +++ b/crates/fj-kernel/src/partial/mod.rs @@ -27,11 +27,13 @@ mod curve; mod edge; +mod maybe_partial; mod vertex; pub use self::{ curve::{PartialCurve, PartialGlobalCurve}, edge::{PartialGlobalEdge, PartialHalfEdge}, + maybe_partial::MaybePartial, vertex::{PartialGlobalVertex, PartialSurfaceVertex, PartialVertex}, }; @@ -43,34 +45,6 @@ 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 From 5eaacdca60d05f0b770c76114774c00b99e95ef5 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 26 Sep 2022 16:40:53 +0200 Subject: [PATCH 02/11] Add `MaybePartial::surface_form` --- crates/fj-kernel/src/partial/maybe_partial.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/partial/maybe_partial.rs b/crates/fj-kernel/src/partial/maybe_partial.rs index 38a2b26de..5b5b7eb9c 100644 --- a/crates/fj-kernel/src/partial/maybe_partial.rs +++ b/crates/fj-kernel/src/partial/maybe_partial.rs @@ -1,4 +1,7 @@ -use crate::stores::Stores; +use crate::{ + objects::{SurfaceVertex, Vertex}, + stores::Stores, +}; use super::HasPartialForm; @@ -29,3 +32,13 @@ impl MaybePartial { } } } + +impl MaybePartial { + /// Access the surface form + pub fn surface_form(&self) -> Option<&SurfaceVertex> { + match self { + Self::Full(full) => Some(full.surface_form()), + Self::Partial(partial) => partial.surface_form.as_ref(), + } + } +} From 4ef80502cb02703c50fb91e65b72aaf64636722e Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 26 Sep 2022 16:53:59 +0200 Subject: [PATCH 03/11] Add `MaybePartial::curve` --- crates/fj-kernel/src/partial/maybe_partial.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/fj-kernel/src/partial/maybe_partial.rs b/crates/fj-kernel/src/partial/maybe_partial.rs index 5b5b7eb9c..b18c7a295 100644 --- a/crates/fj-kernel/src/partial/maybe_partial.rs +++ b/crates/fj-kernel/src/partial/maybe_partial.rs @@ -1,6 +1,6 @@ use crate::{ - objects::{SurfaceVertex, Vertex}, - stores::Stores, + objects::{GlobalCurve, GlobalEdge, SurfaceVertex, Vertex}, + stores::{Handle, Stores}, }; use super::HasPartialForm; @@ -33,6 +33,16 @@ impl MaybePartial { } } +impl MaybePartial { + /// Access the curve + pub fn curve(&self) -> Option<&Handle> { + match self { + Self::Full(full) => Some(full.curve()), + Self::Partial(partial) => partial.curve.as_ref(), + } + } +} + impl MaybePartial { /// Access the surface form pub fn surface_form(&self) -> Option<&SurfaceVertex> { From 83a955bdd204afb7b2ace399acc7eecdcf18ebfb Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 26 Sep 2022 17:07:25 +0200 Subject: [PATCH 04/11] Make `PartialVertex` more flexible --- crates/fj-kernel/src/partial/maybe_partial.rs | 6 ++-- crates/fj-kernel/src/partial/vertex.rs | 32 ++++++++++++------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/crates/fj-kernel/src/partial/maybe_partial.rs b/crates/fj-kernel/src/partial/maybe_partial.rs index b18c7a295..4c6a87806 100644 --- a/crates/fj-kernel/src/partial/maybe_partial.rs +++ b/crates/fj-kernel/src/partial/maybe_partial.rs @@ -45,10 +45,10 @@ impl MaybePartial { impl MaybePartial { /// Access the surface form - pub fn surface_form(&self) -> Option<&SurfaceVertex> { + pub fn surface_form(&self) -> Option> { match self { - Self::Full(full) => Some(full.surface_form()), - Self::Partial(partial) => partial.surface_form.as_ref(), + Self::Full(full) => Some((*full.surface_form()).into()), + Self::Partial(partial) => partial.surface_form.clone(), } } } diff --git a/crates/fj-kernel/src/partial/vertex.rs b/crates/fj-kernel/src/partial/vertex.rs index 9fdc5f967..a9d8ce648 100644 --- a/crates/fj-kernel/src/partial/vertex.rs +++ b/crates/fj-kernel/src/partial/vertex.rs @@ -26,7 +26,7 @@ pub struct PartialVertex { /// /// Can be provided, if already available, or computed from the position on /// the [`Curve`]. - pub surface_form: Option, + pub surface_form: Option>, /// The global form of the [`Vertex`] /// @@ -49,8 +49,11 @@ impl PartialVertex { } /// Provide a surface form for the partial vertex - pub fn with_surface_form(mut self, surface_form: SurfaceVertex) -> Self { - self.surface_form = Some(surface_form); + pub fn with_surface_form( + mut self, + surface_form: impl Into>, + ) -> Self { + self.surface_form = Some(surface_form.into()); self } @@ -79,14 +82,19 @@ impl PartialVertex { .expect("Can't build `Vertex` without `Curve`") .into_full(stores); - let surface_form = self.surface_form.unwrap_or_else(|| { - PartialSurfaceVertex { - position: Some(curve.path().point_from_path_coords(position)), - surface: Some(*curve.surface()), - global_form: self.global_form, - } - .build(stores) - }); + let surface_form = self + .surface_form + .unwrap_or_else(|| { + PartialSurfaceVertex { + position: Some( + curve.path().point_from_path_coords(position), + ), + surface: Some(*curve.surface()), + global_form: self.global_form, + } + .into() + }) + .into_full(stores); let global_form = *surface_form.global_form(); @@ -99,7 +107,7 @@ impl From for PartialVertex { Self { position: Some(vertex.position()), curve: Some(vertex.curve().clone().into()), - surface_form: Some(*vertex.surface_form()), + surface_form: Some((*vertex.surface_form()).into()), global_form: Some((*vertex.global_form()).into()), } } From 52b569767de3403259b46448d302db63240bd3d5 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 26 Sep 2022 15:27:50 +0200 Subject: [PATCH 05/11] Make `PartialHalfEdge` more flexible --- crates/fj-kernel/src/partial/edge.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/crates/fj-kernel/src/partial/edge.rs b/crates/fj-kernel/src/partial/edge.rs index aefe4865e..b06d8fb37 100644 --- a/crates/fj-kernel/src/partial/edge.rs +++ b/crates/fj-kernel/src/partial/edge.rs @@ -23,7 +23,7 @@ pub struct PartialHalfEdge { /// The global form of the [`HalfEdge`] /// /// Can be computed by [`PartialHalfEdge::build`], if not available. - pub global_form: Option, + pub global_form: Option>, } impl PartialHalfEdge { @@ -61,8 +61,11 @@ impl PartialHalfEdge { } /// 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); + pub fn with_global_form( + mut self, + global_form: impl Into>, + ) -> Self { + self.global_form = Some(global_form.into()); self } @@ -131,11 +134,14 @@ impl PartialHalfEdge { .into_full(stores) }); - let global_form = self.global_form.unwrap_or_else(|| { - GlobalEdge::partial() - .from_curve_and_vertices(&curve, &vertices) - .build(stores) - }); + let global_form = self + .global_form + .unwrap_or_else(|| { + GlobalEdge::partial() + .from_curve_and_vertices(&curve, &vertices) + .into() + }) + .into_full(stores); HalfEdge::new(curve, vertices, global_form) } @@ -146,7 +152,7 @@ impl From for PartialHalfEdge { 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()), + global_form: Some(half_edge.global_form().clone().into()), } } } From 86d7bfad929526b94a181a010d7c4ddf99fb713d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 26 Sep 2022 15:36:54 +0200 Subject: [PATCH 06/11] Make `PartialCurve` more flexible --- crates/fj-kernel/src/partial/curve.rs | 40 +++++++++++++++------------ 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/crates/fj-kernel/src/partial/curve.rs b/crates/fj-kernel/src/partial/curve.rs index 58f411286..40350fed3 100644 --- a/crates/fj-kernel/src/partial/curve.rs +++ b/crates/fj-kernel/src/partial/curve.rs @@ -6,6 +6,8 @@ use crate::{ stores::{Handle, Stores}, }; +use super::MaybePartial; + /// A partial [`Curve`] /// /// See [`crate::partial`] for more information. @@ -25,7 +27,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 { @@ -44,9 +46,9 @@ impl PartialCurve { /// Provide a global form for the partial curve pub fn with_global_form( mut self, - global_form: Handle, + global_form: impl Into>>, ) -> Self { - self.global_form = Some(global_form); + self.global_form = Some(global_form.into()); self } @@ -82,19 +84,23 @@ 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).into() + }) + .into_full(stores); Curve::new(surface, path, global_form) } @@ -105,7 +111,7 @@ impl From for PartialCurve { Self { path: Some(curve.path()), surface: Some(*curve.surface()), - global_form: Some(curve.global_form().clone()), + global_form: Some(curve.global_form().clone().into()), } } } From 12b5969b031ada2155f98ffbd06705d636a597d4 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 26 Sep 2022 17:09:53 +0200 Subject: [PATCH 07/11] Add `MaybePartial::surface` --- crates/fj-kernel/src/partial/maybe_partial.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/fj-kernel/src/partial/maybe_partial.rs b/crates/fj-kernel/src/partial/maybe_partial.rs index 4c6a87806..c71a793a1 100644 --- a/crates/fj-kernel/src/partial/maybe_partial.rs +++ b/crates/fj-kernel/src/partial/maybe_partial.rs @@ -1,5 +1,5 @@ use crate::{ - objects::{GlobalCurve, GlobalEdge, SurfaceVertex, Vertex}, + objects::{GlobalCurve, GlobalEdge, Surface, SurfaceVertex, Vertex}, stores::{Handle, Stores}, }; @@ -43,6 +43,16 @@ impl MaybePartial { } } +impl MaybePartial { + /// Access the surface + pub fn surface(&self) -> Option<&Surface> { + match self { + Self::Full(full) => Some(full.surface()), + Self::Partial(partial) => partial.surface.as_ref(), + } + } +} + impl MaybePartial { /// Access the surface form pub fn surface_form(&self) -> Option> { From d3d7af7bc491d3f8446cd850b393ed7b22054bf0 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 26 Sep 2022 17:12:57 +0200 Subject: [PATCH 08/11] Add `MaybePartial::position` --- crates/fj-kernel/src/partial/maybe_partial.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/fj-kernel/src/partial/maybe_partial.rs b/crates/fj-kernel/src/partial/maybe_partial.rs index c71a793a1..277ef9902 100644 --- a/crates/fj-kernel/src/partial/maybe_partial.rs +++ b/crates/fj-kernel/src/partial/maybe_partial.rs @@ -1,3 +1,5 @@ +use fj_math::Point; + use crate::{ objects::{GlobalCurve, GlobalEdge, Surface, SurfaceVertex, Vertex}, stores::{Handle, Stores}, @@ -44,6 +46,14 @@ impl MaybePartial { } impl MaybePartial { + /// Access the position + pub fn position(&self) -> Option> { + match self { + Self::Full(full) => Some(full.position()), + Self::Partial(partial) => partial.position, + } + } + /// Access the surface pub fn surface(&self) -> Option<&Surface> { match self { From 2692825413876c3a820dfcf2f53731f930a499be Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 26 Sep 2022 15:04:46 +0200 Subject: [PATCH 09/11] Use available global curve in `PartialHalfEdge` --- crates/fj-kernel/src/partial/edge.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/crates/fj-kernel/src/partial/edge.rs b/crates/fj-kernel/src/partial/edge.rs index b06d8fb37..9d3172a31 100644 --- a/crates/fj-kernel/src/partial/edge.rs +++ b/crates/fj-kernel/src/partial/edge.rs @@ -7,7 +7,7 @@ use crate::{ stores::{Handle, Stores}, }; -use super::MaybePartial; +use super::{MaybePartial, PartialCurve}; /// A partial [`HalfEdge`] /// @@ -106,9 +106,12 @@ impl PartialHalfEdge { surface: Surface, points: [impl Into>; 2], ) -> Self { - let curve = Curve::partial() - .with_surface(surface) - .as_line_from_points(points); + let curve = PartialCurve { + global_form: self.extract_global_curve(), + ..PartialCurve::default() + } + .with_surface(surface) + .as_line_from_points(points); let vertices = [0., 1.].map(|position| { Vertex::partial() @@ -145,6 +148,13 @@ impl PartialHalfEdge { HalfEdge::new(curve, vertices, global_form) } + + fn extract_global_curve( + &self, + ) -> Option>> { + let global_curve = self.global_form.as_ref()?.curve()?.clone(); + Some(global_curve.into()) + } } impl From for PartialHalfEdge { From a46eb3a4cbde16967a0541b4ee1768af8a129d02 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 26 Sep 2022 16:02:38 +0200 Subject: [PATCH 10/11] Simplify `PartialHalfEdge` I don't think there actually is a use case for setting the vertices separately. --- crates/fj-kernel/src/partial/edge.rs | 37 +++++++--------------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/crates/fj-kernel/src/partial/edge.rs b/crates/fj-kernel/src/partial/edge.rs index 9d3172a31..9df0dcd8f 100644 --- a/crates/fj-kernel/src/partial/edge.rs +++ b/crates/fj-kernel/src/partial/edge.rs @@ -18,7 +18,7 @@ pub struct PartialHalfEdge { pub curve: Option>, /// The vertices that bound this [`HalfEdge`] in the [`Curve`] - pub vertices: [Option>; 2], + pub vertices: Option<[MaybePartial; 2]>, /// The global form of the [`HalfEdge`] /// @@ -38,25 +38,7 @@ impl PartialHalfEdge { 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.vertices = Some(vertices.map(Into::into)); self } @@ -95,7 +77,7 @@ impl PartialHalfEdge { }; self.curve = Some(curve.into()); - self.vertices = vertices.map(Into::into).map(Some); + self.vertices = Some(vertices.map(Into::into)); self } @@ -120,7 +102,7 @@ impl PartialHalfEdge { }); self.curve = Some(curve.into()); - self.vertices = vertices.map(Into::into).map(Some); + self.vertices = Some(vertices.map(Into::into)); self } @@ -131,11 +113,10 @@ impl PartialHalfEdge { .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 vertices = self + .vertices + .expect("Can't build `HalfEdge` without vertices") + .map(|vertex| vertex.into_full(stores)); let global_form = self .global_form @@ -161,7 +142,7 @@ 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), + vertices: Some(half_edge.vertices().clone().map(Into::into)), global_form: Some(half_edge.global_form().clone().into()), } } From 66c91240ef25310b491b128fc6c4a98a397f4b51 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 26 Sep 2022 16:10:28 +0200 Subject: [PATCH 11/11] Add `PartialHalfEdge::as_line_segment` --- crates/fj-kernel/src/partial/edge.rs | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/crates/fj-kernel/src/partial/edge.rs b/crates/fj-kernel/src/partial/edge.rs index 9df0dcd8f..55639ef52 100644 --- a/crates/fj-kernel/src/partial/edge.rs +++ b/crates/fj-kernel/src/partial/edge.rs @@ -107,6 +107,41 @@ impl PartialHalfEdge { self } + /// Update partial half-edge as a line segment, reusing existing vertices + pub fn as_line_segment(mut self) -> Self { + let [from, to] = self + .vertices + .clone() + .expect("Can't infer line segment without vertices") + .map(|vertex| { + vertex.surface_form().expect( + "Can't infer line segment without two surface vertices", + ) + }); + + let surface = from + .surface() + .copied() + .or_else(|| to.surface().copied()) + .expect("Can't infer line segment without a surface"); + let points = [from, to].map(|vertex| { + vertex + .position() + .expect("Can't infer line segment without surface position") + }); + + let curve = PartialCurve { + global_form: self.extract_global_curve(), + ..PartialCurve::default() + } + .with_surface(surface) + .as_line_from_points(points); + + self.curve = Some(curve.into()); + + self + } + /// Build a full [`HalfEdge`] from the partial half-edge pub fn build(self, stores: &Stores) -> HalfEdge { let curve = self