use super::{ChainDirection, MonotoneTriangulator};
use crate::{
math::{IndexType, Polygon, Vector2D},
mesh::{IndexedVertex2D, Triangulation},
prelude::try_min_weight_small_direct,
tesselate::minweight_dynamic_direct,
};
#[derive(Debug, Clone)]
pub struct DynamicMonoTriangulator<V: IndexType, Vec2: Vector2D, Poly: Polygon<Vec2>> {
left: Vec<usize>,
right: Vec<usize>,
d: ChainDirection,
phantom: std::marker::PhantomData<(V, Vec2, Poly)>,
}
impl<V: IndexType, Vec2: Vector2D, Poly: Polygon<Vec2>> MonotoneTriangulator
for DynamicMonoTriangulator<V, Vec2, Poly>
{
type V = V;
type Vec2 = Vec2;
fn new(v: usize) -> Self {
DynamicMonoTriangulator {
left: vec![v],
right: vec![],
d: ChainDirection::None,
phantom: std::marker::PhantomData,
}
}
fn last_opposite(&self) -> usize {
if self.d == ChainDirection::None {
let l = self.left.len();
let r = self.right.len();
assert!((l == 1 && r == 0) || (l == 0 && r == 1));
if l == 1 {
self.left[0]
} else {
self.right[0]
}
} else if self.d == ChainDirection::Right {
assert!(self.left.len() > 0);
self.left[self.left.len() - 1]
} else {
assert!(self.right.len() > 0);
self.right[self.right.len() - 1]
}
}
fn is_right(&self) -> bool {
self.d != ChainDirection::Left
}
fn sanity_check(&self, _: usize, _: usize, _: &Option<Self>) {
}
#[inline]
fn right(&mut self, value: usize, _: &mut Triangulation<V>, _: &Vec<IndexedVertex2D<V, Vec2>>) {
self.right.push(value);
self.d = ChainDirection::Right;
}
#[inline]
fn left(&mut self, value: usize, _: &mut Triangulation<V>, _: &Vec<IndexedVertex2D<V, Vec2>>) {
self.left.push(value);
self.d = ChainDirection::Left;
}
fn finish(&mut self, indices: &mut Triangulation<V>, vec2s: &Vec<IndexedVertex2D<V, Vec2>>) {
let mut vs = Vec::<IndexedVertex2D<V, Vec2>>::new();
for &v in self.left.iter() {
vs.push(vec2s[v]);
}
for &v in self.right.iter().rev() {
vs.push(vec2s[v]);
}
if !try_min_weight_small_direct::<V, Vec2, Poly>(&vs, indices) {
minweight_dynamic_direct::<V, Vec2, Poly>(&vs, indices);
}
}
}