From c7906ad8883664461d2d9d47b5525912365aed42 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 14 Mar 2024 14:39:58 +0100 Subject: [PATCH] Store `HalfEdge` path in geometry layer --- crates/fj-core/src/geometry/half_edge.rs | 31 +++++++++++++++- .../fj-core/src/operations/build/half_edge.rs | 36 +++++++++++++++---- .../src/operations/geometry/half_edge.rs | 12 +++++-- crates/fj-core/src/operations/join/cycle.rs | 13 +++++-- .../fj-core/src/operations/reverse/cycle.rs | 14 ++++++-- crates/fj-core/src/operations/reverse/edge.rs | 11 ++++-- .../fj-core/src/operations/split/half_edge.rs | 10 ++++++ .../fj-core/src/operations/transform/edge.rs | 12 +++++-- 8 files changed, 121 insertions(+), 18 deletions(-) diff --git a/crates/fj-core/src/geometry/half_edge.rs b/crates/fj-core/src/geometry/half_edge.rs index fc4c3a2e2..1e913fa44 100644 --- a/crates/fj-core/src/geometry/half_edge.rs +++ b/crates/fj-core/src/geometry/half_edge.rs @@ -1,3 +1,32 @@ +use super::SurfacePath; + /// The geometry of a half-edge #[derive(Copy, Clone)] -pub struct HalfEdgeGeometry {} +pub struct HalfEdgeGeometry { + /// # The path of the half-edge + /// + /// ## Implementation Note + /// + /// Currently, all curve-related geometry is defined locally, in terms of + /// the surface that the curve is on (or purely in 2D, if there is no + /// surface associated with this geometry). However, curves exist globally, + /// independently of surfaces. Half-edges in multiple surfaces can refer to + /// the same curve, and in fact, that is the whole reason for their + /// existence as a topological object. + /// + /// This contradiction, globally defined curves but locally defined curve + /// geometry, is the reason that this curve geometry is defined right here, + /// associated with a locally existing half-edge. (And, I might add, + /// redundantly so, as multiple half-edges within the same surface context + /// can refer to the same curve.) + /// + /// Instead, it should be possible to define curve geometry *either* locally + /// or globally. Then that respective definition can be associated with the + /// curve (and possibly, in addition, a surface). How exactly that is going + /// to work is up in the air. + /// + /// The point of all this exposition is to clarify that this field doesn't + /// really belong here. It exists here for practical reasons that are, + /// hopefully, temporary. + pub path: SurfacePath, +} diff --git a/crates/fj-core/src/operations/build/half_edge.rs b/crates/fj-core/src/operations/build/half_edge.rs index 0835c9d5d..45f497242 100644 --- a/crates/fj-core/src/operations/build/half_edge.rs +++ b/crates/fj-core/src/operations/build/half_edge.rs @@ -2,7 +2,7 @@ use fj_interop::ext::ArrayExt; use fj_math::{Arc, Point, Scalar}; use crate::{ - geometry::{CurveBoundary, SurfacePath}, + geometry::{CurveBoundary, HalfEdgeGeometry, SurfacePath}, objects::{Curve, HalfEdge, Vertex}, operations::insert::Insert, storage::Handle, @@ -33,13 +33,22 @@ pub trait BuildHalfEdge { start_vertex: Handle, core: &mut Core, ) -> Handle { - HalfEdge::new( + let half_edge = HalfEdge::new( sibling.path(), sibling.boundary().reverse(), sibling.curve().clone(), start_vertex, ) - .insert(core) + .insert(core); + + core.layers.geometry.define_half_edge( + half_edge.clone(), + HalfEdgeGeometry { + path: sibling.path(), + }, + ); + + half_edge } /// Create an arc @@ -65,7 +74,12 @@ pub trait BuildHalfEdge { let boundary = [arc.start_angle, arc.end_angle].map(|coord| Point::from([coord])); - HalfEdge::unjoined(path, boundary, core).insert(core) + let half_edge = HalfEdge::unjoined(path, boundary, core).insert(core); + core.layers + .geometry + .define_half_edge(half_edge.clone(), HalfEdgeGeometry { path }); + + half_edge } /// Create a circle @@ -78,7 +92,12 @@ pub trait BuildHalfEdge { let boundary = [Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord])); - HalfEdge::unjoined(path, boundary, core).insert(core) + let half_edge = HalfEdge::unjoined(path, boundary, core).insert(core); + core.layers + .geometry + .define_half_edge(half_edge.clone(), HalfEdgeGeometry { path }); + + half_edge } /// Create a line segment @@ -93,7 +112,12 @@ pub trait BuildHalfEdge { boundary.zip_ext(points_surface), ); - HalfEdge::unjoined(path, boundary, core).insert(core) + let half_edge = HalfEdge::unjoined(path, boundary, core).insert(core); + core.layers + .geometry + .define_half_edge(half_edge.clone(), HalfEdgeGeometry { path }); + + half_edge } } diff --git a/crates/fj-core/src/operations/geometry/half_edge.rs b/crates/fj-core/src/operations/geometry/half_edge.rs index 54de2f73f..8f05de05a 100644 --- a/crates/fj-core/src/operations/geometry/half_edge.rs +++ b/crates/fj-core/src/operations/geometry/half_edge.rs @@ -1,7 +1,7 @@ use fj_math::Point; use crate::{ - geometry::{CurveBoundary, SurfacePath}, + geometry::{CurveBoundary, HalfEdgeGeometry, SurfacePath}, objects::HalfEdge, operations::insert::Insert, storage::Handle, @@ -35,13 +35,19 @@ impl UpdateHalfEdgeGeometry for Handle { ) -> Self { let path = update(self.path()); - HalfEdge::new( + let half_edge = HalfEdge::new( path, self.boundary(), self.curve().clone(), self.start_vertex().clone(), ) - .insert(core) + .insert(core); + + core.layers + .geometry + .define_half_edge(half_edge.clone(), HalfEdgeGeometry { path }); + + half_edge } fn update_boundary( diff --git a/crates/fj-core/src/operations/join/cycle.rs b/crates/fj-core/src/operations/join/cycle.rs index b90fcdb92..91af735fa 100644 --- a/crates/fj-core/src/operations/join/cycle.rs +++ b/crates/fj-core/src/operations/join/cycle.rs @@ -4,10 +4,11 @@ use fj_math::Point; use itertools::Itertools; use crate::{ - geometry::{CurveBoundary, SurfacePath}, + geometry::{CurveBoundary, HalfEdgeGeometry, SurfacePath}, objects::{Cycle, HalfEdge}, operations::{ build::BuildHalfEdge, + insert::Insert, update::{UpdateCycle, UpdateHalfEdge}, }, storage::Handle, @@ -88,12 +89,20 @@ impl JoinCycle for Cycle { .into_iter() .circular_tuple_windows() .map(|((prev_half_edge, _, _), (half_edge, path, boundary))| { - HalfEdge::unjoined(path, boundary, core) + let half_edge = HalfEdge::unjoined(path, boundary, core) .update_curve(|_, _| half_edge.curve().clone(), core) .update_start_vertex( |_, _| prev_half_edge.start_vertex().clone(), core, ) + .insert(core); + + core.layers.geometry.define_half_edge( + half_edge.clone(), + HalfEdgeGeometry { path }, + ); + + half_edge }) .collect::>(); self.add_half_edges(half_edges, core) diff --git a/crates/fj-core/src/operations/reverse/cycle.rs b/crates/fj-core/src/operations/reverse/cycle.rs index f3d12acff..d4a990cbc 100644 --- a/crates/fj-core/src/operations/reverse/cycle.rs +++ b/crates/fj-core/src/operations/reverse/cycle.rs @@ -1,4 +1,5 @@ use crate::{ + geometry::HalfEdgeGeometry, objects::{Cycle, HalfEdge}, operations::{derive::DeriveFrom, insert::Insert}, Core, @@ -12,14 +13,23 @@ impl Reverse for Cycle { .half_edges() .pairs() .map(|(current, next)| { - HalfEdge::new( + let half_edge = HalfEdge::new( current.path(), current.boundary().reverse(), current.curve().clone(), next.start_vertex().clone(), ) .insert(core) - .derive_from(current, core) + .derive_from(current, core); + + core.layers.geometry.define_half_edge( + half_edge.clone(), + HalfEdgeGeometry { + path: current.path(), + }, + ); + + half_edge }) .collect::>(); diff --git a/crates/fj-core/src/operations/reverse/edge.rs b/crates/fj-core/src/operations/reverse/edge.rs index 91e6affa2..4b992bec9 100644 --- a/crates/fj-core/src/operations/reverse/edge.rs +++ b/crates/fj-core/src/operations/reverse/edge.rs @@ -1,4 +1,5 @@ use crate::{ + geometry::HalfEdgeGeometry, objects::HalfEdge, operations::{derive::DeriveFrom, insert::Insert}, storage::Handle, @@ -12,13 +13,19 @@ impl ReverseCurveCoordinateSystems for Handle { let path = self.path().reverse(); let boundary = self.boundary().reverse(); - HalfEdge::new( + let half_edge = HalfEdge::new( path, boundary, self.curve().clone(), self.start_vertex().clone(), ) .insert(core) - .derive_from(self, core) + .derive_from(self, core); + + core.layers + .geometry + .define_half_edge(half_edge.clone(), HalfEdgeGeometry { path }); + + half_edge } } diff --git a/crates/fj-core/src/operations/split/half_edge.rs b/crates/fj-core/src/operations/split/half_edge.rs index d842fae1e..dc146bd64 100644 --- a/crates/fj-core/src/operations/split/half_edge.rs +++ b/crates/fj-core/src/operations/split/half_edge.rs @@ -1,6 +1,7 @@ use fj_math::Point; use crate::{ + geometry::HalfEdgeGeometry, objects::{HalfEdge, Vertex}, operations::insert::Insert, storage::Handle, @@ -57,6 +58,15 @@ impl SplitHalfEdge for HalfEdge { ) .insert(core); + core.layers.geometry.define_half_edge( + a.clone(), + HalfEdgeGeometry { path: self.path() }, + ); + core.layers.geometry.define_half_edge( + b.clone(), + HalfEdgeGeometry { path: self.path() }, + ); + [a, b] } } diff --git a/crates/fj-core/src/operations/transform/edge.rs b/crates/fj-core/src/operations/transform/edge.rs index 9c11a244d..50820b2e3 100644 --- a/crates/fj-core/src/operations/transform/edge.rs +++ b/crates/fj-core/src/operations/transform/edge.rs @@ -1,7 +1,8 @@ use fj_math::Transform; use crate::{ - objects::HalfEdge, operations::insert::Insert, storage::Handle, Core, + geometry::HalfEdgeGeometry, objects::HalfEdge, operations::insert::Insert, + storage::Handle, Core, }; use super::{TransformCache, TransformObject}; @@ -26,6 +27,13 @@ impl TransformObject for Handle { .clone() .transform_with_cache(transform, core, cache); - HalfEdge::new(path, boundary, curve, start_vertex).insert(core) + let half_edge = + HalfEdge::new(path, boundary, curve, start_vertex).insert(core); + + core.layers + .geometry + .define_half_edge(half_edge.clone(), HalfEdgeGeometry { path }); + + half_edge } }