From 1b26d56f51ebbce67595e2366441fa3ec998eb15 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 18 Mar 2024 12:33:32 +0100 Subject: [PATCH 01/10] Implement `Approx` for `Handle` --- crates/fj-core/src/algorithms/approx/cycle.rs | 5 +---- crates/fj-core/src/algorithms/approx/edge.rs | 6 ++++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/cycle.rs b/crates/fj-core/src/algorithms/approx/cycle.rs index 131bf134f..145ee63d9 100644 --- a/crates/fj-core/src/algorithms/approx/cycle.rs +++ b/crates/fj-core/src/algorithms/approx/cycle.rs @@ -2,8 +2,6 @@ //! //! See [`CycleApprox`]. -use std::ops::Deref; - use fj_math::Segment; use crate::{geometry::SurfaceGeometry, objects::Cycle, Core}; @@ -30,8 +28,7 @@ impl Approx for (&Cycle, &SurfaceGeometry) { .half_edges() .iter() .map(|half_edge| { - (half_edge.deref(), surface) - .approx_with_cache(tolerance, cache, core) + (half_edge, surface).approx_with_cache(tolerance, cache, core) }) .collect(); diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 86ecc5b6a..95a3fa52c 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -5,14 +5,16 @@ //! approximations are usually used to build cycle approximations, and this way, //! the caller doesn't have to deal with duplicate vertices. -use crate::{geometry::SurfaceGeometry, objects::HalfEdge, Core}; +use crate::{ + geometry::SurfaceGeometry, objects::HalfEdge, storage::Handle, Core, +}; use super::{ curve::CurveApproxCache, vertex::VertexApproxCache, Approx, ApproxPoint, Tolerance, }; -impl Approx for (&HalfEdge, &SurfaceGeometry) { +impl Approx for (&Handle, &SurfaceGeometry) { type Approximation = HalfEdgeApprox; type Cache = HalfEdgeApproxCache; From 01674a858c69a686e2db65b22129c554795b0b38 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 18 Mar 2024 12:35:23 +0100 Subject: [PATCH 02/10] Implement `BoundingVolume` for `Handle` --- crates/fj-core/src/algorithms/bounding_volume/edge.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/fj-core/src/algorithms/bounding_volume/edge.rs b/crates/fj-core/src/algorithms/bounding_volume/edge.rs index 3145c98ff..b902e33d5 100644 --- a/crates/fj-core/src/algorithms/bounding_volume/edge.rs +++ b/crates/fj-core/src/algorithms/bounding_volume/edge.rs @@ -3,9 +3,10 @@ use fj_math::{Aabb, Vector}; use crate::{ geometry::{Geometry, SurfacePath}, objects::HalfEdge, + storage::Handle, }; -impl super::BoundingVolume<2> for HalfEdge { +impl super::BoundingVolume<2> for Handle { fn aabb(&self, _: &Geometry) -> Option> { match self.path() { SurfacePath::Circle(circle) => { From 4ba7c3c18916f05325a108d0e6da2d5289f72a7d Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 18 Mar 2024 12:42:22 +0100 Subject: [PATCH 03/10] Expect `&Geometry` in `Face::coord_handedness` --- crates/fj-core/src/algorithms/approx/face.rs | 2 +- crates/fj-core/src/objects/kinds/face.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/face.rs b/crates/fj-core/src/algorithms/approx/face.rs index 1047efd53..3892fd046 100644 --- a/crates/fj-core/src/algorithms/approx/face.rs +++ b/crates/fj-core/src/algorithms/approx/face.rs @@ -110,7 +110,7 @@ impl Approx for &Face { exterior, interiors, color: self.region().get_color(core), - coord_handedness: self.coord_handedness(), + coord_handedness: self.coord_handedness(&core.layers.geometry), } } } diff --git a/crates/fj-core/src/objects/kinds/face.rs b/crates/fj-core/src/objects/kinds/face.rs index 5237ac07f..5f65e8c8b 100644 --- a/crates/fj-core/src/objects/kinds/face.rs +++ b/crates/fj-core/src/objects/kinds/face.rs @@ -1,6 +1,7 @@ use fj_math::Winding; use crate::{ + geometry::Geometry, objects::{Region, Surface}, storage::{Handle, HandleWrapper}, }; @@ -64,7 +65,7 @@ impl Face { /// Faces *do* have an orientation, meaning they have definite front and /// back sides. The front side is the side, where the face's exterior cycle /// is wound counter-clockwise. - pub fn coord_handedness(&self) -> Handedness { + pub fn coord_handedness(&self, _: &Geometry) -> Handedness { match self.region.exterior().winding() { Winding::Ccw => Handedness::RightHanded, Winding::Cw => Handedness::LeftHanded, From d179892ec22c5abc780fd85a8148708648dbd55f Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 18 Mar 2024 12:44:32 +0100 Subject: [PATCH 04/10] Expect `&Geometry` in `check_interior_winding` --- crates/fj-core/src/validate/face.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/fj-core/src/validate/face.rs b/crates/fj-core/src/validate/face.rs index d1fdb05f2..fc0bc81ad 100644 --- a/crates/fj-core/src/validate/face.rs +++ b/crates/fj-core/src/validate/face.rs @@ -13,10 +13,10 @@ impl Validate for Face { &self, _: &ValidationConfig, errors: &mut Vec, - _: &Geometry, + geometry: &Geometry, ) { FaceValidationError::check_boundary(self, errors); - FaceValidationError::check_interior_winding(self, errors); + FaceValidationError::check_interior_winding(self, geometry, errors); } } @@ -56,7 +56,11 @@ impl FaceValidationError { // checks for `Cycle` to make sure that the cycle is closed properly. } - fn check_interior_winding(face: &Face, errors: &mut Vec) { + fn check_interior_winding( + face: &Face, + _: &Geometry, + errors: &mut Vec, + ) { if face.region().exterior().half_edges().is_empty() { // Can't determine winding, if the cycle has no edges. Sounds like a // job for a different validation check. From 24f08b6be2fbec41b1470b10d265059eb28dba6e Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 18 Mar 2024 12:45:46 +0100 Subject: [PATCH 05/10] Expect `&Geometry` in `check_exterior_cycles` --- crates/fj-core/src/validate/sketch.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index 100ed5fa8..c4b2e8dfa 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -13,10 +13,12 @@ impl Validate for Sketch { &self, config: &ValidationConfig, errors: &mut Vec, - _: &Geometry, + geometry: &Geometry, ) { SketchValidationError::check_object_references(self, config, errors); - SketchValidationError::check_exterior_cycles(self, config, errors); + SketchValidationError::check_exterior_cycles( + self, geometry, config, errors, + ); SketchValidationError::check_interior_cycles(self, config, errors); } } @@ -74,6 +76,7 @@ impl SketchValidationError { fn check_exterior_cycles( sketch: &Sketch, + _: &Geometry, _config: &ValidationConfig, errors: &mut Vec, ) { From f33f5ca712a2ef413426da84ae9760bf33c293f4 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 18 Mar 2024 12:46:27 +0100 Subject: [PATCH 06/10] Expect `&Geometry` in `check_interior_cycles` --- crates/fj-core/src/validate/sketch.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index c4b2e8dfa..53eb034e0 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -19,7 +19,9 @@ impl Validate for Sketch { SketchValidationError::check_exterior_cycles( self, geometry, config, errors, ); - SketchValidationError::check_interior_cycles(self, config, errors); + SketchValidationError::check_interior_cycles( + self, geometry, config, errors, + ); } } @@ -94,6 +96,7 @@ impl SketchValidationError { fn check_interior_cycles( sketch: &Sketch, + _: &Geometry, _config: &ValidationConfig, errors: &mut Vec, ) { From cad8778bcbb1b2be5177bb3bbe44766d936fb72c Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 18 Mar 2024 12:47:23 +0100 Subject: [PATCH 07/10] Expect `&Geometry` in `Cycle::winding` --- crates/fj-core/src/objects/kinds/cycle.rs | 4 ++-- crates/fj-core/src/objects/kinds/face.rs | 4 ++-- crates/fj-core/src/operations/sweep/sketch.rs | 5 ++++- crates/fj-core/src/validate/face.rs | 6 +++--- crates/fj-core/src/validate/sketch.rs | 8 ++++---- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/crates/fj-core/src/objects/kinds/cycle.rs b/crates/fj-core/src/objects/kinds/cycle.rs index 61bb4179a..2e0ac0cf9 100644 --- a/crates/fj-core/src/objects/kinds/cycle.rs +++ b/crates/fj-core/src/objects/kinds/cycle.rs @@ -1,7 +1,7 @@ use fj_math::{Scalar, Winding}; use crate::{ - geometry::SurfacePath, + geometry::{Geometry, SurfacePath}, objects::{HalfEdge, ObjectSet}, storage::Handle, }; @@ -29,7 +29,7 @@ impl Cycle { /// Please note that this is not *the* winding of the cycle, only one of the /// two possible windings, depending on the direction you look at the /// surface that the cycle is defined on from. - pub fn winding(&self) -> Winding { + pub fn winding(&self, _: &Geometry) -> Winding { // The cycle could be made up of one or two circles. If that is the // case, the winding of the cycle is determined by the winding of the // first circle. diff --git a/crates/fj-core/src/objects/kinds/face.rs b/crates/fj-core/src/objects/kinds/face.rs index 5f65e8c8b..c0f22fc7a 100644 --- a/crates/fj-core/src/objects/kinds/face.rs +++ b/crates/fj-core/src/objects/kinds/face.rs @@ -65,8 +65,8 @@ impl Face { /// Faces *do* have an orientation, meaning they have definite front and /// back sides. The front side is the side, where the face's exterior cycle /// is wound counter-clockwise. - pub fn coord_handedness(&self, _: &Geometry) -> Handedness { - match self.region.exterior().winding() { + pub fn coord_handedness(&self, geometry: &Geometry) -> Handedness { + match self.region.exterior().winding(geometry) { Winding::Ccw => Handedness::RightHanded, Winding::Cw => Handedness::LeftHanded, } diff --git a/crates/fj-core/src/operations/sweep/sketch.rs b/crates/fj-core/src/operations/sweep/sketch.rs index 087ad51a6..d2f6d33a9 100644 --- a/crates/fj-core/src/operations/sweep/sketch.rs +++ b/crates/fj-core/src/operations/sweep/sketch.rs @@ -40,7 +40,10 @@ impl SweepSketch for Sketch { let region = { // The following code assumes that the sketch is winded counter- // clockwise. Let's check that real quick. - assert!(region.exterior().winding().is_ccw()); + assert!(region + .exterior() + .winding(&core.layers.geometry) + .is_ccw()); let is_negative_sweep = { let u = match core.layers.geometry.of_surface(&surface).u { diff --git a/crates/fj-core/src/validate/face.rs b/crates/fj-core/src/validate/face.rs index fc0bc81ad..3a7c04756 100644 --- a/crates/fj-core/src/validate/face.rs +++ b/crates/fj-core/src/validate/face.rs @@ -58,7 +58,7 @@ impl FaceValidationError { fn check_interior_winding( face: &Face, - _: &Geometry, + geometry: &Geometry, errors: &mut Vec, ) { if face.region().exterior().half_edges().is_empty() { @@ -67,7 +67,7 @@ impl FaceValidationError { return; } - let exterior_winding = face.region().exterior().winding(); + let exterior_winding = face.region().exterior().winding(geometry); for interior in face.region().interiors() { if interior.half_edges().is_empty() { @@ -75,7 +75,7 @@ impl FaceValidationError { // like a job for a different validation check. continue; } - let interior_winding = interior.winding(); + let interior_winding = interior.winding(geometry); if exterior_winding == interior_winding { errors.push( diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index 53eb034e0..6a23c46ab 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -78,13 +78,13 @@ impl SketchValidationError { fn check_exterior_cycles( sketch: &Sketch, - _: &Geometry, + geometry: &Geometry, _config: &ValidationConfig, errors: &mut Vec, ) { sketch.regions().iter().for_each(|region| { let cycle = region.exterior(); - if cycle.winding() == Winding::Cw { + if cycle.winding(geometry) == Winding::Cw { errors.push(ValidationError::Sketch( SketchValidationError::ClockwiseExteriorCycle { cycle: cycle.clone(), @@ -96,7 +96,7 @@ impl SketchValidationError { fn check_interior_cycles( sketch: &Sketch, - _: &Geometry, + geometry: &Geometry, _config: &ValidationConfig, errors: &mut Vec, ) { @@ -104,7 +104,7 @@ impl SketchValidationError { region .interiors() .iter() - .filter(|interior| interior.winding() == Winding::Ccw) + .filter(|interior| interior.winding(geometry) == Winding::Ccw) .for_each(|cycle| { errors.push(ValidationError::Sketch( SketchValidationError::CounterClockwiseInteriorCycle { From 44d34283df358b04f2bc55611c04fcab235b86b5 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 18 Mar 2024 12:51:51 +0100 Subject: [PATCH 08/10] Implement `SplitHalfEdge` for `Handle` --- crates/fj-core/src/operations/split/half_edge.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-core/src/operations/split/half_edge.rs b/crates/fj-core/src/operations/split/half_edge.rs index dc146bd64..2ec5a5c1b 100644 --- a/crates/fj-core/src/operations/split/half_edge.rs +++ b/crates/fj-core/src/operations/split/half_edge.rs @@ -33,7 +33,7 @@ pub trait SplitHalfEdge { ) -> [Handle; 2]; } -impl SplitHalfEdge for HalfEdge { +impl SplitHalfEdge for Handle { fn split_half_edge( &self, point: impl Into>, From 2438f529d1d1eca27311e29c7b98ab47741d5389 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 18 Mar 2024 12:53:21 +0100 Subject: [PATCH 09/10] Implement `SweepHalfEdge` for `Handle` --- crates/fj-core/src/operations/sweep/half_edge.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fj-core/src/operations/sweep/half_edge.rs b/crates/fj-core/src/operations/sweep/half_edge.rs index 883e42525..a1c07706a 100644 --- a/crates/fj-core/src/operations/sweep/half_edge.rs +++ b/crates/fj-core/src/operations/sweep/half_edge.rs @@ -47,7 +47,7 @@ pub trait SweepHalfEdge { ) -> (Face, Handle); } -impl SweepHalfEdge for HalfEdge { +impl SweepHalfEdge for Handle { fn sweep_half_edge( &self, end_vertex: Handle, From ecc7f26e3f01e160d97bb6b92e6330f72d36b2c0 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Mon, 18 Mar 2024 13:56:28 +0100 Subject: [PATCH 10/10] Read half-edge path from geometry layer --- crates/fj-core/src/algorithms/approx/edge.rs | 10 ++++--- .../src/algorithms/bounding_volume/edge.rs | 9 ++++--- crates/fj-core/src/objects/kinds/cycle.rs | 4 +-- .../fj-core/src/operations/build/half_edge.rs | 4 +-- .../src/operations/geometry/half_edge.rs | 4 +-- crates/fj-core/src/operations/holes.rs | 19 ++++++++++--- .../fj-core/src/operations/reverse/cycle.rs | 4 +-- crates/fj-core/src/operations/reverse/edge.rs | 2 +- .../fj-core/src/operations/split/half_edge.rs | 12 ++++++--- crates/fj-core/src/operations/sweep/cycle.rs | 2 +- .../fj-core/src/operations/sweep/half_edge.rs | 7 ++++- .../fj-core/src/operations/transform/edge.rs | 2 +- crates/fj-core/src/validate/shell.rs | 27 ++++++++++++++----- .../validation/checks/half_edge_connection.rs | 7 +++-- 14 files changed, 79 insertions(+), 34 deletions(-) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 95a3fa52c..27a59c9da 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -46,7 +46,7 @@ impl Approx for (&Handle, &SurfaceGeometry) { let rest = { let approx = ( half_edge.curve(), - half_edge.path(), + core.layers.geometry.of_half_edge(half_edge).path, surface, half_edge.boundary(), ) @@ -57,8 +57,12 @@ impl Approx for (&Handle, &SurfaceGeometry) { ); approx.points.into_iter().map(|point| { - let point_surface = - half_edge.path().point_from_path_coords(point.local_form); + let point_surface = core + .layers + .geometry + .of_half_edge(half_edge) + .path + .point_from_path_coords(point.local_form); ApproxPoint::new(point_surface, point.global_form) }) diff --git a/crates/fj-core/src/algorithms/bounding_volume/edge.rs b/crates/fj-core/src/algorithms/bounding_volume/edge.rs index b902e33d5..ec7ed05f2 100644 --- a/crates/fj-core/src/algorithms/bounding_volume/edge.rs +++ b/crates/fj-core/src/algorithms/bounding_volume/edge.rs @@ -7,8 +7,8 @@ use crate::{ }; impl super::BoundingVolume<2> for Handle { - fn aabb(&self, _: &Geometry) -> Option> { - match self.path() { + fn aabb(&self, geometry: &Geometry) -> Option> { + match geometry.of_half_edge(self).path { SurfacePath::Circle(circle) => { // Just calculate the AABB of the whole circle. This is not the // most precise, but it should do for now. @@ -23,7 +23,10 @@ impl super::BoundingVolume<2> for Handle { } SurfacePath::Line(_) => { let points = self.boundary().inner.map(|point_curve| { - self.path().point_from_path_coords(point_curve) + geometry + .of_half_edge(self) + .path + .point_from_path_coords(point_curve) }); Some(Aabb::<2>::from_points(points)) diff --git a/crates/fj-core/src/objects/kinds/cycle.rs b/crates/fj-core/src/objects/kinds/cycle.rs index 2e0ac0cf9..69546f9a6 100644 --- a/crates/fj-core/src/objects/kinds/cycle.rs +++ b/crates/fj-core/src/objects/kinds/cycle.rs @@ -29,7 +29,7 @@ impl Cycle { /// Please note that this is not *the* winding of the cycle, only one of the /// two possible windings, depending on the direction you look at the /// surface that the cycle is defined on from. - pub fn winding(&self, _: &Geometry) -> Winding { + pub fn winding(&self, geometry: &Geometry) -> Winding { // The cycle could be made up of one or two circles. If that is the // case, the winding of the cycle is determined by the winding of the // first circle. @@ -43,7 +43,7 @@ impl Cycle { let [a, b] = first.boundary().inner; let edge_direction_positive = a < b; - let circle = match first.path() { + let circle = match geometry.of_half_edge(first).path { SurfacePath::Circle(circle) => circle, SurfacePath::Line(_) => unreachable!( "Invalid cycle: less than 3 edges, but not all are circles" diff --git a/crates/fj-core/src/operations/build/half_edge.rs b/crates/fj-core/src/operations/build/half_edge.rs index 45f497242..b674210ab 100644 --- a/crates/fj-core/src/operations/build/half_edge.rs +++ b/crates/fj-core/src/operations/build/half_edge.rs @@ -34,7 +34,7 @@ pub trait BuildHalfEdge { core: &mut Core, ) -> Handle { let half_edge = HalfEdge::new( - sibling.path(), + core.layers.geometry.of_half_edge(sibling).path, sibling.boundary().reverse(), sibling.curve().clone(), start_vertex, @@ -44,7 +44,7 @@ pub trait BuildHalfEdge { core.layers.geometry.define_half_edge( half_edge.clone(), HalfEdgeGeometry { - path: sibling.path(), + path: core.layers.geometry.of_half_edge(sibling).path, }, ); diff --git a/crates/fj-core/src/operations/geometry/half_edge.rs b/crates/fj-core/src/operations/geometry/half_edge.rs index 1ac2dd40b..ead3ddb82 100644 --- a/crates/fj-core/src/operations/geometry/half_edge.rs +++ b/crates/fj-core/src/operations/geometry/half_edge.rs @@ -50,7 +50,7 @@ impl UpdateHalfEdgeGeometry for Handle { update: impl FnOnce(SurfacePath) -> SurfacePath, core: &mut Core, ) -> Self { - let path = update(self.path()); + let path = update(core.layers.geometry.of_half_edge(self).path); let half_edge = HalfEdge::new( path, @@ -73,7 +73,7 @@ impl UpdateHalfEdgeGeometry for Handle { core: &mut Core, ) -> Self { HalfEdge::new( - self.path(), + core.layers.geometry.of_half_edge(self).path, update(self.boundary()), self.curve().clone(), self.start_vertex().clone(), diff --git a/crates/fj-core/src/operations/holes.rs b/crates/fj-core/src/operations/holes.rs index 6d878f2c7..3017c09ef 100644 --- a/crates/fj-core/src/operations/holes.rs +++ b/crates/fj-core/src/operations/holes.rs @@ -68,7 +68,10 @@ impl AddHole for Shell { [Cycle::empty().add_joined_edges( [( entry.clone(), - entry.path(), + core.layers + .geometry + .of_half_edge(&entry) + .path, entry.boundary(), )], core, @@ -139,7 +142,10 @@ impl AddHole for Shell { [Cycle::empty().add_joined_edges( [( entry.clone(), - entry.path(), + core.layers + .geometry + .of_half_edge(&entry) + .path, entry.boundary(), )], core, @@ -159,7 +165,14 @@ impl AddHole for Shell { |region, core| { region.add_interiors( [Cycle::empty().add_joined_edges( - [(exit.clone(), exit.path(), exit.boundary())], + [( + exit.clone(), + core.layers + .geometry + .of_half_edge(exit) + .path, + exit.boundary(), + )], core, )], core, diff --git a/crates/fj-core/src/operations/reverse/cycle.rs b/crates/fj-core/src/operations/reverse/cycle.rs index d4a990cbc..d579654de 100644 --- a/crates/fj-core/src/operations/reverse/cycle.rs +++ b/crates/fj-core/src/operations/reverse/cycle.rs @@ -14,7 +14,7 @@ impl Reverse for Cycle { .pairs() .map(|(current, next)| { let half_edge = HalfEdge::new( - current.path(), + core.layers.geometry.of_half_edge(current).path, current.boundary().reverse(), current.curve().clone(), next.start_vertex().clone(), @@ -25,7 +25,7 @@ impl Reverse for Cycle { core.layers.geometry.define_half_edge( half_edge.clone(), HalfEdgeGeometry { - path: current.path(), + path: core.layers.geometry.of_half_edge(current).path, }, ); diff --git a/crates/fj-core/src/operations/reverse/edge.rs b/crates/fj-core/src/operations/reverse/edge.rs index 4b992bec9..bba0b773a 100644 --- a/crates/fj-core/src/operations/reverse/edge.rs +++ b/crates/fj-core/src/operations/reverse/edge.rs @@ -10,7 +10,7 @@ use super::ReverseCurveCoordinateSystems; impl ReverseCurveCoordinateSystems for Handle { fn reverse_curve_coordinate_systems(&self, core: &mut Core) -> Self { - let path = self.path().reverse(); + let path = core.layers.geometry.of_half_edge(self).path.reverse(); let boundary = self.boundary().reverse(); let half_edge = HalfEdge::new( diff --git a/crates/fj-core/src/operations/split/half_edge.rs b/crates/fj-core/src/operations/split/half_edge.rs index 2ec5a5c1b..efc170571 100644 --- a/crates/fj-core/src/operations/split/half_edge.rs +++ b/crates/fj-core/src/operations/split/half_edge.rs @@ -44,14 +44,14 @@ impl SplitHalfEdge for Handle { let [start, end] = self.boundary().inner; let a = HalfEdge::new( - self.path(), + core.layers.geometry.of_half_edge(self).path, [start, point], self.curve().clone(), self.start_vertex().clone(), ) .insert(core); let b = HalfEdge::new( - self.path(), + core.layers.geometry.of_half_edge(self).path, [point, end], self.curve().clone(), Vertex::new().insert(core), @@ -60,11 +60,15 @@ impl SplitHalfEdge for Handle { core.layers.geometry.define_half_edge( a.clone(), - HalfEdgeGeometry { path: self.path() }, + HalfEdgeGeometry { + path: core.layers.geometry.of_half_edge(self).path, + }, ); core.layers.geometry.define_half_edge( b.clone(), - HalfEdgeGeometry { path: self.path() }, + HalfEdgeGeometry { + path: core.layers.geometry.of_half_edge(self).path, + }, ); [a, b] diff --git a/crates/fj-core/src/operations/sweep/cycle.rs b/crates/fj-core/src/operations/sweep/cycle.rs index b64ec1860..23f04051c 100644 --- a/crates/fj-core/src/operations/sweep/cycle.rs +++ b/crates/fj-core/src/operations/sweep/cycle.rs @@ -77,7 +77,7 @@ impl SweepCycle for Cycle { top_edges.push(( top_edge, - bottom_half_edge.path(), + core.layers.geometry.of_half_edge(bottom_half_edge).path, bottom_half_edge.boundary(), )); } diff --git a/crates/fj-core/src/operations/sweep/half_edge.rs b/crates/fj-core/src/operations/sweep/half_edge.rs index a1c07706a..d2db2834b 100644 --- a/crates/fj-core/src/operations/sweep/half_edge.rs +++ b/crates/fj-core/src/operations/sweep/half_edge.rs @@ -59,7 +59,12 @@ impl SweepHalfEdge for Handle { ) -> (Face, Handle) { let path = path.into(); - let surface = self.path().sweep_surface_path(surface, path, core); + let surface = core + .layers + .geometry + .of_half_edge(self) + .path + .sweep_surface_path(surface, path, core); // Next, we need to define the boundaries of the face. Let's start with // the global vertices and edges. diff --git a/crates/fj-core/src/operations/transform/edge.rs b/crates/fj-core/src/operations/transform/edge.rs index 50820b2e3..933ac520e 100644 --- a/crates/fj-core/src/operations/transform/edge.rs +++ b/crates/fj-core/src/operations/transform/edge.rs @@ -16,7 +16,7 @@ impl TransformObject for Handle { ) -> Self { // Don't need to transform the path, as that's defined in surface // coordinates. - let path = self.path(); + let path = core.layers.geometry.of_half_edge(self).path; let boundary = self.boundary(); let curve = self .curve() diff --git a/crates/fj-core/src/validate/shell.rs b/crates/fj-core/src/validate/shell.rs index 51e8d6dba..a8826ae42 100644 --- a/crates/fj-core/src/validate/shell.rs +++ b/crates/fj-core/src/validate/shell.rs @@ -104,6 +104,7 @@ impl ShellValidationError { surface_a: &SurfaceGeometry, edge_b: &Handle, surface_b: &SurfaceGeometry, + geometry: &Geometry, config: &ValidationConfig, mismatches: &mut Vec, ) { @@ -116,10 +117,14 @@ impl ShellValidationError { let c = a + (d - a) * 2. / 3.; for point_curve in [a, b, c, d] { - let a_surface = - edge_a.path().point_from_path_coords(point_curve); - let b_surface = - edge_b.path().point_from_path_coords(point_curve); + let a_surface = geometry + .of_half_edge(edge_a) + .path + .point_from_path_coords(point_curve); + let b_surface = geometry + .of_half_edge(edge_b) + .path + .point_from_path_coords(point_curve); let a_global = surface_a.point_from_surface_coords(a_surface); @@ -148,6 +153,7 @@ impl ShellValidationError { &geometry.of_surface(surface_a), edge_b, &geometry.of_surface(surface_b), + geometry, config, &mut mismatches, ); @@ -156,6 +162,7 @@ impl ShellValidationError { &geometry.of_surface(surface_b), edge_a, &geometry.of_surface(surface_a), + geometry, config, &mut mismatches, ); @@ -245,6 +252,7 @@ impl ShellValidationError { &geometry.of_surface(surface_a), half_edge_b.clone(), &geometry.of_surface(surface_b), + geometry, ) .all(|d| d < config.distinct_min_distance) { @@ -369,14 +377,19 @@ fn distances( surface_a: &SurfaceGeometry, edge_b: Handle, surface_b: &SurfaceGeometry, + geometry: &Geometry, ) -> impl Iterator { fn sample( percent: f64, (edge, surface): (&Handle, &SurfaceGeometry), + geometry: &Geometry, ) -> Point<3> { let [start, end] = edge.boundary().inner; let path_coords = start + (end - start) * percent; - let surface_coords = edge.path().point_from_path_coords(path_coords); + let surface_coords = geometry + .of_half_edge(edge) + .path + .point_from_path_coords(path_coords); surface.point_from_surface_coords(surface_coords) } @@ -389,8 +402,8 @@ fn distances( let mut distances = Vec::new(); for i in 0..sample_count { let percent = i as f64 * step; - let sample1 = sample(percent, (&edge_a, surface_a)); - let sample2 = sample(1.0 - percent, (&edge_b, surface_b)); + let sample1 = sample(percent, (&edge_a, surface_a), geometry); + let sample2 = sample(1.0 - percent, (&edge_b, surface_b), geometry); distances.push(sample1.distance_to(&sample2)) } distances.into_iter() diff --git a/crates/fj-core/src/validation/checks/half_edge_connection.rs b/crates/fj-core/src/validation/checks/half_edge_connection.rs index 2d65a92b9..8e2b8083b 100644 --- a/crates/fj-core/src/validation/checks/half_edge_connection.rs +++ b/crates/fj-core/src/validation/checks/half_edge_connection.rs @@ -41,13 +41,16 @@ pub struct AdjacentHalfEdgesNotConnected { impl ValidationCheck for AdjacentHalfEdgesNotConnected { fn check( object: &Cycle, - _: &Geometry, + geometry: &Geometry, config: &ValidationConfig, ) -> impl Iterator { object.half_edges().pairs().filter_map(|(first, second)| { let end_pos_of_first_half_edge = { let [_, end] = first.boundary().inner; - first.path().point_from_path_coords(end) + geometry + .of_half_edge(first) + .path + .point_from_path_coords(end) }; let start_pos_of_second_half_edge = second.start_position();