From 97bf88fbe8b5e9226c0ca0dd85becd5c8b404321 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 23 Apr 2024 14:38:58 +0200 Subject: [PATCH] Move `Cycle` validation check to `Face`/`Sketch` The code of this check is going to require access to a `Surface` soon, due to changes I'm working on. The reshuffling done in this commit is preparation for having this surface available. --- crates/fj-core/src/validate/cycle.rs | 15 ++-- crates/fj-core/src/validate/face.rs | 9 ++- crates/fj-core/src/validate/sketch.rs | 5 ++ .../validation/checks/half_edge_connection.rs | 68 +++++++++++++++---- 4 files changed, 73 insertions(+), 24 deletions(-) diff --git a/crates/fj-core/src/validate/cycle.rs b/crates/fj-core/src/validate/cycle.rs index bc9ed4ddf..854a9adba 100644 --- a/crates/fj-core/src/validate/cycle.rs +++ b/crates/fj-core/src/validate/cycle.rs @@ -1,10 +1,7 @@ use crate::{ geometry::Geometry, topology::Cycle, - validation::{ - checks::AdjacentHalfEdgesNotConnected, ValidationCheck, - ValidationConfig, ValidationError, - }, + validation::{ValidationConfig, ValidationError}, }; use super::Validate; @@ -12,13 +9,9 @@ use super::Validate; impl Validate for Cycle { fn validate( &self, - config: &ValidationConfig, - errors: &mut Vec, - geometry: &Geometry, + _: &ValidationConfig, + _: &mut Vec, + _: &Geometry, ) { - errors.extend( - AdjacentHalfEdgesNotConnected::check(self, geometry, config) - .map(Into::into), - ); } } diff --git a/crates/fj-core/src/validate/face.rs b/crates/fj-core/src/validate/face.rs index 4ffd9d9c0..a168dff8a 100644 --- a/crates/fj-core/src/validate/face.rs +++ b/crates/fj-core/src/validate/face.rs @@ -2,7 +2,10 @@ use crate::{ geometry::Geometry, topology::Face, validation::{ - checks::{FaceHasNoBoundary, InteriorCycleHasInvalidWinding}, + checks::{ + AdjacentHalfEdgesNotConnected, FaceHasNoBoundary, + InteriorCycleHasInvalidWinding, + }, ValidationCheck, ValidationConfig, ValidationError, }, }; @@ -16,6 +19,10 @@ impl Validate for Face { errors: &mut Vec, geometry: &Geometry, ) { + errors.extend( + AdjacentHalfEdgesNotConnected::check(self, geometry, config) + .map(Into::into), + ); errors.extend( FaceHasNoBoundary::check(self, geometry, config).map(Into::into), ); diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index 5445cc235..b8231bd09 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -5,6 +5,7 @@ use crate::{ storage::Handle, topology::{Cycle, Sketch}, validate_references, + validation::{checks::AdjacentHalfEdgesNotConnected, ValidationCheck}, }; use super::{ @@ -19,6 +20,10 @@ impl Validate for Sketch { errors: &mut Vec, geometry: &Geometry, ) { + errors.extend( + AdjacentHalfEdgesNotConnected::check(self, geometry, config) + .map(Into::into), + ); SketchValidationError::check_object_references(self, config, errors); SketchValidationError::check_exterior_cycles( self, geometry, config, errors, 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 7e61cee87..489b42608 100644 --- a/crates/fj-core/src/validation/checks/half_edge_connection.rs +++ b/crates/fj-core/src/validation/checks/half_edge_connection.rs @@ -3,7 +3,7 @@ use fj_math::{Point, Scalar}; use crate::{ geometry::Geometry, storage::Handle, - topology::{Cycle, HalfEdge}, + topology::{Cycle, Face, HalfEdge, Region, Sketch}, validation::{validation_check::ValidationCheck, ValidationConfig}, }; @@ -57,16 +57,40 @@ pub struct AdjacentHalfEdgesNotConnected { pub unconnected_half_edges: [Handle; 2], } -impl ValidationCheck for AdjacentHalfEdgesNotConnected { +impl ValidationCheck for AdjacentHalfEdgesNotConnected { fn check<'r>( - object: &'r Cycle, + object: &'r Face, geometry: &'r Geometry, config: &'r ValidationConfig, ) -> impl Iterator + 'r { - check_cycle(object, geometry, config) + check_region(object.region(), geometry, config) } } +impl ValidationCheck for AdjacentHalfEdgesNotConnected { + fn check<'r>( + object: &'r Sketch, + geometry: &'r Geometry, + config: &'r ValidationConfig, + ) -> impl Iterator + 'r { + object + .regions() + .iter() + .flat_map(|region| check_region(region, geometry, config)) + } +} + +fn check_region<'r>( + region: &'r Region, + geometry: &'r Geometry, + config: &'r ValidationConfig, +) -> impl Iterator + 'r { + [region.exterior()] + .into_iter() + .chain(region.interiors()) + .flat_map(|cycle| check_cycle(cycle, geometry, config)) +} + fn check_cycle<'r>( cycle: &'r Cycle, geometry: &'r Geometry, @@ -105,10 +129,10 @@ mod tests { use crate::{ operations::{ - build::{BuildCycle, BuildHalfEdge}, - update::UpdateCycle, + build::{BuildFace, BuildHalfEdge}, + update::{UpdateCycle, UpdateFace, UpdateRegion}, }, - topology::{Cycle, HalfEdge}, + topology::{Face, HalfEdge}, validation::ValidationCheck, Core, }; @@ -119,16 +143,36 @@ mod tests { fn adjacent_half_edges_not_connected() -> anyhow::Result<()> { let mut core = Core::new(); - let valid = Cycle::polygon([[0., 0.], [1., 0.], [1., 1.]], &mut core); + // We're only testing for `Face` here, not `Sketch`. Should be fine, as + // most of the code is shared. + let valid = Face::polygon( + core.layers.topology.surfaces.space_2d(), + [[0., 0.], [1., 0.], [1., 1.]], + &mut core, + ); AdjacentHalfEdgesNotConnected::check_and_return_first_error( &valid, &core.layers.geometry, )?; - let invalid = valid.update_half_edge( - valid.half_edges().first(), - |_, core| { - [HalfEdge::line_segment([[0., 0.], [2., 0.]], None, core)] + let invalid = valid.update_region( + |region, core| { + region.update_exterior( + |cycle, core| { + cycle.update_half_edge( + cycle.half_edges().first(), + |_, core| { + [HalfEdge::line_segment( + [[0., 0.], [2., 0.]], + None, + core, + )] + }, + core, + ) + }, + core, + ) }, &mut core, );