ratatui_widgets/canvas/
circle.rs

1use ratatui_core::style::Color;
2
3use crate::canvas::{Painter, Shape};
4#[cfg(not(feature = "std"))]
5use crate::polyfills::F64Polyfills;
6
7/// A circle with a given center and radius and with a given color
8#[derive(Debug, Default, Clone, PartialEq)]
9pub struct Circle {
10    /// `x` coordinate of the circle's center
11    pub x: f64,
12    /// `y` coordinate of the circle's center
13    pub y: f64,
14    /// Radius of the circle
15    pub radius: f64,
16    /// Color of the circle
17    pub color: Color,
18}
19
20impl Circle {
21    /// Create a new circle with the given center, radius, and color
22    pub const fn new(x: f64, y: f64, radius: f64, color: Color) -> Self {
23        Self {
24            x,
25            y,
26            radius,
27            color,
28        }
29    }
30}
31
32impl Shape for Circle {
33    fn draw(&self, painter: &mut Painter<'_, '_>) {
34        for angle in 0..360 {
35            let radians = f64::from(angle).to_radians();
36            let circle_x = self.radius.mul_add(radians.cos(), self.x);
37            let circle_y = self.radius.mul_add(radians.sin(), self.y);
38            if let Some((x, y)) = painter.get_point(circle_x, circle_y) {
39                painter.paint(x, y, self.color);
40            }
41        }
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use ratatui_core::buffer::Buffer;
48    use ratatui_core::layout::Rect;
49    use ratatui_core::style::Color;
50    use ratatui_core::symbols::Marker;
51    use ratatui_core::widgets::Widget;
52
53    use crate::canvas::{Canvas, Circle};
54
55    #[test]
56    fn test_it_draws_a_circle() {
57        let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 5));
58        let canvas = Canvas::default()
59            .paint(|ctx| {
60                ctx.draw(&Circle {
61                    x: 5.0,
62                    y: 2.0,
63                    radius: 5.0,
64                    color: Color::Reset,
65                });
66            })
67            .marker(Marker::Braille)
68            .x_bounds([-10.0, 10.0])
69            .y_bounds([-10.0, 10.0]);
70        canvas.render(buffer.area, &mut buffer);
71        let expected = Buffer::with_lines([
72            "      ⣀⣀⣀ ",
73            "     ⡞⠁ ⠈⢣",
74            "     ⢇⡀ ⢀⡼",
75            "      ⠉⠉⠉ ",
76            "          ",
77        ]);
78        assert_eq!(buffer, expected);
79    }
80}