use core::fmt;
use log::error;
use std::cmp::Ordering;
use crate::utils::types::HedgeIteratorIdx;
use super::{node::VertexNode, tri_data_structure::TriDataStructure, tri_iterator::TriIterator};
#[derive(Copy, Clone)]
pub struct HedgeIterator<'a> {
pub tds: &'a TriDataStructure,
pub idx: HedgeIteratorIdx,
}
impl<'a> HedgeIterator<'a> {
pub fn new(tds: &'a TriDataStructure, idx: HedgeIteratorIdx) -> Self {
Self { tds, idx }
}
pub fn starting_node(&self) -> VertexNode {
self.tds.hedge_starting_nodes[self.idx()]
}
pub fn idx(&self) -> HedgeIteratorIdx {
self.idx
}
pub fn is_conceptual(&self) -> bool {
self.starting_node().is_conceptual() || self.end_node().is_conceptual()
}
pub fn is_sound(&self) -> bool {
let mut sound = true;
let starting_node = self.starting_node();
let end_node = self.end_node();
let mut check = |condition: bool, error_msg: &str| {
if !condition {
error!("{}: {}", self, error_msg);
sound = false;
}
};
check(self.next().starting_node() == end_node, "Wrong next hedge");
check(self.prev().end_node() == starting_node, "Wrong prev hedge");
check(
self.twin().starting_node() == end_node && self.twin().end_node() == starting_node,
"Wrong twin hedge",
);
sound
}
pub fn end_node(&self) -> VertexNode {
match (self.idx() % 3).cmp(&2) {
Ordering::Equal => self.tds.hedge_starting_nodes[self.idx() - 2],
Ordering::Greater | Ordering::Less => self.tds.hedge_starting_nodes[self.idx() + 1], }
}
pub fn next(&self) -> HedgeIterator<'a> {
match (self.idx() % 3).cmp(&2) {
Ordering::Equal => Self::new(self.tds, self.idx() - 2),
Ordering::Greater | Ordering::Less => Self::new(self.tds, self.idx() + 1),
}
}
pub fn twin(&self) -> HedgeIterator<'a> {
Self::new(self.tds, self.tds.hedge_twins[self.idx()])
}
pub fn prev(&self) -> HedgeIterator<'a> {
match (self.idx() % 3).cmp(&0) {
Ordering::Equal => Self::new(self.tds, self.idx() + 2),
Ordering::Greater | Ordering::Less => Self::new(self.tds, self.idx() - 1),
}
}
pub fn tri(&self) -> TriIterator<'a> {
TriIterator::new(self.tds, self.idx() / 3)
}
}
impl fmt::Display for HedgeIterator<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Edge {}: {} -> {}",
self.idx(),
self.starting_node(),
self.end_node()
)
}
}