diff --git a/crates/fj-core/src/algorithms/approx/curve.rs b/crates/fj-core/src/algorithms/approx/curve.rs index f76043d484..6a5dc4bfa7 100644 --- a/crates/fj-core/src/algorithms/approx/curve.rs +++ b/crates/fj-core/src/algorithms/approx/curve.rs @@ -5,7 +5,10 @@ use std::collections::BTreeMap; use fj_math::Point; use crate::{ - geometry::{CurveBoundary, GlobalPath, SurfaceGeometry, SurfacePath}, + geometry::{ + CurveBoundary, GlobalPath, HalfEdgeGeometry, SurfaceGeometry, + SurfacePath, + }, objects::Curve, storage::Handle, Core, @@ -13,14 +16,7 @@ use crate::{ use super::{Approx, ApproxPoint, Tolerance}; -impl Approx - for ( - &Handle, - SurfacePath, - &SurfaceGeometry, - CurveBoundary>, - ) -{ +impl Approx for (&Handle, &HalfEdgeGeometry, &SurfaceGeometry) { type Approximation = CurveApprox; type Cache = CurveApproxCache; @@ -30,20 +26,20 @@ impl Approx cache: &mut Self::Cache, core: &mut Core, ) -> Self::Approximation { - let (curve, surface_path, surface, boundary) = self; + let (curve, half_edge, surface) = self; - match cache.get(curve, boundary) { + match cache.get(curve, half_edge.boundary) { Some(approx) => approx, None => { let approx = approx_curve( - &surface_path, + &half_edge.path, surface, - boundary, + half_edge.boundary, tolerance, core, ); - cache.insert(curve.clone(), boundary, approx) + cache.insert(curve.clone(), half_edge.boundary, approx) } } } @@ -187,7 +183,10 @@ mod tests { use crate::{ algorithms::approx::{Approx, ApproxPoint}, - geometry::{CurveBoundary, GlobalPath, SurfaceGeometry, SurfacePath}, + geometry::{ + CurveBoundary, GlobalPath, HalfEdgeGeometry, SurfaceGeometry, + SurfacePath, + }, objects::Curve, operations::insert::Insert, Core, @@ -198,14 +197,15 @@ mod tests { let mut core = Core::new(); let curve = Curve::new().insert(&mut core); - let (surface_path, boundary) = + let (path, boundary) = SurfacePath::line_from_points([[1., 1.], [2., 1.]]); let boundary = CurveBoundary::from(boundary); + let half_edge = HalfEdgeGeometry { path, boundary }; let surface = core.layers.geometry.xz_plane(); let tolerance = 1.; - let approx = (&curve, surface_path, &surface, boundary) - .approx(tolerance, &mut core); + let approx = + (&curve, &half_edge, &surface).approx(tolerance, &mut core); assert_eq!(approx.points, vec![]); } @@ -215,17 +215,18 @@ mod tests { let mut core = Core::new(); let curve = Curve::new().insert(&mut core); - let (surface_path, boundary) = + let (path, boundary) = SurfacePath::line_from_points([[1., 1.], [2., 1.]]); let boundary = CurveBoundary::from(boundary); + let half_edge = HalfEdgeGeometry { path, boundary }; let surface = SurfaceGeometry { u: GlobalPath::circle_from_radius(1.), v: [0., 0., 1.].into(), }; let tolerance = 1.; - let approx = (&curve, surface_path, &surface, boundary) - .approx(tolerance, &mut core); + let approx = + (&curve, &half_edge, &surface).approx(tolerance, &mut core); assert_eq!(approx.points, vec![]); } @@ -236,26 +237,26 @@ mod tests { let global_path = GlobalPath::circle_from_radius(1.); let curve = Curve::new().insert(&mut core); - let surface_path = SurfacePath::line_from_points_with_coords([ + let path = SurfacePath::line_from_points_with_coords([ ([0.], [0., 1.]), ([TAU], [TAU, 1.]), ]); let boundary = CurveBoundary::from([[0.], [TAU]]); + let half_edge = HalfEdgeGeometry { path, boundary }; let surface = SurfaceGeometry { u: global_path, v: [0., 0., 1.].into(), }; let tolerance = 1.; - let approx = (&curve, surface_path, &surface, boundary) - .approx(tolerance, &mut core); + let approx = + (&curve, &half_edge, &surface).approx(tolerance, &mut core); let expected_approx = (global_path, boundary) .approx(tolerance, &mut core) .into_iter() .map(|(point_local, _)| { - let point_surface = - surface_path.point_from_path_coords(point_local); + let point_surface = path.point_from_path_coords(point_local); let point_global = surface.point_from_surface_coords(point_surface); ApproxPoint::new(point_local, point_global) @@ -269,21 +270,20 @@ mod tests { let mut core = Core::new(); let curve = Curve::new().insert(&mut core); - let surface_path = - SurfacePath::circle_from_center_and_radius([0., 0.], 1.); + let path = SurfacePath::circle_from_center_and_radius([0., 0.], 1.); let boundary = CurveBoundary::from([[0.], [TAU]]); + let half_edge = HalfEdgeGeometry { path, boundary }; let surface = core.layers.geometry.xz_plane(); let tolerance = 1.; - let approx = (&curve, surface_path, &surface, boundary) - .approx(tolerance, &mut core); + let approx = + (&curve, &half_edge, &surface).approx(tolerance, &mut core); - let expected_approx = (&surface_path, boundary) + let expected_approx = (&path, boundary) .approx(tolerance, &mut core) .into_iter() .map(|(point_local, _)| { - let point_surface = - surface_path.point_from_path_coords(point_local); + let point_surface = path.point_from_path_coords(point_local); let point_global = surface.point_from_surface_coords(point_surface); ApproxPoint::new(point_local, point_global) diff --git a/crates/fj-core/src/algorithms/approx/edge.rs b/crates/fj-core/src/algorithms/approx/edge.rs index 356cb193d0..5db47de993 100644 --- a/crates/fj-core/src/algorithms/approx/edge.rs +++ b/crates/fj-core/src/algorithms/approx/edge.rs @@ -50,9 +50,8 @@ impl Approx for (&Handle, &SurfaceGeometry) { let rest = { let approx = ( half_edge.curve(), - core.layers.geometry.of_half_edge(half_edge).path, + &core.layers.geometry.of_half_edge(half_edge), surface, - half_edge.boundary(), ) .approx_with_cache( tolerance, diff --git a/crates/fj-core/src/algorithms/bounding_volume/edge.rs b/crates/fj-core/src/algorithms/bounding_volume/edge.rs index ec7ed05f20..4e243d1581 100644 --- a/crates/fj-core/src/algorithms/bounding_volume/edge.rs +++ b/crates/fj-core/src/algorithms/bounding_volume/edge.rs @@ -22,11 +22,10 @@ impl super::BoundingVolume<2> for Handle { }) } SurfacePath::Line(_) => { - let points = self.boundary().inner.map(|point_curve| { - geometry - .of_half_edge(self) - .path - .point_from_path_coords(point_curve) + let geometry = geometry.of_half_edge(self); + + let points = geometry.boundary.inner.map(|point_curve| { + geometry.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 b1fc57b6a3..40e84b53a7 100644 --- a/crates/fj-core/src/objects/kinds/cycle.rs +++ b/crates/fj-core/src/objects/kinds/cycle.rs @@ -40,10 +40,12 @@ impl Cycle { .next() .expect("Invalid cycle: expected at least one edge"); - let [a, b] = first.boundary().inner; + let geometry = geometry.of_half_edge(first); + + let [a, b] = geometry.boundary.inner; let edge_direction_positive = a < b; - let circle = match geometry.of_half_edge(first).path { + let circle = match geometry.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/objects/kinds/half_edge.rs b/crates/fj-core/src/objects/kinds/half_edge.rs index 523def5dc8..6608d40d3c 100644 --- a/crates/fj-core/src/objects/kinds/half_edge.rs +++ b/crates/fj-core/src/objects/kinds/half_edge.rs @@ -1,7 +1,4 @@ -use fj_math::Point; - use crate::{ - geometry::CurveBoundary, objects::{Curve, Vertex}, storage::Handle, }; @@ -35,30 +32,19 @@ use crate::{ /// [`Shell`]: crate::objects::Shell #[derive(Clone, Debug)] pub struct HalfEdge { - boundary: CurveBoundary>, curve: Handle, start_vertex: Handle, } impl HalfEdge { /// Create an instance of `Edge` - pub fn new( - boundary: impl Into>>, - curve: Handle, - start_vertex: Handle, - ) -> Self { + pub fn new(curve: Handle, start_vertex: Handle) -> Self { Self { - boundary: boundary.into(), curve, start_vertex, } } - /// Access the boundary points of the edge on the curve - pub fn boundary(&self) -> CurveBoundary> { - self.boundary - } - /// Access the curve of the edge pub fn curve(&self) -> &Handle { &self.curve diff --git a/crates/fj-core/src/operations/build/half_edge.rs b/crates/fj-core/src/operations/build/half_edge.rs index 0d0a3ce5aa..53c3abcd57 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, HalfEdgeGeometry, SurfacePath}, + geometry::{HalfEdgeGeometry, SurfacePath}, objects::{Curve, HalfEdge, Vertex}, operations::{geometry::UpdateHalfEdgeGeometry, insert::Insert}, storage::Handle, @@ -16,14 +16,11 @@ use crate::{ /// [module-level documentation]: super pub trait BuildHalfEdge { /// Create a half-edge that is not joined to a sibling - fn unjoined( - boundary: impl Into>>, - core: &mut Core, - ) -> HalfEdge { + fn unjoined(core: &mut Core) -> HalfEdge { let curve = Curve::new().insert(core); let start_vertex = Vertex::new().insert(core); - HalfEdge::new(boundary, curve, start_vertex) + HalfEdge::new(curve, start_vertex) } /// Create a half-edge from its sibling @@ -35,13 +32,9 @@ pub trait BuildHalfEdge { let mut geometry = core.layers.geometry.of_half_edge(sibling); geometry.boundary = geometry.boundary.reverse(); - HalfEdge::new( - sibling.boundary().reverse(), - sibling.curve().clone(), - start_vertex, - ) - .insert(core) - .set_geometry(geometry, &mut core.layers.geometry) + HalfEdge::new(sibling.curve().clone(), start_vertex) + .insert(core) + .set_geometry(geometry, &mut core.layers.geometry) } /// Create an arc @@ -67,7 +60,7 @@ pub trait BuildHalfEdge { let boundary = [arc.start_angle, arc.end_angle].map(|coord| Point::from([coord])); - let half_edge = HalfEdge::unjoined(boundary, core).insert(core); + let half_edge = HalfEdge::unjoined(core).insert(core); core.layers.geometry.define_half_edge( half_edge.clone(), HalfEdgeGeometry { @@ -89,7 +82,7 @@ pub trait BuildHalfEdge { let boundary = [Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord])); - let half_edge = HalfEdge::unjoined(boundary, core).insert(core); + let half_edge = HalfEdge::unjoined(core).insert(core); core.layers.geometry.define_half_edge( half_edge.clone(), HalfEdgeGeometry { @@ -113,15 +106,13 @@ pub trait BuildHalfEdge { boundary.zip_ext(points_surface), ); - HalfEdge::unjoined(boundary, core) - .insert(core) - .set_geometry( - HalfEdgeGeometry { - path, - boundary: boundary.into(), - }, - &mut core.layers.geometry, - ) + HalfEdge::unjoined(core).insert(core).set_geometry( + HalfEdgeGeometry { + path, + boundary: boundary.into(), + }, + &mut core.layers.geometry, + ) } } diff --git a/crates/fj-core/src/operations/holes.rs b/crates/fj-core/src/operations/holes.rs index 3017c09ef0..7b19b73478 100644 --- a/crates/fj-core/src/operations/holes.rs +++ b/crates/fj-core/src/operations/holes.rs @@ -68,11 +68,7 @@ impl AddHole for Shell { [Cycle::empty().add_joined_edges( [( entry.clone(), - core.layers - .geometry - .of_half_edge(&entry) - .path, - entry.boundary(), + core.layers.geometry.of_half_edge(&entry), )], core, )], @@ -142,11 +138,7 @@ impl AddHole for Shell { [Cycle::empty().add_joined_edges( [( entry.clone(), - core.layers - .geometry - .of_half_edge(&entry) - .path, - entry.boundary(), + core.layers.geometry.of_half_edge(&entry), )], core, )], @@ -167,11 +159,7 @@ impl AddHole for Shell { [Cycle::empty().add_joined_edges( [( exit.clone(), - core.layers - .geometry - .of_half_edge(exit) - .path, - exit.boundary(), + core.layers.geometry.of_half_edge(exit), )], core, )], diff --git a/crates/fj-core/src/operations/join/cycle.rs b/crates/fj-core/src/operations/join/cycle.rs index 82cd9bfc8c..5821a1d68f 100644 --- a/crates/fj-core/src/operations/join/cycle.rs +++ b/crates/fj-core/src/operations/join/cycle.rs @@ -1,10 +1,9 @@ use std::ops::RangeInclusive; -use fj_math::Point; use itertools::Itertools; use crate::{ - geometry::{CurveBoundary, HalfEdgeGeometry, SurfacePath}, + geometry::HalfEdgeGeometry, objects::{Cycle, HalfEdge}, operations::{ build::BuildHalfEdge, @@ -22,9 +21,7 @@ pub trait JoinCycle { #[must_use] fn add_joined_edges(&self, edges: Es, core: &mut Core) -> Self where - Es: IntoIterator< - Item = (Handle, SurfacePath, CurveBoundary>), - >, + Es: IntoIterator, HalfEdgeGeometry)>, Es::IntoIter: Clone + ExactSizeIterator; /// Join the cycle to another @@ -81,26 +78,21 @@ pub trait JoinCycle { impl JoinCycle for Cycle { fn add_joined_edges(&self, edges: Es, core: &mut Core) -> Self where - Es: IntoIterator< - Item = (Handle, SurfacePath, CurveBoundary>), - >, + Es: IntoIterator, HalfEdgeGeometry)>, Es::IntoIter: Clone + ExactSizeIterator, { let half_edges = edges .into_iter() .circular_tuple_windows() - .map(|((prev_half_edge, _, _), (half_edge, path, boundary))| { - HalfEdge::unjoined(boundary, core) + .map(|((prev_half_edge, _), (half_edge, geometry))| { + HalfEdge::unjoined(core) .update_curve(|_, _| half_edge.curve().clone(), core) .update_start_vertex( |_, _| prev_half_edge.start_vertex().clone(), core, ) .insert(core) - .set_geometry( - HalfEdgeGeometry { path, boundary }, - &mut core.layers.geometry, - ) + .set_geometry(geometry, &mut core.layers.geometry) }) .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 a3dd7b3cb9..f3d3f341d4 100644 --- a/crates/fj-core/src/operations/reverse/cycle.rs +++ b/crates/fj-core/src/operations/reverse/cycle.rs @@ -18,7 +18,6 @@ impl Reverse for Cycle { geometry.boundary = geometry.boundary.reverse(); HalfEdge::new( - current.boundary().reverse(), current.curve().clone(), next.start_vertex().clone(), ) diff --git a/crates/fj-core/src/operations/reverse/edge.rs b/crates/fj-core/src/operations/reverse/edge.rs index 4508a25e76..e42ae6a98a 100644 --- a/crates/fj-core/src/operations/reverse/edge.rs +++ b/crates/fj-core/src/operations/reverse/edge.rs @@ -13,13 +13,10 @@ impl ReverseCurveCoordinateSystems for Handle { geometry.path = geometry.path.reverse(); geometry.boundary = geometry.boundary.reverse(); - let half_edge = HalfEdge::new( - geometry.boundary, - self.curve().clone(), - self.start_vertex().clone(), - ) - .insert(core) - .derive_from(self, core); + let half_edge = + HalfEdge::new(self.curve().clone(), self.start_vertex().clone()) + .insert(core) + .derive_from(self, core); core.layers .geometry diff --git a/crates/fj-core/src/operations/split/edge.rs b/crates/fj-core/src/operations/split/edge.rs index 84496ca443..b85893a4f5 100644 --- a/crates/fj-core/src/operations/split/edge.rs +++ b/crates/fj-core/src/operations/split/edge.rs @@ -37,7 +37,7 @@ impl SplitEdge for Shell { let point = point.into(); let sibling = self - .get_sibling_of(half_edge) + .get_sibling_of(half_edge, &core.layers.geometry) .expect("Expected half-edge and its sibling to be part of shell"); let [half_edge_a, half_edge_b] = half_edge.split_half_edge(point, core); diff --git a/crates/fj-core/src/operations/split/half_edge.rs b/crates/fj-core/src/operations/split/half_edge.rs index 9279599a81..92621b7fa4 100644 --- a/crates/fj-core/src/operations/split/half_edge.rs +++ b/crates/fj-core/src/operations/split/half_edge.rs @@ -42,36 +42,24 @@ impl SplitHalfEdge for Handle { ) -> [Handle; 2] { let point = point.into(); - let [start, end] = self.boundary().inner; + let geometry = core.layers.geometry.of_half_edge(self); + let [start, end] = geometry.boundary.inner; - let a = HalfEdge::new( - [start, point], - self.curve().clone(), - self.start_vertex().clone(), - ) - .insert(core) - .derive_from(self, core) - .set_geometry( - core.layers - .geometry - .of_half_edge(self) - .with_boundary([start, point]), - &mut core.layers.geometry, - ); - let b = HalfEdge::new( - [point, end], - self.curve().clone(), - Vertex::new().insert(core), - ) - .insert(core) - .derive_from(self, core) - .set_geometry( - core.layers - .geometry - .of_half_edge(self) - .with_boundary([point, end]), - &mut core.layers.geometry, - ); + let a = + HalfEdge::new(self.curve().clone(), self.start_vertex().clone()) + .insert(core) + .derive_from(self, core) + .set_geometry( + geometry.with_boundary([start, point]), + &mut core.layers.geometry, + ); + let b = HalfEdge::new(self.curve().clone(), Vertex::new().insert(core)) + .insert(core) + .derive_from(self, core) + .set_geometry( + geometry.with_boundary([point, end]), + &mut core.layers.geometry, + ); [a, b] } diff --git a/crates/fj-core/src/operations/sweep/cycle.rs b/crates/fj-core/src/operations/sweep/cycle.rs index 23f04051cd..313c71efc8 100644 --- a/crates/fj-core/src/operations/sweep/cycle.rs +++ b/crates/fj-core/src/operations/sweep/cycle.rs @@ -77,8 +77,7 @@ impl SweepCycle for Cycle { top_edges.push(( top_edge, - core.layers.geometry.of_half_edge(bottom_half_edge).path, - bottom_half_edge.boundary(), + core.layers.geometry.of_half_edge(bottom_half_edge), )); } diff --git a/crates/fj-core/src/operations/sweep/half_edge.rs b/crates/fj-core/src/operations/sweep/half_edge.rs index 3014c16b2f..4fbb1f711d 100644 --- a/crates/fj-core/src/operations/sweep/half_edge.rs +++ b/crates/fj-core/src/operations/sweep/half_edge.rs @@ -59,12 +59,8 @@ impl SweepHalfEdge for Handle { ) -> (Face, Handle) { let path = path.into(); - let surface = core - .layers - .geometry - .of_half_edge(self) - .path - .sweep_surface_path(surface, path, core); + let geometry = core.layers.geometry.of_half_edge(self); + let surface = geometry.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. @@ -86,7 +82,7 @@ impl SweepHalfEdge for Handle { // Let's figure out the surface coordinates of the edge vertices. let surface_points = { - let [a, b] = self.boundary().inner; + let [a, b] = geometry.boundary.inner; [ [a.t, Scalar::ZERO], @@ -104,7 +100,7 @@ impl SweepHalfEdge for Handle { // Now, the boundaries of each edge. let boundaries = { - let [a, b] = self.boundary().inner; + let [a, b] = geometry.boundary.inner; let [c, d] = [0., 1.].map(|coord| Point::from([coord])); [[a, b], [c, d], [b, a], [d, c]] diff --git a/crates/fj-core/src/operations/transform/edge.rs b/crates/fj-core/src/operations/transform/edge.rs index 9e1a708adc..6baf3fcc9f 100644 --- a/crates/fj-core/src/operations/transform/edge.rs +++ b/crates/fj-core/src/operations/transform/edge.rs @@ -13,7 +13,6 @@ impl TransformObject for Handle { core: &mut Core, cache: &mut TransformCache, ) -> Self { - let boundary = self.boundary(); let curve = self .curve() .clone() @@ -23,8 +22,7 @@ impl TransformObject for Handle { .clone() .transform_with_cache(transform, core, cache); - let half_edge = - HalfEdge::new(boundary, curve, start_vertex).insert(core); + let half_edge = HalfEdge::new(curve, start_vertex).insert(core); core.layers.geometry.define_half_edge( half_edge.clone(), diff --git a/crates/fj-core/src/operations/update/half_edge.rs b/crates/fj-core/src/operations/update/half_edge.rs index 003a6a2244..b1f782d1d6 100644 --- a/crates/fj-core/src/operations/update/half_edge.rs +++ b/crates/fj-core/src/operations/update/half_edge.rs @@ -38,7 +38,6 @@ impl UpdateHalfEdge for HalfEdge { T: Insert>, { HalfEdge::new( - self.boundary(), update(self.curve(), core) .insert(core) .derive_from(self.curve(), core), @@ -55,7 +54,6 @@ impl UpdateHalfEdge for HalfEdge { T: Insert>, { HalfEdge::new( - self.boundary(), self.curve().clone(), update(self.start_vertex(), core) .insert(core) diff --git a/crates/fj-core/src/queries/sibling_of_half_edge.rs b/crates/fj-core/src/queries/sibling_of_half_edge.rs index 5c5dd2314c..07583f548e 100644 --- a/crates/fj-core/src/queries/sibling_of_half_edge.rs +++ b/crates/fj-core/src/queries/sibling_of_half_edge.rs @@ -1,4 +1,5 @@ use crate::{ + geometry::Geometry, objects::{HalfEdge, Shell}, storage::Handle, }; @@ -8,7 +9,12 @@ use super::BoundingVerticesOfHalfEdge; /// Queries related to the sibling of a [`HalfEdge`] pub trait SiblingOfHalfEdge { /// Indicate whether the provided half-edges are siblings - fn are_siblings(&self, a: &Handle, b: &Handle) -> bool; + fn are_siblings( + &self, + a: &Handle, + b: &Handle, + geometry: &Geometry, + ) -> bool; /// Retrieve the sibling of this half-edge /// @@ -18,13 +24,20 @@ pub trait SiblingOfHalfEdge { fn get_sibling_of( &self, half_edge: &Handle, + geometry: &Geometry, ) -> Option>; } impl SiblingOfHalfEdge for Shell { - fn are_siblings(&self, a: &Handle, b: &Handle) -> bool { + fn are_siblings( + &self, + a: &Handle, + b: &Handle, + geometry: &Geometry, + ) -> bool { let same_curve = a.curve().id() == b.curve().id(); - let same_boundary = a.boundary() == b.boundary().reverse(); + let same_boundary = geometry.of_half_edge(a).boundary + == geometry.of_half_edge(b).boundary.reverse(); let same_vertices = { let Some(a_vertices) = self.bounding_vertices_of_half_edge(a) else { @@ -44,11 +57,12 @@ impl SiblingOfHalfEdge for Shell { fn get_sibling_of( &self, half_edge: &Handle, + geometry: &Geometry, ) -> Option> { for face in self.faces() { for cycle in face.region().all_cycles() { for h in cycle.half_edges() { - if self.are_siblings(half_edge, h) { + if self.are_siblings(half_edge, h, geometry) { return Some(h.clone()); } } diff --git a/crates/fj-core/src/validate/shell.rs b/crates/fj-core/src/validate/shell.rs index 237d743c16..83d85a258c 100644 --- a/crates/fj-core/src/validate/shell.rs +++ b/crates/fj-core/src/validate/shell.rs @@ -23,7 +23,7 @@ impl Validate for Shell { ShellValidationError::check_curve_coordinates( self, geometry, config, errors, ); - ShellValidationError::check_half_edge_pairs(self, errors); + ShellValidationError::check_half_edge_pairs(self, geometry, errors); ShellValidationError::check_half_edge_coincidence( self, geometry, config, errors, ); @@ -112,7 +112,7 @@ impl ShellValidationError { // we have right now are circles, 3 would be enough to check // for coincidence. But the first and last might be // identical, so let's add an extra one. - let [a, d] = edge_a.boundary().inner; + let [a, d] = geometry.of_half_edge(edge_a).boundary.inner; let b = a + (d - a) * 1. / 3.; let c = a + (d - a) * 2. / 3.; @@ -177,14 +177,18 @@ impl ShellValidationError { } /// Check that each half-edge is part of a pair - fn check_half_edge_pairs(shell: &Shell, errors: &mut Vec) { + fn check_half_edge_pairs( + shell: &Shell, + geometry: &Geometry, + errors: &mut Vec, + ) { let mut unmatched_half_edges = BTreeMap::new(); for face in shell.faces() { for cycle in face.region().all_cycles() { for half_edge in cycle.half_edges() { let curve = half_edge.curve().clone(); - let boundary = half_edge.boundary(); + let boundary = geometry.of_half_edge(half_edge).boundary; let vertices = cycle.bounding_vertices_of_half_edge(half_edge).expect( "`half_edge` came from `cycle`, must exist there", @@ -200,7 +204,8 @@ impl ShellValidationError { // currently looking at. Let's make sure the logic // we use here to determine that matches the // "official" definition. - assert!(shell.are_siblings(half_edge, sibling)); + assert!(shell + .are_siblings(half_edge, sibling, geometry)); } None => { // If this half-edge has a sibling, we haven't seen @@ -238,7 +243,7 @@ impl ShellValidationError { continue; } - if shell.are_siblings(half_edge_a, half_edge_b) { + if shell.are_siblings(half_edge_a, half_edge_b, geometry) { // If the half-edges are siblings, they are allowed to be // coincident. Must be, in fact. There's another validation // check that takes care of that. @@ -257,8 +262,11 @@ impl ShellValidationError { .all(|d| d < config.distinct_min_distance) { let boundaries = Box::new(CoincidentHalfEdgeBoundaries { - boundaries: [half_edge_a, half_edge_b] - .map(|half_edge| half_edge.boundary()), + boundaries: [half_edge_a, half_edge_b].map( + |half_edge| { + geometry.of_half_edge(half_edge).boundary + }, + ), }); let curves = Box::new(CoincidentHalfEdgeCurves { curves: [half_edge_a, half_edge_b] @@ -384,7 +392,7 @@ fn distances( (edge, surface): (&Handle, &SurfaceGeometry), geometry: &Geometry, ) -> Point<3> { - let [start, end] = edge.boundary().inner; + let [start, end] = geometry.of_half_edge(edge).boundary.inner; let path_coords = start + (end - start) * percent; let surface_coords = geometry .of_half_edge(edge) @@ -454,7 +462,6 @@ mod tests { geometry.boundary.reverse(); [HalfEdge::new( - half_edge.boundary().reverse(), half_edge.curve().clone(), half_edge.start_vertex().clone(), ) 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 0cad2daa8e..7fefc9560e 100644 --- a/crates/fj-core/src/validation/checks/half_edge_connection.rs +++ b/crates/fj-core/src/validation/checks/half_edge_connection.rs @@ -46,7 +46,7 @@ impl ValidationCheck for AdjacentHalfEdgesNotConnected { ) -> impl Iterator { object.half_edges().pairs().filter_map(|(first, second)| { let end_pos_of_first_half_edge = { - let [_, end] = first.boundary().inner; + let [_, end] = geometry.of_half_edge(first).boundary.inner; geometry .of_half_edge(first) .path