#![warn(missing_docs)]
pub(crate) mod contour;
pub(crate) mod predicates;
pub(crate) mod half;
pub(crate) mod hull;
pub(crate) mod indexes;
pub(crate) mod triangulate;
pub use triangulate::Triangulation;
type Point = (f64, f64);
#[derive(thiserror::Error, Debug, Eq, PartialEq)]
pub enum Error {
#[error("Point is located on a fixed edge but is not its endpoint")]
PointOnFixedEdge(usize),
#[error("There are no more points left to triangulate")]
NoMorePoints,
#[error("Fixed edges cross each other")]
CrossingFixedEdge,
#[error("input cannot be empty")]
EmptyInput,
#[error("input cannot contain NaN or infinity")]
InvalidInput,
#[error("edge must index into point array and have different src and dst")]
InvalidEdge,
#[error("contours must be closed")]
OpenContour,
#[error("too few points")]
TooFewPoints,
#[error("could not find initial seed")]
CannotInitialize,
#[error("escaped wedge when searching fixed edge")]
WedgeEscape,
}
pub fn triangulate_points(pts: &[Point]) -> Result<Vec<(usize, usize, usize)>, Error> {
let t = Triangulation::build(&pts)?;
Ok(t.triangles().collect())
}
pub fn triangulate_contours<V>(pts: &[Point], contours: &[V])
-> Result<Vec<(usize, usize, usize)>, Error>
where for<'b> &'b V: IntoIterator<Item=&'b usize>
{
let t = Triangulation::build_from_contours(&pts, contours)?;
Ok(t.triangles().collect())
}
pub fn triangulate_with_edges<'a, E>(pts: &[Point], edges: E)
-> Result<Vec<(usize, usize, usize)>, Error>
where E: IntoIterator<Item=&'a (usize, usize)> + Copy + Clone
{
let t = Triangulation::build_with_edges(&pts, edges)?;
Ok(t.triangles().collect())
}
pub fn save_debug_panic<'a, E>(pts: &[Point], edges: E, filename: &str)
-> std::io::Result<()>
where E: IntoIterator<Item=&'a (usize, usize)> + Copy + Clone + std::panic::UnwindSafe
{
let mut safe_steps = 0;
loop {
let result = std::panic::catch_unwind(move || {
let mut t = Triangulation::new_with_edges(pts, edges)
.expect("Could not build CDT triangulation");
for _ in 0..safe_steps {
t.step().expect("Step failed");
}
});
if result.is_ok() {
safe_steps += 1;
} else {
safe_steps -= 1;
break;
}
}
let mut t = Triangulation::new_with_edges(pts, edges)
.expect("Could not build CDT triangulation");
for _ in 0..safe_steps {
t.step().expect("Step failed");
}
t.save_debug_svg(filename)
}