genmesh/
triangulate.rs

1use std::collections::VecDeque;
2
3use Polygon::{PolyQuad, PolyTri};
4use {Polygon, Quad, Triangle};
5
6/// provides a way to convert a polygon down to triangles
7pub trait EmitTriangles {
8    /// The content of each point in the face
9    type Vertex;
10
11    /// convert a polygon to one or more triangles, each triangle
12    /// is returned by calling `emit`
13    fn emit_triangles<F>(&self, F)
14    where
15        F: FnMut(Triangle<Self::Vertex>);
16}
17
18impl<T: Clone> EmitTriangles for Quad<T> {
19    type Vertex = T;
20
21    fn emit_triangles<F>(&self, mut emit: F)
22    where
23        F: FnMut(Triangle<T>),
24    {
25        let &Quad {
26            ref x,
27            ref y,
28            ref z,
29            ref w,
30        } = self;
31        emit(Triangle::new(x.clone(), y.clone(), z.clone()));
32        emit(Triangle::new(z.clone(), w.clone(), x.clone()));
33    }
34}
35
36impl<T: Clone> EmitTriangles for Triangle<T> {
37    type Vertex = T;
38
39    fn emit_triangles<F>(&self, mut emit: F)
40    where
41        F: FnMut(Triangle<T>),
42    {
43        emit(self.clone());
44    }
45}
46
47impl<T: Clone> EmitTriangles for Polygon<T> {
48    type Vertex = T;
49
50    fn emit_triangles<F>(&self, emit: F)
51    where
52        F: FnMut(Triangle<T>),
53    {
54        match self {
55            &PolyTri(ref t) => t.emit_triangles(emit),
56            &PolyQuad(ref q) => q.emit_triangles(emit),
57        }
58    }
59}
60
61/// `Triangluate` is a easy to to convert any Polygon stream to
62/// a stream of triangles. This is useful since Quads and other geometry
63/// are not supported by modern graphics pipelines like OpenGL.
64pub trait Triangulate<T, V> {
65    /// convert a stream of Polygons to a stream of triangles
66    fn triangulate(self) -> TriangulateIterator<T, V>;
67}
68
69impl<V, P: EmitTriangles<Vertex = V>, T: Iterator<Item = P>> Triangulate<T, V> for T {
70    fn triangulate(self) -> TriangulateIterator<T, V> {
71        TriangulateIterator::new(self)
72    }
73}
74
75/// Used to iterator of polygons into a iterator of triangles
76pub struct TriangulateIterator<SRC, V> {
77    source: SRC,
78    buffer: VecDeque<Triangle<V>>,
79}
80
81impl<V, U: EmitTriangles<Vertex = V>, SRC: Iterator<Item = U>> TriangulateIterator<SRC, V> {
82    fn new(src: SRC) -> TriangulateIterator<SRC, V> {
83        TriangulateIterator {
84            source: src,
85            buffer: VecDeque::new(),
86        }
87    }
88}
89
90impl<V, U: EmitTriangles<Vertex = V>, SRC: Iterator<Item = U>> Iterator
91    for TriangulateIterator<SRC, V>
92{
93    type Item = Triangle<V>;
94
95    fn size_hint(&self) -> (usize, Option<usize>) {
96        let (n, _) = self.source.size_hint();
97        (n, None)
98    }
99
100    fn next(&mut self) -> Option<Self::Item> {
101        loop {
102            match self.buffer.pop_front() {
103                Some(v) => return Some(v),
104                None => (),
105            }
106
107            match self.source.next() {
108                Some(p) => p.emit_triangles(|v| self.buffer.push_back(v)),
109                None => return None,
110            }
111        }
112    }
113}