use crate::geom::tri::{self, Tri};
use crate::geom::{Cuboid, Rect, Vertex, Vertex2d, Vertex3d};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Polygon<I> {
pub points: I,
}
#[derive(Clone, Debug)]
pub struct TriangleIndices {
index: usize,
n_points: usize,
}
impl<I> Polygon<I>
where
I: Iterator,
{
pub fn new<P>(points: P) -> Self
where
P: IntoIterator<IntoIter = I, Item = I::Item>,
{
let points = points.into_iter();
Polygon { points }
}
pub fn triangles(self) -> Option<Triangles<I>> {
triangles(self.points)
}
pub fn contains(self, p: &I::Item) -> Option<Tri<I::Item>>
where
I::Item: Vertex2d,
{
contains(self.points, p)
}
pub fn bounding_rect(self) -> Option<Rect<<I::Item as Vertex>::Scalar>>
where
I::Item: Vertex2d,
{
super::bounding_rect(self.points)
}
pub fn bounding_cuboid(self) -> Option<Cuboid<<I::Item as Vertex>::Scalar>>
where
I::Item: Vertex3d,
{
super::bounding_cuboid(self.points)
}
}
#[derive(Clone, Debug)]
pub struct Triangles<I>
where
I: Iterator,
{
first: I::Item,
prev: I::Item,
points: I,
}
pub fn triangles<I>(points: I) -> Option<Triangles<I::IntoIter>>
where
I: IntoIterator,
{
let mut points = points.into_iter();
let first = match points.next() {
Some(p) => p,
None => return None,
};
let prev = match points.next() {
Some(p) => p,
None => return None,
};
Some(Triangles {
first: first,
prev: prev,
points: points,
})
}
pub fn triangle_indices(n_points: usize) -> TriangleIndices {
let index = 0;
TriangleIndices { index, n_points }
}
pub fn contains<I>(points: I, point: &I::Item) -> Option<Tri<I::Item>>
where
I: IntoIterator,
I::Item: Vertex2d,
{
triangles(points).and_then(|ts| tri::iter_contains(ts, &point))
}
impl<I> Iterator for Triangles<I>
where
I: Iterator,
I::Item: Vertex,
{
type Item = Tri<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
self.points.next().map(|point| {
let t = Tri([self.first, self.prev, point]);
self.prev = point;
t
})
}
}
impl Iterator for TriangleIndices {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
let index = self.index;
let tri_index = index / 3;
if self.n_points < tri_index + 3 {
return None;
}
self.index += 1;
match index % 3 {
0 => Some(0),
remainder => Some(tri_index + remainder),
}
}
}