gon/
regular_poly.rs

1use crate::{
2    default_start_angle,
3    options::{Options, StrokeOptions},
4    tess, FreePolyBuilder, PolyBuilder, DEFAULT_RADIUS,
5};
6use gee::{Angle, Circle, Point, Rect};
7
8#[derive(Clone, Debug)]
9pub struct RegularPolyBuilder {
10    circle: Circle,
11    sides: u32,
12    start_angle: Angle,
13    options: Options,
14}
15
16impl Default for RegularPolyBuilder {
17    fn default() -> Self {
18        Self {
19            circle: Circle::from_radius(DEFAULT_RADIUS),
20            sides: 3,
21            start_angle: default_start_angle(),
22            options: Default::default(),
23        }
24    }
25}
26
27impl RegularPolyBuilder {
28    pub fn new(sides: u32) -> Self {
29        Self::default().with_sides(sides)
30    }
31
32    pub fn triangle() -> Self {
33        Self::new(3)
34    }
35
36    pub fn square() -> Self {
37        Self::new(4)
38    }
39
40    pub fn pentagon() -> Self {
41        Self::new(5)
42    }
43
44    pub fn hexagon() -> Self {
45        Self::new(6)
46    }
47
48    pub fn octagon() -> Self {
49        Self::new(8)
50    }
51
52    pub fn decagon() -> Self {
53        Self::new(10)
54    }
55
56    pub fn with_sides(mut self, sides: u32) -> Self {
57        assert!(
58            sides >= 3,
59            "regular polygons must have at least 3 sides, but this one has {}",
60            sides
61        );
62        self.sides = sides;
63        self
64    }
65
66    pub fn with_circle(mut self, circle: Circle) -> Self {
67        self.circle = circle;
68        self
69    }
70
71    pub fn with_center_and_radius(self, center: Point, radius: f32) -> Self {
72        self.with_circle(Circle::new(center, radius))
73    }
74
75    pub fn with_rotation(mut self, start_angle: impl Into<Angle>) -> Self {
76        self.start_angle = start_angle.into();
77        self
78    }
79
80    stroke!(public);
81
82    fill!();
83
84    build!();
85}
86
87impl PolyBuilder for RegularPolyBuilder {
88    fn options(&self) -> &Options {
89        &self.options
90    }
91
92    fn bounding_rect(&self) -> Rect {
93        self.circle.bounding_rect()
94    }
95
96    fn build<B: tess::path::traits::PathBuilder>(self, builder: &mut B) {
97        PolyBuilder::build(
98            FreePolyBuilder::from_parts(
99                self.circle.circle_points(self.sides, self.start_angle),
100                true,
101                Some(self.bounding_rect()),
102                self.options,
103            ),
104            builder,
105        );
106    }
107}