From e144aa419ed65e589ffab663435465f3db2ec595 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 1 Aug 2023 11:09:55 +0200 Subject: [PATCH 1/4] Add dedicated directory for `queries` module --- crates/fj-core/src/{queries.rs => queries/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/fj-core/src/{queries.rs => queries/mod.rs} (100%) diff --git a/crates/fj-core/src/queries.rs b/crates/fj-core/src/queries/mod.rs similarity index 100% rename from crates/fj-core/src/queries.rs rename to crates/fj-core/src/queries/mod.rs From 1cb35cddba1a0a9970348adac9e8087fd43f9c10 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 1 Aug 2023 11:10:56 +0200 Subject: [PATCH 2/4] Move `BoundingVerticesOfEdge` to dedicated module --- .../src/queries/bounding_vertices_of_edge.rs | 68 ++++++++++++++++++ crates/fj-core/src/queries/mod.rs | 69 +------------------ 2 files changed, 70 insertions(+), 67 deletions(-) create mode 100644 crates/fj-core/src/queries/bounding_vertices_of_edge.rs diff --git a/crates/fj-core/src/queries/bounding_vertices_of_edge.rs b/crates/fj-core/src/queries/bounding_vertices_of_edge.rs new file mode 100644 index 000000000..4c1be23eb --- /dev/null +++ b/crates/fj-core/src/queries/bounding_vertices_of_edge.rs @@ -0,0 +1,68 @@ +use crate::{ + geometry::CurveBoundary, + objects::{Cycle, Face, HalfEdge, Region, Shell, Vertex}, + storage::Handle, +}; + +/// Determine the bounding vertices of an edge +pub trait BoundingVerticesOfEdge { + /// Determine the bounding vertices of an edge + /// + /// Returns `None`, if the provided edge is not part of the object this + /// method is called on. + fn bounding_vertices_of_edge( + &self, + edge: &Handle, + ) -> Option>; +} + +impl BoundingVerticesOfEdge for Cycle { + fn bounding_vertices_of_edge( + &self, + edge: &Handle, + ) -> Option> { + let start = edge.start_vertex().clone(); + let end = self.half_edge_after(edge)?.start_vertex().clone(); + + Some(CurveBoundary::from([start, end])) + } +} + +impl BoundingVerticesOfEdge for Region { + fn bounding_vertices_of_edge( + &self, + edge: &Handle, + ) -> Option> { + for cycle in self.all_cycles() { + if let Some(vertices) = cycle.bounding_vertices_of_edge(edge) { + return Some(vertices); + } + } + + None + } +} + +impl BoundingVerticesOfEdge for Face { + fn bounding_vertices_of_edge( + &self, + edge: &Handle, + ) -> Option> { + self.region().bounding_vertices_of_edge(edge) + } +} + +impl BoundingVerticesOfEdge for Shell { + fn bounding_vertices_of_edge( + &self, + edge: &Handle, + ) -> Option> { + for face in self.faces() { + if let Some(vertices) = face.bounding_vertices_of_edge(edge) { + return Some(vertices); + } + } + + None + } +} diff --git a/crates/fj-core/src/queries/mod.rs b/crates/fj-core/src/queries/mod.rs index e4d880b1c..ae7987de9 100644 --- a/crates/fj-core/src/queries/mod.rs +++ b/crates/fj-core/src/queries/mod.rs @@ -9,71 +9,6 @@ //! This module provides traits express such non-trivial queries, and implements //! them for various objects that have the information to answer the query. -use crate::{ - geometry::CurveBoundary, - objects::{Cycle, Face, HalfEdge, Region, Shell, Vertex}, - storage::Handle, -}; +mod bounding_vertices_of_edge; -/// Determine the bounding vertices of an edge -pub trait BoundingVerticesOfEdge { - /// Determine the bounding vertices of an edge - /// - /// Returns `None`, if the provided edge is not part of the object this - /// method is called on. - fn bounding_vertices_of_edge( - &self, - edge: &Handle, - ) -> Option>; -} - -impl BoundingVerticesOfEdge for Cycle { - fn bounding_vertices_of_edge( - &self, - edge: &Handle, - ) -> Option> { - let start = edge.start_vertex().clone(); - let end = self.half_edge_after(edge)?.start_vertex().clone(); - - Some(CurveBoundary::from([start, end])) - } -} - -impl BoundingVerticesOfEdge for Region { - fn bounding_vertices_of_edge( - &self, - edge: &Handle, - ) -> Option> { - for cycle in self.all_cycles() { - if let Some(vertices) = cycle.bounding_vertices_of_edge(edge) { - return Some(vertices); - } - } - - None - } -} - -impl BoundingVerticesOfEdge for Face { - fn bounding_vertices_of_edge( - &self, - edge: &Handle, - ) -> Option> { - self.region().bounding_vertices_of_edge(edge) - } -} - -impl BoundingVerticesOfEdge for Shell { - fn bounding_vertices_of_edge( - &self, - edge: &Handle, - ) -> Option> { - for face in self.faces() { - if let Some(vertices) = face.bounding_vertices_of_edge(edge) { - return Some(vertices); - } - } - - None - } -} +pub use self::bounding_vertices_of_edge::BoundingVerticesOfEdge; From 6dc8e99c5737d3a07e6bae86120e89fe8b84e1f6 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 1 Aug 2023 11:23:49 +0200 Subject: [PATCH 3/4] Add `AllEdgesWithSurface` --- .../src/queries/all_edges_with_surface.rs | 40 +++++++++++++++++++ crates/fj-core/src/queries/mod.rs | 6 ++- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 crates/fj-core/src/queries/all_edges_with_surface.rs diff --git a/crates/fj-core/src/queries/all_edges_with_surface.rs b/crates/fj-core/src/queries/all_edges_with_surface.rs new file mode 100644 index 000000000..ad6e012c0 --- /dev/null +++ b/crates/fj-core/src/queries/all_edges_with_surface.rs @@ -0,0 +1,40 @@ +use crate::{ + objects::{Face, HalfEdge, Shell, Surface}, + storage::Handle, +}; + +/// Access all edges referenced by the object and the surface they're on +pub trait AllEdgesWithSurface { + /// Access all edges referenced by the object and the surface they're on + fn all_edges_with_surface( + &self, + result: &mut Vec<(Handle, Handle)>, + ); +} + +impl AllEdgesWithSurface for Face { + fn all_edges_with_surface( + &self, + result: &mut Vec<(Handle, Handle)>, + ) { + for cycle in self.region().all_cycles() { + result.extend( + cycle + .half_edges() + .cloned() + .map(|half_edge| (half_edge, self.surface().clone())), + ); + } + } +} + +impl AllEdgesWithSurface for Shell { + fn all_edges_with_surface( + &self, + result: &mut Vec<(Handle, Handle)>, + ) { + for face in self.faces() { + face.all_edges_with_surface(result); + } + } +} diff --git a/crates/fj-core/src/queries/mod.rs b/crates/fj-core/src/queries/mod.rs index ae7987de9..b8ffcc6cb 100644 --- a/crates/fj-core/src/queries/mod.rs +++ b/crates/fj-core/src/queries/mod.rs @@ -9,6 +9,10 @@ //! This module provides traits express such non-trivial queries, and implements //! them for various objects that have the information to answer the query. +mod all_edges_with_surface; mod bounding_vertices_of_edge; -pub use self::bounding_vertices_of_edge::BoundingVerticesOfEdge; +pub use self::{ + all_edges_with_surface::AllEdgesWithSurface, + bounding_vertices_of_edge::BoundingVerticesOfEdge, +}; From 6175fe6c3f00a562de4282765f8bae83adcaf033 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 1 Aug 2023 11:24:59 +0200 Subject: [PATCH 4/4] Use new query in validation check --- crates/fj-core/src/validate/shell.rs | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/crates/fj-core/src/validate/shell.rs b/crates/fj-core/src/validate/shell.rs index 0c1452722..4bb91cc2d 100644 --- a/crates/fj-core/src/validate/shell.rs +++ b/crates/fj-core/src/validate/shell.rs @@ -1,14 +1,11 @@ -use std::{ - collections::{BTreeMap, HashMap}, - iter::repeat, -}; +use std::collections::{BTreeMap, HashMap}; use fj_math::{Point, Scalar}; use crate::{ geometry::SurfaceGeometry, objects::{HalfEdge, Shell, Surface}, - queries::BoundingVerticesOfEdge, + queries::{AllEdgesWithSurface, BoundingVerticesOfEdge}, storage::{Handle, HandleWrapper, ObjectId}, }; @@ -115,16 +112,8 @@ impl ShellValidationError { config: &ValidationConfig, errors: &mut Vec, ) { - let edges_and_surfaces: Vec<_> = shell - .faces() - .into_iter() - .flat_map(|face| { - face.region() - .all_cycles() - .flat_map(|cycle| cycle.half_edges().cloned()) - .zip(repeat(face.surface().clone())) - }) - .collect(); + let mut edges_and_surfaces = Vec::new(); + shell.all_edges_with_surface(&mut edges_and_surfaces); // This is O(N^2) which isn't great, but we can't use a HashMap since we // need to deal with float inaccuracies. Maybe we could use some smarter