use tracing::instrument;
use crate::{FaceId, HalfedgeId, MeshGraph, VertexId, error_none, utils::unwrap_or_return};
impl MeshGraph {
#[instrument(skip(self))]
pub fn boundary_he(&self, he_id: HalfedgeId) -> Option<HalfedgeId> {
let he = *self
.halfedges
.get(he_id)
.or_else(error_none!("Halfedge not found"))?;
if he.is_boundary() {
return Some(he_id);
}
let twin_id = he.twin.or_else(error_none!("Twin missing"))?;
let twin_he = self
.halfedges
.get(twin_id)
.or_else(error_none!("Twin not found"))?;
if twin_he.is_boundary() {
return Some(twin_id);
}
None
}
#[instrument(skip(self))]
pub fn boundary_vertex_order(&mut self, v_id1: VertexId, v_id2: VertexId) -> [VertexId; 2] {
let he_id = unwrap_or_return!(
self.halfedge_from_to(v_id1, v_id2),
"Couldn't find halfedge between {v_id1:?} and {v_id2:?}",
[v_id1, v_id2]
);
let he = self.halfedges[he_id];
if he.is_boundary() {
[v_id1, v_id2]
} else {
[v_id2, v_id1]
}
}
#[instrument(skip(self))]
pub fn halfedge_from_to(
&self,
start_vertex_id: VertexId,
end_vertex_id: VertexId,
) -> Option<HalfedgeId> {
let out_hes = self
.outgoing_halfedges
.get(start_vertex_id)
.or_else(error_none!("Start vertex not found"))?;
out_hes.iter().copied().find(|he_id| {
self.halfedges
.get(*he_id)
.is_some_and(|he| he.end_vertex == end_vertex_id)
})
}
pub fn face_with_vertices(
&self,
v_id1: VertexId,
v_id2: VertexId,
v_id3: VertexId,
) -> Option<FaceId> {
let he_id = self.halfedge_from_to(v_id1, v_id2)?;
let he = self
.halfedges
.get(he_id)
.or_else(error_none!("Halfedge not found"))?;
if Some(v_id3) == he.opposite_vertex(self) {
return he.face.or_else(error_none!("No face"));
}
let twin_id = he.twin.or_else(error_none!("No twin"))?;
let twin = self
.halfedges
.get(twin_id)
.or_else(error_none!("Twin not found"))?;
if Some(v_id3) == twin.opposite_vertex(self) {
return twin.face.or_else(error_none!("No face"));
}
None
}
}