1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
use crate::geom::tri::{self, Tri};
use crate::geom::{Cuboid, Rect, Vertex, Vertex2d, Vertex3d};
/// A simple type wrapper around a list of points that describe a polygon.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Polygon<I> {
/// The iterator yielding all points in the polygon.
pub points: I,
}
/// An iterator yielding indices into a polygon's vertices required to triangulate the polygon.
#[derive(Clone, Debug)]
pub struct TriangleIndices {
index: usize,
n_points: usize,
}
impl<I> Polygon<I>
where
I: Iterator,
{
/// Construct a new polygon from the given list of points describing its vertices.
pub fn new<P>(points: P) -> Self
where
P: IntoIterator<IntoIter = I, Item = I::Item>,
{
let points = points.into_iter();
Polygon { points }
}
/// Triangulate the polygon given as a list of `Point`s describing its sides.
///
/// Returns `None` if the polygon's iterator yields less than two points.
pub fn triangles(self) -> Option<Triangles<I>> {
triangles(self.points)
}
/// Returns `Some` with the touched triangle if the given `Point` is over the polygon described
/// by the given series of points.
///
/// This uses the `triangles` function internally.
pub fn contains(self, p: &I::Item) -> Option<Tri<I::Item>>
where
I::Item: Vertex2d,
{
contains(self.points, p)
}
/// The `Rect` that bounds the polygon.
///
/// Returns `None` if the polygon's point iterator is empty.
pub fn bounding_rect(self) -> Option<Rect<<I::Item as Vertex>::Scalar>>
where
I::Item: Vertex2d,
{
super::bounding_rect(self.points)
}
/// The `Cuboid that bounds the polygon.
///
/// Returns `None` if the polygon's point iterator is empty.
pub fn bounding_cuboid(self) -> Option<Cuboid<<I::Item as Vertex>::Scalar>>
where
I::Item: Vertex3d,
{
super::bounding_cuboid(self.points)
}
}
/// An iterator that triangulates a polygon represented by a sequence of points describing its
/// edges.
#[derive(Clone, Debug)]
pub struct Triangles<I>
where
I: Iterator,
{
first: I::Item,
prev: I::Item,
points: I,
}
/// Triangulate the polygon given as a list of `Point`s describing its sides.
///
/// Returns `None` if the given iterator yields less than two points.
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,
})
}
/// An iterator yielding indices into a polygon's vertices required to triangulate the polygon.
pub fn triangle_indices(n_points: usize) -> TriangleIndices {
let index = 0;
TriangleIndices { index, n_points }
}
/// Returns `Some` with the touched triangle if the given `Point` is over the polygon described by
/// the given series of points.
///
/// This uses the `triangles` function internally.
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),
}
}
}