``` 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
```
```// Regular ngons.

use crate::{Canvas, ClosedPath, FlatIterPath, Paint, Scale, Translate, P2, V2};

#[derive(Copy, Clone, Debug)]
pub struct Ngon {
phase: f32,
r: f32,
n: usize,
c: P2,
i: usize,
}

impl Ngon {
pub fn new(c: P2, n: usize, r: f32) -> Self {
Self {
phase: 0.,
r,
n,
c,
i: 0,
}
}

pub fn triangle(c: P2, r: f32) -> Self { Self::new(c, 3, r) }

pub fn square(c: P2, r: f32) -> Self {
let mut diamond = Self::diamond(c, r);
diamond.phase -= std::f32::consts::PI / 4.;
diamond
}

pub fn diamond(c: P2, r: f32) -> Self { Self::new(c, 4, r) }

pub fn rotate(&mut self, phase: f32) { self.phase += phase; }
}

impl Iterator for Ngon {
type Item = P2;

fn next(&mut self) -> Option<Self::Item> {
if self.i == self.n {
return None;
}

let completion = self.i as f32 / self.n as f32;
let theta = (completion * std::f32::consts::PI * 2.0) + self.phase;
self.i += 1;

Some(P2::new(
self.c.x + theta.sin() * self.r,
self.c.y + theta.cos() * self.r,
))
}
}

impl Scale for Ngon {
fn scale(self, factor: f32) -> Self {
Self {
r: self.r * factor,
..self
}
}
}

impl Translate for Ngon {
fn translate(self, translation: V2) -> Self {
Self {
c: self.c + translation,
..self
}
}
}

impl Paint for Ngon {
fn paint(&self, comp: &mut Canvas) { comp.paint(ClosedPath::from(FlatIterPath::from(*self))) }
}
```