Skip to main content

dot_canvas/
circle.rs

1use crate::Shape;
2
3pub struct Circle {
4    pub x: f32,
5    pub y: f32,
6    pub radius: f32,
7}
8
9impl Circle {
10    pub fn new(x: f32, y: f32, radius: f32) -> Self {
11        Circle { x, y, radius }
12    }
13}
14
15impl<'a> Shape<'a> for Circle {
16    fn points(&'a self) -> Box<dyn Iterator<Item = (f32, f32)> + 'a> {
17        let mut x = self.radius;
18        let mut y = 0.0;
19        let mut err = 0.0;
20
21        let inc = 0.25;
22
23        let mut points = vec![];
24
25        while x >= y {
26            points.push((self.x + x, self.y + y));
27            points.push((self.x + y, self.y + x));
28            points.push((self.x - y, self.y + x));
29            points.push((self.x - x, self.y + y));
30            points.push((self.x - x, self.y - y));
31            points.push((self.x - y, self.y - x));
32            points.push((self.x + y, self.y - x));
33            points.push((self.x + x, self.y - y));
34
35            if err <= 0.0 {
36                y += inc;
37                err += 2.0 * y + inc;
38            }
39
40            if err > 0.0 {
41                x -= inc;
42                err -= 2.0 * x + inc;
43            }
44        }
45        Box::new(points.into_iter())
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52    use crate::*;
53
54    #[test]
55    fn draw_circle4() {
56        let width = 10.0;
57        let height = 10.0;
58        let mut context = Context::new(width, height);
59
60        context.draw(&Circle {
61            x: 5.0,
62            y: 5.0,
63            radius: 4.0,
64        });
65        let result = context.to_string();
66        println!("{}", result);
67
68        let expected = [
69            "                    ",
70            "      ⣀⠤⠒⠒⠑⠒⠢⢄⡀     ",
71            "    ⡠⠊        ⠈⠢⡀   ",
72            "   ⡜            ⠘⡄  ",
73            "  ⢸              ⢸  ",
74            "  ⢱              ⢰⠁ ",
75            "  ⠈⢆            ⢀⠎  ",
76            "   ⠈⠢⡀         ⡠⠊   ",
77            "     ⠈⠒⠤⣀⣀⢀⣀⡠⠔⠊     ",
78            "          ⠁         ",
79        ];
80        assert_eq!(result, expected.join("\n"));
81    }
82
83    #[test]
84    fn draw_dynamic() {
85        let radius = 10.0;
86        let mut context = Context::new(radius * 2.0, radius * 2.0);
87
88        context.draw(&Circle {
89            x: radius,
90            y: radius,
91            radius,
92        });
93        let result = context.to_string();
94        println!("{}", result);
95
96        let expected = [
97            "             ⣀⡠⠤⠔⠒⠒⠒⠑⠒⠒⠒⠤⠤⣀⡀            ",
98            "         ⢀⠤⠒⠉              ⠈⠑⠢⢄         ",
99            "       ⡠⠊⠁                     ⠉⠢⡀      ",
100            "     ⡠⠊                          ⠈⠢⡀    ",
101            "   ⢀⠎                              ⠈⢆   ",
102            "  ⢠⠃                                 ⢣  ",
103            " ⢠⠃                                   ⢣ ",
104            " ⡎                                    ⠈⡆",
105            "⢰⠁                                     ⢱",
106            "⢸                                      ⢸",
107            "⢱                                      ⢰",
108            "⢸                                      ⢸",
109            " ⡇                                     ⡇",
110            " ⠸⡀                                   ⡸ ",
111            "  ⠱⡀                                 ⡰⠁ ",
112            "   ⠑⡄                               ⡔⠁  ",
113            "    ⠈⠢⡀                           ⡠⠊    ",
114            "      ⠈⠢⡀                       ⡠⠊      ",
115            "        ⠈⠑⠤⣀                ⢀⡠⠔⠉        ",
116            "            ⠉⠒⠢⠤⢄⣀⣀⣀⢀⣀⣀⣀⠤⠤⠒⠊⠁           ",
117        ];
118        assert_eq!(result, expected.join("\n"));
119    }
120}