valora/forms/
polygon.rs

1//! Polygon.
2
3use crate::{
4    Angle, Canvas, Center, Ellipse, FlatIterPath, Paint, Rect, Rotate, Scale, Subdivide, Translate,
5    P2, V2,
6};
7use arrayvec::ArrayVec;
8use itertools::Itertools;
9use std::iter::{DoubleEndedIterator, FromIterator};
10
11#[derive(Debug, Clone, PartialEq)]
12pub struct Polygon {
13    vertices: Vec<P2>,
14}
15
16impl Polygon {
17    /// Returns an iterator over the polygon's vertices.
18    pub fn vertices<'a>(&'a self) -> impl DoubleEndedIterator<Item = P2> + Clone + 'a {
19        self.vertices.iter().copied()
20    }
21
22    /// Returns an iterator over unique references to the polgyon's vertices.
23    pub fn vertices_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut P2> + 'a {
24        self.vertices.iter_mut()
25    }
26
27    /// Returns an iterator over each vertex in the form (left neighbor, vertex, right neighbor).
28    pub fn vertices_with_neighbors<'a>(&'a self) -> impl Iterator<Item = (P2, P2, P2)> + 'a {
29        let last_iter = self.vertices().rev().take(1);
30        last_iter
31            .clone()
32            .chain(self.vertices())
33            .chain(last_iter)
34            .tuple_windows()
35    }
36}
37
38impl Paint for Polygon {
39    fn paint(&self, canvas: &mut Canvas) {
40        canvas.paint(FlatIterPath::new(self.vertices(), /*closed=*/ true))
41    }
42}
43
44impl Paint for &Polygon {
45    fn paint(&self, canvas: &mut Canvas) {
46        (**self).paint(canvas);
47    }
48}
49
50impl Subdivide for Polygon {
51    fn subdivide(self) -> Self {
52        let from_start = self.vertices();
53        let skipped = self.vertices().skip(1).chain(self.vertices().take(1));
54
55        from_start
56            .zip(skipped)
57            .flat_map(|(a, b)| {
58                let midpoint = a + ((b + (a.to_vector() * -1.)) * 0.5).to_vector();
59                ArrayVec::from([a, midpoint]).into_iter()
60            })
61            .collect::<Self>()
62    }
63}
64
65impl Rotate for Polygon {
66    fn rotate(mut self, pivot: P2, theta: Angle) -> Self {
67        self.vertices_mut().for_each(|v| {
68            *v = v.rotate(pivot, theta);
69        });
70
71        self
72    }
73}
74
75impl Translate for Polygon {
76    fn translate(mut self, translation: V2) -> Self {
77        self.vertices.iter_mut().for_each(|p| *p += translation);
78        self
79    }
80}
81
82impl Center for Polygon {
83    fn center(&self) -> P2 {
84        Rect::extent(self.vertices()).center()
85    }
86}
87
88impl Scale for Polygon {
89    fn scale(mut self, factor: f32) -> Self {
90        let scale_vertex_from = |anchor: P2, v: P2| -> P2 {
91            let distance = (anchor - v).length();
92            let phase = Ellipse::circle(anchor, distance).circumphase(&v);
93            Ellipse::circle(anchor, distance * factor).circumpoint(phase)
94        };
95
96        let center = self.center();
97        self.vertices
98            .iter_mut()
99            .for_each(|p| *p = scale_vertex_from(center, *p));
100        self
101    }
102}
103
104impl<I> From<I> for Polygon
105where
106    I: Iterator<Item = P2>,
107{
108    fn from(src: I) -> Self {
109        Self {
110            vertices: src.collect(),
111        }
112    }
113}
114
115impl FromIterator<P2> for Polygon {
116    fn from_iter<T>(iter: T) -> Self
117    where
118        T: IntoIterator<Item = P2>,
119    {
120        Self {
121            vertices: iter.into_iter().collect(),
122        }
123    }
124}