use crate::trids::node::VertexNode;
use super::{
hedge_iterator::HedgeIterator,
tet_data_structure::{TetDataStructure, TRIANGLE_SUBINDICES},
tet_iterator::TetIterator,
};
#[derive(Copy, Clone)]
pub struct HalfTriIterator<'a> {
pub tds: &'a TetDataStructure,
pub half_tri_idx: usize,
}
impl<'a> HalfTriIterator<'a> {
pub fn hedges(&self) -> [HedgeIterator<'a>; 3] {
[
HedgeIterator {
tds: self.tds,
hedge_idx: 0,
half_tri_idx: self.half_tri_idx,
},
HedgeIterator {
tds: self.tds,
hedge_idx: 1,
half_tri_idx: self.half_tri_idx,
},
HedgeIterator {
tds: self.tds,
hedge_idx: 2,
half_tri_idx: self.half_tri_idx,
},
]
}
pub fn idx(&self) -> usize {
self.half_tri_idx
}
pub fn is_sound(&self) -> bool {
let [n0, n1, n2] = self.nodes();
let [n_opposite0, n_opposite1, n_opposite2] = self.opposite().nodes();
if !((n0 == n_opposite0 && n1 == n_opposite2 && n2 == n_opposite1)
|| (n0 == n_opposite2 && n1 == n_opposite1 && n2 == n_opposite0)
|| (n0 == n_opposite1 && n1 == n_opposite0 && n2 == n_opposite2))
{
log::error!("{}: Wrong opposite triangle: {}", self, self.opposite());
return false;
}
true
}
pub fn is_conceptual(&self) -> bool {
self.nodes().iter().any(|n| n.is_conceptual())
}
pub fn nodes(&self) -> [VertexNode; 3] {
let mod4 = self.half_tri_idx % 4;
let sub_idx = TRIANGLE_SUBINDICES[mod4];
[
self.tds.tet_nodes[self.half_tri_idx - mod4 + sub_idx[0]],
self.tds.tet_nodes[self.half_tri_idx - mod4 + sub_idx[1]],
self.tds.tet_nodes[self.half_tri_idx - mod4 + sub_idx[2]],
]
}
pub fn opposite_node(&self) -> VertexNode {
self.tds.tet_nodes[self.idx()]
}
pub fn opposite(&self) -> HalfTriIterator<'a> {
HalfTriIterator {
tds: self.tds,
half_tri_idx: self.tds.half_tri_opposite[self.idx()],
}
}
pub fn tet(&self) -> TetIterator<'a> {
TetIterator {
tds: self.tds,
tet_idx: self.half_tri_idx >> 2, }
}
}
impl std::fmt::Display for HalfTriIterator<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let [n0, n1, n2] = self.nodes();
write!(
f,
"Triangle {}: {} -> {} -> {}",
self.half_tri_idx, n0, n1, n2
)
}
}