1use 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 pub fn vertices<'a>(&'a self) -> impl DoubleEndedIterator<Item = P2> + Clone + 'a {
19 self.vertices.iter().copied()
20 }
21
22 pub fn vertices_mut<'a>(&'a mut self) -> impl DoubleEndedIterator<Item = &'a mut P2> + 'a {
24 self.vertices.iter_mut()
25 }
26
27 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(), 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}