graphics/
ellipse.rs

1//! Draw ellipse
2
3pub use crate::rectangle::{centered, centered_square as circle};
4use crate::{
5    math::Matrix2d,
6    triangulation,
7    types::{Color, Radius, Rectangle, Resolution},
8    DrawState, Graphics,
9};
10
11/// Ellipse border
12#[derive(Copy, Clone)]
13pub struct Border {
14    /// The border color
15    pub color: Color,
16    /// The border radius
17    pub radius: Radius,
18}
19
20/// An ellipse with filled color
21#[derive(Copy, Clone)]
22pub struct Ellipse {
23    /// The ellipse color
24    pub color: Color,
25    /// The ellipse border
26    pub border: Option<Border>,
27    /// The resolution for the shape, 360 degrees.
28    pub resolution: Resolution,
29}
30
31impl Ellipse {
32    /// Creates a new ellipse
33    pub fn new(color: Color) -> Ellipse {
34        Ellipse {
35            color,
36            border: None,
37            resolution: 128,
38        }
39    }
40
41    /// Creates a new ellipse border
42    pub fn new_border(color: Color, radius: Radius) -> Ellipse {
43        Ellipse {
44            color: [0.0; 4],
45            border: Some(Border { color, radius }),
46            resolution: 128,
47        }
48    }
49
50    /// Sets ellipse color.
51    pub fn color(mut self, value: Color) -> Self {
52        self.color = value;
53        self
54    }
55
56    /// Sets ellipse border.
57    pub fn border(mut self, value: Border) -> Self {
58        self.border = Some(value);
59        self
60    }
61
62    /// Sets optional ellipse border.
63    pub fn maybe_border(mut self, value: Option<Border>) -> Self {
64        self.border = value;
65        self
66    }
67
68    /// Sets resolution of the ellipse smoothness.
69    pub fn resolution(mut self, value: Resolution) -> Self {
70        self.resolution = value;
71        self
72    }
73
74    /// Draws ellipse by corners using default method.
75    #[inline(always)]
76    pub fn draw_from_to<P: Into<crate::types::Vec2d>, G>(
77        &self,
78        from: P,
79        to: P,
80        draw_state: &DrawState,
81        transform: Matrix2d,
82        g: &mut G,
83    ) where
84        G: Graphics,
85    {
86        use crate::rectangle::rectangle_by_corners;
87
88        let from = from.into();
89        let to = to.into();
90        g.ellipse(
91            self,
92            rectangle_by_corners(from[0], from[1], to[0], to[1]),
93            draw_state,
94            transform,
95        );
96    }
97
98    /// Draws ellipse using default method.
99    #[inline(always)]
100    pub fn draw<R: Into<Rectangle>, G>(
101        &self,
102        rectangle: R,
103        draw_state: &DrawState,
104        transform: Matrix2d,
105        g: &mut G,
106    ) where
107        G: Graphics,
108    {
109        g.ellipse(self, rectangle, draw_state, transform);
110    }
111
112    /// Draws ellipse using triangulation.
113    pub fn draw_tri<R: Into<Rectangle>, G>(
114        &self,
115        rectangle: R,
116        draw_state: &DrawState,
117        transform: Matrix2d,
118        g: &mut G,
119    ) where
120        G: Graphics,
121    {
122        let rectangle = rectangle.into();
123        g.tri_list(draw_state, &self.color, |f| {
124            triangulation::with_ellipse_tri_list(
125                self.resolution,
126                transform,
127                rectangle,
128                |vertices| f(vertices),
129            )
130        });
131
132        if let Some(Border {
133            color,
134            radius: border_radius,
135        }) = self.border
136        {
137            g.tri_list(draw_state, &color, |f| {
138                triangulation::with_ellipse_border_tri_list(
139                    self.resolution,
140                    transform,
141                    rectangle,
142                    border_radius,
143                    |vertices| f(vertices),
144                )
145            });
146        }
147    }
148}
149
150#[cfg(test)]
151mod test {
152    use super::*;
153
154    #[test]
155    fn test_ellipse() {
156        let _ellipse = Ellipse::new([1.0; 4]).color([0.0; 4]).border(Border {
157            color: [1.0; 4],
158            radius: 3.0,
159        });
160    }
161}