use axiolid_core::Point2;
use crate::Constraint;
pub(crate) const NO_HALFEDGE: u32 = u32::MAX;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum TriangulationError {
TooFewPoints,
AllPointsCollinear,
VertexUnplaceable {
index: u32,
},
ConstraintOutOfRange {
index: u32,
},
CrossingConstraints {
a: u32,
b: u32,
},
}
impl core::fmt::Display for TriangulationError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::TooFewPoints => write!(f, "a triangulation needs at least three points"),
Self::AllPointsCollinear => write!(f, "every input point is collinear"),
Self::VertexUnplaceable { index } => {
write!(f, "vertex {index} could not be placed in any triangle")
}
Self::ConstraintOutOfRange { index } => {
write!(f, "constraint references out-of-range vertex {index}")
}
Self::CrossingConstraints { a, b } => {
write!(f, "constraint ({a}, {b}) crosses another constraint")
}
}
}
}
impl core::error::Error for TriangulationError {}
#[derive(Debug, Clone)]
pub struct Triangulation {
pub(crate) points: Vec<Point2>,
pub(crate) triangles: Vec<u32>,
pub(crate) halfedges: Vec<u32>,
pub(crate) constraints: Vec<Constraint>,
}
impl Triangulation {
#[must_use]
pub fn triangles(&self) -> &[u32] {
&self.triangles
}
#[must_use]
pub fn points(&self) -> &[Point2] {
&self.points
}
#[must_use]
pub fn triangle_count(&self) -> usize {
self.triangles.len() / 3
}
#[must_use]
pub fn constraints(&self) -> &[Constraint] {
&self.constraints
}
pub(crate) fn is_constrained(&self, a: u32, b: u32) -> bool {
self.constraints
.binary_search(&Constraint::new(a, b))
.is_ok()
}
}