graphics_rs/shapes/
circle.rs1use crate::traits::{canvas::Canvas, is_color::IsColor, shape::Shape};
2
3pub struct Circle {
4 cx: i64,
5 cy: i64,
6 radius: usize,
7}
8
9impl Circle {
10 pub fn new(cx: i64, cy: i64, radius: usize) -> Self {
11 Self { cx, cy, radius }
12 }
13
14 fn get_circle_rect_area(&self, canvas: &mut impl Canvas) -> (i64, i64, i64, i64) {
15 let x1 = canvas.clamp_col(self.cx - self.radius as i64);
16 let x2 = canvas.clamp_col(self.cx + self.radius as i64);
17 let y1 = canvas.clamp_row(self.cy - self.radius as i64);
18 let y2 = canvas.clamp_row(self.cy + self.radius as i64);
19
20 (x1, x2, y1, y2)
21 }
22
23 fn draw_antialiased(&mut self, canvas: &mut impl Canvas, x1: i64, x2: i64, y1: i64, y2: i64) {
24 for row in y1..=y2 {
25 for col in x1..=x2 {
26 let resolution = canvas.resolution();
27
28 let mut count: usize = 0;
29 for i in 0..resolution as i64 {
30 for j in 0..resolution as i64 {
31 let res1 = (resolution + 1) as i64;
32 let dx = col * res1 * 2 + 2 + i * 2 - res1 * self.cx as i64 * 2 - res1;
33 let dy = row * res1 * 2 + 2 + j * 2 - res1 * self.cy as i64 * 2 - res1;
34
35 if dx.pow(2) + dy.pow(2) <= res1.pow(2) * (self.radius as i64).pow(2) * 4 {
36 count += 1;
37 }
38 }
39 }
40
41 let alpha = canvas.color().alpha() as f64 * count as f64 / resolution.pow(2) as f64;
42 let color = canvas
43 .color()
44 .with_alpha(alpha.clamp(0f64, u8::MAX as f64) as u8);
45 canvas.set_pixel_color(row as usize, col as usize, color);
46 }
47 }
48 }
49
50 fn draw_simple(&mut self, canvas: &mut impl Canvas, x1: i64, x2: i64, y1: i64, y2: i64) {
51 for row in y1..=y2 {
52 for col in x1..=x2 {
53 let valid_pixel = row.abs_diff(self.cy).pow(2) + col.abs_diff(self.cx).pow(2)
54 <= self.radius.pow(2) as u64;
55
56 if valid_pixel {
57 if canvas.fits_inside(row, col) {
58 canvas.set_pixel(row as usize, col as usize);
59 }
60 }
61 }
62 }
63 }
64}
65
66impl Shape for Circle {
67 fn draw_to(&mut self, canvas: &mut impl Canvas) {
68 let (x1, x2, y1, y2) = self.get_circle_rect_area(canvas);
69
70 if canvas.antialiasing() {
71 self.draw_antialiased(canvas, x1, x2, y1, y2);
72 } else {
73 self.draw_simple(canvas, x1, x2, y1, y2);
74 }
75 }
76}