Merge pull request #1949 from hannobraun/queries

Add infrastructure for non-trivial object queries
This commit is contained in:
Hanno Braun 2023-07-18 11:23:52 +02:00 committed by GitHub
commit 5d1d399ba8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 102 additions and 3 deletions

View File

@ -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<Vertex>; 2],
}
impl From<[Handle<Vertex>; 2]> for BoundingVertices {
fn from(vertices: [Handle<Vertex>; 2]) -> Self {
Self {
inner: vertices.map(Into::into),
}
}
}

View File

@ -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,
};

View File

@ -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;

View File

@ -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<HalfEdge>,

View File

@ -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<HalfEdge>,
) -> Option<BoundingVertices>;
}
impl BoundingVerticesOfEdge for Cycle {
fn bounding_vertices_of_edge(
&self,
edge: &Handle<HalfEdge>,
) -> Option<BoundingVertices> {
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<HalfEdge>,
) -> Option<BoundingVertices> {
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<HalfEdge>,
) -> Option<BoundingVertices> {
self.region().bounding_vertices_of_edge(edge)
}
}
impl BoundingVerticesOfEdge for Shell {
fn bounding_vertices_of_edge(
&self,
edge: &Handle<HalfEdge>,
) -> Option<BoundingVertices> {
for face in self.faces() {
if let Some(vertices) = face.bounding_vertices_of_edge(edge) {
return Some(vertices);
}
}
None
}
}