diff --git a/crates/fj-core/src/geometry/bounding_vertices.rs b/crates/fj-core/src/geometry/bounding_vertices.rs new file mode 100644 index 000000000..75cb891e4 --- /dev/null +++ b/crates/fj-core/src/geometry/bounding_vertices.rs @@ -0,0 +1,19 @@ +use crate::{ + objects::Vertex, + storage::{Handle, HandleWrapper}, +}; + +/// The bounding vertices of an edge +#[derive(Eq, PartialEq)] +pub struct BoundingVertices { + /// The bounding vertices + pub inner: [HandleWrapper; 2], +} + +impl From<[Handle; 2]> for BoundingVertices { + fn from(vertices: [Handle; 2]) -> Self { + Self { + inner: vertices.map(Into::into), + } + } +} diff --git a/crates/fj-core/src/geometry/mod.rs b/crates/fj-core/src/geometry/mod.rs index cb5a1cb36..732dbbb7f 100644 --- a/crates/fj-core/src/geometry/mod.rs +++ b/crates/fj-core/src/geometry/mod.rs @@ -1,11 +1,13 @@ //! Types that are tied to objects, but aren't objects themselves mod boundary; +mod bounding_vertices; mod path; mod surface; pub use self::{ boundary::BoundaryOnCurve, + bounding_vertices::BoundingVertices, path::{GlobalPath, SurfacePath}, surface::SurfaceGeometry, }; diff --git a/crates/fj-core/src/lib.rs b/crates/fj-core/src/lib.rs index b84a84163..cf7fcad3d 100644 --- a/crates/fj-core/src/lib.rs +++ b/crates/fj-core/src/lib.rs @@ -87,6 +87,7 @@ pub mod algorithms; pub mod geometry; pub mod objects; pub mod operations; +pub mod queries; pub mod services; pub mod storage; pub mod validate; diff --git a/crates/fj-core/src/objects/kinds/cycle.rs b/crates/fj-core/src/objects/kinds/cycle.rs index bc7558307..5c16028ec 100644 --- a/crates/fj-core/src/objects/kinds/cycle.rs +++ b/crates/fj-core/src/objects/kinds/cycle.rs @@ -37,9 +37,7 @@ impl Cycle { /// Access the half-edge after the provided one /// - /// # Panics - /// - /// Panics, if the provided half-edge is not part of this cycle. + /// Returns `None`, if the provided `HalfEdge` is not part of the cycle. pub fn half_edge_after( &self, half_edge: &Handle, diff --git a/crates/fj-core/src/queries.rs b/crates/fj-core/src/queries.rs new file mode 100644 index 000000000..a0116aa36 --- /dev/null +++ b/crates/fj-core/src/queries.rs @@ -0,0 +1,79 @@ +//! Queries about objects +//! +//! Objects have methods that provide access to anything that the object itself +//! has direct access to. However, not all potentially interesting information +//! can be accessed that way. An example are the bounding vertices of an edge: +//! `HalfEdge` only stores its starting vertex, so you need a `Cycle` to get +//! both vertices. +//! +//! 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::BoundingVertices, + objects::{Cycle, Face, HalfEdge, Region, Shell}, + 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(BoundingVertices::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 + } +}