nannou_core/geom/
quad.rs

1use crate::geom::{tri, vertex, Cuboid, Range, Rect, Tri, Vertex, Vertex2d, Vertex3d};
2use core::ops::{Deref, Index};
3
4/// The number of vertices in a quad.
5pub const NUM_VERTICES: u8 = 4;
6
7/// The number of triangles that make up a quad.
8pub const NUM_TRIANGLES: u8 = 2;
9
10/// The same as `triangles`, but instead returns the vertex indices for each triangle.
11pub const TRIANGLE_INDEX_TRIS: TrianglesIndexTris = [[0, 1, 2], [0, 2, 3]];
12pub type TrianglesIndexTris = [[usize; tri::NUM_VERTICES as usize]; NUM_TRIANGLES as usize];
13
14/// The number of indices used to describe each triangle in the quad.
15pub const NUM_TRIANGLE_INDICES: u8 = 6;
16
17/// The same as `triangles`, but instead returns the vertex indices for each triangle.
18pub const TRIANGLE_INDICES: [usize; NUM_TRIANGLE_INDICES as usize] = [0, 1, 2, 0, 2, 3];
19
20/// A quad represented by its four vertices.
21#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
22pub struct Quad<V = vertex::Default>(pub [V; NUM_VERTICES as usize]);
23
24/// An `Iterator` yielding the two triangles that make up a quad.
25#[derive(Clone, Debug)]
26pub struct Triangles<V = vertex::Default> {
27    a: Option<Tri<V>>,
28    b: Option<Tri<V>>,
29}
30
31/// A simple iterator yielding each vertex in a `Quad`.
32#[derive(Clone, Debug)]
33pub struct Vertices<V = vertex::Default> {
34    quad: Quad<V>,
35    index: u8,
36}
37
38impl<V> Quad<V>
39where
40    V: Vertex,
41{
42    /// Produce an iterator yielding each vertex in the `Quad`.
43    pub fn vertices(self) -> Vertices<V> {
44        vertices(self)
45    }
46
47    /// Produce the centroid of the quad, aka the "mean"/"average" vertex.
48    pub fn centroid(&self) -> V
49    where
50        V: vertex::Average,
51    {
52        centroid(self)
53    }
54
55    /// Triangulates the given quad, represented by four points that describe its edges in either
56    /// clockwise or anti-clockwise order.
57    ///
58    /// # Example
59    ///
60    /// The following rectangle
61    ///
62    /// ```ignore
63    ///  a        b
64    ///   --------
65    ///   |      |
66    ///   |      |
67    ///   |      |
68    ///   --------
69    ///  d        c
70    ///
71    /// ```
72    ///
73    /// given as
74    ///
75    /// ```ignore
76    /// triangles([a, b, c, d])
77    /// ```
78    ///
79    /// returns
80    ///
81    /// ```ignore
82    /// (Tri([a, b, c]), Tri([a, c, d]))
83    /// ```
84    ///
85    /// Here's a basic code example:
86    ///
87    /// ```
88    /// # use nannou_core as nannou;
89    /// use nannou::geom::{self, pt2, Quad, Tri};
90    ///
91    /// fn main() {
92    ///     let a = pt2(0.0, 1.0);
93    ///     let b = pt2(1.0, 1.0);
94    ///     let c = pt2(1.0, 0.0);
95    ///     let d = pt2(0.0, 0.0);
96    ///     let quad = Quad([a, b, c, d]);
97    ///     let triangles = geom::quad::triangles(&quad);
98    ///     assert_eq!(triangles, (Tri([a, b, c]), Tri([a, c, d])));
99    /// }
100    /// ```
101    #[inline]
102    pub fn triangles(&self) -> (Tri<V>, Tri<V>) {
103        triangles(self)
104    }
105
106    /// The same as `triangles` but provided as an **Iterator**.
107    pub fn triangles_iter(&self) -> Triangles<V> {
108        triangles_iter(self)
109    }
110
111    /// The bounding `Rect` of the quad.
112    pub fn bounding_rect(self) -> Rect<V::Scalar>
113    where
114        V: Vertex2d,
115    {
116        let (a, b, c, d) = self.into();
117        let ([ax, ay], b, c, d) = (a.point2(), b.point2(), c.point2(), d.point2());
118        let rect = Rect {
119            x: Range::new(ax, ax),
120            y: Range::new(ay, ay),
121        };
122        rect.stretch_to_point(b)
123            .stretch_to_point(c)
124            .stretch_to_point(d)
125    }
126
127    /// The bounding `Rect` of the triangle.
128    pub fn bounding_cuboid(self) -> Cuboid<V::Scalar>
129    where
130        V: Vertex3d,
131    {
132        let (a, b, c, d) = self.into();
133        let ([ax, ay, az], b, c, d) = (a.point3(), b.point3(), c.point3(), d.point3());
134        let cuboid = Cuboid {
135            x: Range::new(ax, ax),
136            y: Range::new(ay, ay),
137            z: Range::new(az, az),
138        };
139        cuboid
140            .stretch_to_point(b)
141            .stretch_to_point(c)
142            .stretch_to_point(d)
143    }
144
145    /// Map the **Quad**'s vertices to a new type.
146    pub fn map_vertices<F, V2>(self, mut map: F) -> Quad<V2>
147    where
148        F: FnMut(V) -> V2,
149    {
150        let (a, b, c, d) = self.into();
151        Quad([map(a), map(b), map(c), map(d)])
152    }
153}
154
155/// Produce an iterator yielding each vertex in the given **Quad**.
156pub fn vertices<V>(quad: Quad<V>) -> Vertices<V> {
157    let index = 0;
158    Vertices { quad, index }
159}
160
161/// Produce the centroid of the quad, aka the "mean"/"average" vertex.
162pub fn centroid<V>(quad: &Quad<V>) -> V
163where
164    V: vertex::Average,
165{
166    crate::geom::centroid(quad.iter().cloned()).unwrap()
167}
168
169/// Triangulates the given quad, represented by four points that describe its edges in either
170/// clockwise or anti-clockwise order.
171///
172/// # Example
173///
174/// The following rectangle
175///
176/// ```ignore
177///
178///  a        b
179///   --------
180///   |      |
181///   |      |
182///   |      |
183///   --------
184///  d        c
185///
186/// ```
187///
188/// given as
189///
190/// ```ignore
191/// triangles([a, b, c, d])
192/// ```
193///
194/// returns
195///
196/// ```ignore
197/// (Tri([a, b, c]), Tri([a, c, d]))
198/// ```
199///
200/// Here's a basic code example:
201///
202/// ```
203/// # use nannou_core as nannou;
204/// use nannou::geom::{self, pt2, Quad, Tri};
205///
206/// fn main() {
207///     let a = pt2(0.0, 1.0);
208///     let b = pt2(1.0, 1.0);
209///     let c = pt2(1.0, 0.0);
210///     let d = pt2(0.0, 0.0);
211///     let quad = Quad([a, b, c, d]);
212///     let triangles = geom::quad::triangles(&quad);
213///     assert_eq!(triangles, (Tri([a, b, c]), Tri([a, c, d])));
214/// }
215/// ```
216#[inline]
217pub fn triangles<V>(q: &Quad<V>) -> (Tri<V>, Tri<V>)
218where
219    V: Vertex,
220{
221    let a = Tri::from_index_tri(&q.0, &TRIANGLE_INDEX_TRIS[0]);
222    let b = Tri::from_index_tri(&q.0, &TRIANGLE_INDEX_TRIS[1]);
223    (a, b)
224}
225
226/// The same as `triangles` but provided as an `Iterator`.
227pub fn triangles_iter<V>(points: &Quad<V>) -> Triangles<V>
228where
229    V: Vertex,
230{
231    let (a, b) = triangles(points);
232    Triangles {
233        a: Some(a),
234        b: Some(b),
235    }
236}
237
238impl<V> Iterator for Triangles<V> {
239    type Item = Tri<V>;
240    fn next(&mut self) -> Option<Self::Item> {
241        self.a.take().or_else(|| self.b.take())
242    }
243    fn size_hint(&self) -> (usize, Option<usize>) {
244        let len = self.len();
245        (len, Some(len))
246    }
247}
248
249impl<V> DoubleEndedIterator for Triangles<V> {
250    fn next_back(&mut self) -> Option<Self::Item> {
251        self.b.take().or_else(|| self.a.take())
252    }
253}
254
255impl<V> ExactSizeIterator for Triangles<V> {
256    fn len(&self) -> usize {
257        match (&self.a, &self.b) {
258            (&Some(_), &Some(_)) => 2,
259            (&None, &Some(_)) => 0,
260            _ => 1,
261        }
262    }
263}
264
265impl<V> Iterator for Vertices<V>
266where
267    V: Clone,
268{
269    type Item = V;
270    fn next(&mut self) -> Option<Self::Item> {
271        if self.index < NUM_VERTICES {
272            let v = self.quad[self.index as usize].clone();
273            self.index += 1;
274            Some(v)
275        } else {
276            None
277        }
278    }
279
280    fn size_hint(&self) -> (usize, Option<usize>) {
281        let len = self.len();
282        (len, Some(len))
283    }
284}
285
286impl<V> ExactSizeIterator for Vertices<V>
287where
288    V: Clone,
289{
290    fn len(&self) -> usize {
291        NUM_VERTICES as usize - self.index as usize
292    }
293}
294
295impl<V> Deref for Quad<V> {
296    type Target = [V; NUM_VERTICES as usize];
297    fn deref(&self) -> &Self::Target {
298        &self.0
299    }
300}
301
302impl<V> From<[V; NUM_VERTICES as usize]> for Quad<V>
303where
304    V: Vertex,
305{
306    fn from(points: [V; NUM_VERTICES as usize]) -> Self {
307        Quad(points)
308    }
309}
310
311impl<V> From<(V, V, V, V)> for Quad<V>
312where
313    V: Vertex,
314{
315    fn from((a, b, c, d): (V, V, V, V)) -> Self {
316        Quad([a, b, c, d])
317    }
318}
319
320impl<V> Into<[V; NUM_VERTICES as usize]> for Quad<V>
321where
322    V: Vertex,
323{
324    fn into(self) -> [V; NUM_VERTICES as usize] {
325        self.0
326    }
327}
328
329impl<V> Into<(V, V, V, V)> for Quad<V>
330where
331    V: Vertex,
332{
333    fn into(self) -> (V, V, V, V) {
334        (self[0], self[1], self[2], self[3])
335    }
336}
337
338impl<V> AsRef<Quad<V>> for Quad<V>
339where
340    V: Vertex,
341{
342    fn as_ref(&self) -> &Quad<V> {
343        self
344    }
345}
346
347impl<V> AsRef<[V; NUM_VERTICES as usize]> for Quad<V>
348where
349    V: Vertex,
350{
351    fn as_ref(&self) -> &[V; NUM_VERTICES as usize] {
352        &self.0
353    }
354}
355
356impl<V> Index<usize> for Quad<V>
357where
358    V: Vertex,
359{
360    type Output = V;
361    fn index(&self, index: usize) -> &Self::Output {
362        &self.0[index]
363    }
364}