Merge pull request #2406 from hannobraun/query

Simplify half-edge sibling query
This commit is contained in:
Hanno Braun 2024-06-28 20:06:14 +02:00 committed by GitHub
commit 14b95668bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 10 additions and 28 deletions

View File

@ -37,7 +37,7 @@ impl SplitEdge for Shell {
let point = point.into(); let point = point.into();
let sibling = self let sibling = self
.get_sibling_of(half_edge, &core.layers.geometry) .get_sibling_of(half_edge)
.expect("Expected half-edge and its sibling to be part of shell"); .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); let [half_edge_a, half_edge_b] = half_edge.split_half_edge(point, core);

View File

@ -1,5 +1,4 @@
use crate::{ use crate::{
geometry::Geometry,
storage::Handle, storage::Handle,
topology::{HalfEdge, Shell}, topology::{HalfEdge, Shell},
}; };
@ -9,12 +8,7 @@ use super::BoundingVerticesOfHalfEdge;
/// Queries related to the sibling of a [`HalfEdge`] /// Queries related to the sibling of a [`HalfEdge`]
pub trait SiblingOfHalfEdge { pub trait SiblingOfHalfEdge {
/// Indicate whether the provided half-edges are siblings /// Indicate whether the provided half-edges are siblings
fn are_siblings( fn are_siblings(&self, a: &Handle<HalfEdge>, b: &Handle<HalfEdge>) -> bool;
&self,
a: &Handle<HalfEdge>,
b: &Handle<HalfEdge>,
geometry: &Geometry,
) -> bool;
/// Retrieve the sibling of this half-edge /// Retrieve the sibling of this half-edge
/// ///
@ -24,20 +18,12 @@ pub trait SiblingOfHalfEdge {
fn get_sibling_of( fn get_sibling_of(
&self, &self,
half_edge: &Handle<HalfEdge>, half_edge: &Handle<HalfEdge>,
geometry: &Geometry,
) -> Option<Handle<HalfEdge>>; ) -> Option<Handle<HalfEdge>>;
} }
impl SiblingOfHalfEdge for Shell { impl SiblingOfHalfEdge for Shell {
fn are_siblings( fn are_siblings(&self, a: &Handle<HalfEdge>, b: &Handle<HalfEdge>) -> bool {
&self,
a: &Handle<HalfEdge>,
b: &Handle<HalfEdge>,
geometry: &Geometry,
) -> bool {
let same_curve = a.curve().id() == b.curve().id(); let same_curve = a.curve().id() == b.curve().id();
let same_boundary = geometry.of_half_edge(a).boundary
== geometry.of_half_edge(b).boundary.reverse();
let same_vertices = { let same_vertices = {
let Some(a_vertices) = self.bounding_vertices_of_half_edge(a) let Some(a_vertices) = self.bounding_vertices_of_half_edge(a)
else { else {
@ -51,18 +37,17 @@ impl SiblingOfHalfEdge for Shell {
a_vertices == b_vertices.reverse() a_vertices == b_vertices.reverse()
}; };
same_curve && same_boundary && same_vertices same_curve && same_vertices
} }
fn get_sibling_of( fn get_sibling_of(
&self, &self,
half_edge: &Handle<HalfEdge>, half_edge: &Handle<HalfEdge>,
geometry: &Geometry,
) -> Option<Handle<HalfEdge>> { ) -> Option<Handle<HalfEdge>> {
for face in self.faces() { for face in self.faces() {
for cycle in face.region().all_cycles() { for cycle in face.region().all_cycles() {
for h in cycle.half_edges() { for h in cycle.half_edges() {
if self.are_siblings(half_edge, h, geometry) { if self.are_siblings(half_edge, h) {
return Some(h.clone()); return Some(h.clone());
} }
} }

View File

@ -117,7 +117,7 @@ impl ValidationCheck<Shell> for CoincidentHalfEdgesAreNotSiblings {
continue; continue;
} }
if object.are_siblings(half_edge_a, half_edge_b, geometry) { if object.are_siblings(half_edge_a, half_edge_b) {
// If the half-edges are siblings, they are allowed to be // If the half-edges are siblings, they are allowed to be
// coincident. Must be, in fact. There's another validation // coincident. Must be, in fact. There's another validation
// check that takes care of that. // check that takes care of that.

View File

@ -27,7 +27,7 @@ pub struct HalfEdgeHasNoSibling {
impl ValidationCheck<Shell> for HalfEdgeHasNoSibling { impl ValidationCheck<Shell> for HalfEdgeHasNoSibling {
fn check<'r>( fn check<'r>(
object: &'r Shell, object: &'r Shell,
geometry: &'r Geometry, _: &'r Geometry,
_: &'r ValidationConfig, _: &'r ValidationConfig,
) -> impl Iterator<Item = Self> + 'r { ) -> impl Iterator<Item = Self> + 'r {
let mut unmatched_half_edges = BTreeMap::new(); let mut unmatched_half_edges = BTreeMap::new();
@ -36,15 +36,13 @@ impl ValidationCheck<Shell> for HalfEdgeHasNoSibling {
for cycle in face.region().all_cycles() { for cycle in face.region().all_cycles() {
for half_edge in cycle.half_edges() { for half_edge in cycle.half_edges() {
let curve = half_edge.curve().clone(); let curve = half_edge.curve().clone();
let boundary = geometry.of_half_edge(half_edge).boundary;
let vertices = let vertices =
cycle.bounding_vertices_of_half_edge(half_edge).expect( cycle.bounding_vertices_of_half_edge(half_edge).expect(
"`half_edge` came from `cycle`, must exist there", "`half_edge` came from `cycle`, must exist there",
); );
let key = (curve.clone(), boundary, vertices.clone()); let key = (curve.clone(), vertices.clone());
let key_reversed = let key_reversed = (curve, vertices.reverse());
(curve, boundary.reverse(), vertices.reverse());
match unmatched_half_edges.remove(&key_reversed) { match unmatched_half_edges.remove(&key_reversed) {
Some(sibling) => { Some(sibling) => {
@ -52,8 +50,7 @@ impl ValidationCheck<Shell> for HalfEdgeHasNoSibling {
// currently looking at. Let's make sure the logic // currently looking at. Let's make sure the logic
// we use here to determine that matches the // we use here to determine that matches the
// "official" definition. // "official" definition.
assert!(object assert!(object.are_siblings(half_edge, sibling));
.are_siblings(half_edge, sibling, geometry));
} }
None => { None => {
// If this half-edge has a sibling, we haven't seen // If this half-edge has a sibling, we haven't seen