use crate::error::{Error, Result};
use crate::scalar::GeomScalar;
use nalgebra::Point2;
pub(crate) fn triangulate_rings<S: GeomScalar>(
outer: &[Point2<S>],
holes: &[Vec<Point2<S>>],
) -> Result<TriangulationOf<S>> {
if outer.len() < 3 {
return Err(Error::InvalidProfile(
"Profile must have at least 3 vertices".to_string(),
));
}
let mut vertices =
Vec::with_capacity((outer.len() + holes.iter().map(|h| h.len()).sum::<usize>()) * 2);
let mut points: Vec<Point2<S>> = Vec::with_capacity(vertices.capacity() / 2);
for p in outer {
vertices.push(p.x.value());
vertices.push(p.y.value());
points.push(*p);
}
let mut hole_indices = Vec::with_capacity(holes.len());
for hole in holes {
hole_indices.push(vertices.len() / 2);
for p in hole {
vertices.push(p.x.value());
vertices.push(p.y.value());
points.push(*p);
}
}
let indices = if hole_indices.is_empty() {
crate::triangulation::safe_earcut(&vertices, &[], 2).map_err(Error::TriangulationError)?
} else {
crate::triangulation::safe_earcut(&vertices, &hole_indices, 2)
.map_err(Error::TriangulationError)?
};
Ok(TriangulationOf { points, indices })
}
#[inline]
pub(crate) fn rectangle_ring<S: GeomScalar>(width: S, height: S) -> Vec<Point2<S>> {
let two = S::from_f64(2.0);
let half_w = width / two;
let half_h = height / two;
vec![
Point2::new(-half_w, -half_h),
Point2::new(half_w, -half_h),
Point2::new(half_w, half_h),
Point2::new(-half_w, half_h),
]
}
#[derive(Debug, Clone)]
pub struct TriangulationOf<S: nalgebra::Scalar> {
pub points: Vec<Point2<S>>,
pub indices: Vec<usize>,
}
pub type Triangulation = TriangulationOf<f64>;