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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Regular ngons.

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

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

impl Ngon {
    pub fn new(center: P2, n: usize, radius: f32) -> Self {
        Self {
            phase: Angle::radians(0.),
            radius,
            n,
            center,
            i: 0,
        }
    }

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

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

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

    pub fn rotate(&mut self, phase: Angle) {
        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 = Angle::radians(completion * std::f32::consts::PI * 2.0) + self.phase;
        self.i += 1;

        Some(P2::new(
            self.center.x + theta.get().sin() * self.radius,
            self.center.y + theta.get().cos() * self.radius,
        ))
    }
}

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

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

impl Rotate for Ngon {
    fn rotate(self, pivot: P2, theta: Angle) -> Self {
        Self {
            center: self.center.rotate(pivot, theta),
            phase: self.phase + theta,
            ..self
        }
    }
}

impl Paint for Ngon {
    fn paint(&self, comp: &mut Canvas) {
        comp.paint(FlatIterPath::new(*self, /*closed=*/ true))
    }
}