Skip to main content

ranim_items/vitem/geometry/
circle.rs

1use std::f64::consts::PI;
2
3use color::{AlphaColor, Srgb};
4use glam::DVec3;
5use ranim_core::{
6    Extract,
7    anchor::Aabb,
8    color,
9    core_item::CoreItem,
10    glam,
11    traits::{FillColor, Opacity, StrokeColor, With},
12};
13
14use crate::vitem::{DEFAULT_STROKE_WIDTH, VItem};
15
16use super::Arc;
17
18/// A circle centered at the origin in the XY plane.
19#[derive(Clone, Debug, ranim_macros::Interpolatable)]
20pub struct Circle {
21    /// Radius.
22    pub radius: f64,
23    /// Stroke rgba.
24    pub stroke_rgba: AlphaColor<Srgb>,
25    /// Stroke width.
26    pub stroke_width: f32,
27    /// Fill rgba.
28    pub fill_rgba: AlphaColor<Srgb>,
29}
30
31impl Circle {
32    /// Creates a circle with the given radius.
33    pub fn new(radius: f64) -> Self {
34        Self {
35            radius,
36            stroke_rgba: AlphaColor::WHITE,
37            stroke_width: DEFAULT_STROKE_WIDTH,
38            fill_rgba: AlphaColor::TRANSPARENT,
39        }
40    }
41
42    /// Scales the intrinsic radius.
43    pub fn scale(&mut self, scale: f64) -> &mut Self {
44        self.radius *= scale;
45        self
46    }
47}
48
49impl Aabb for Circle {
50    fn aabb(&self) -> [DVec3; 2] {
51        let r = DVec3::new(self.radius, self.radius, 0.0);
52        [-r, r].aabb()
53    }
54}
55
56impl Opacity for Circle {
57    fn set_opacity(&mut self, opacity: f32) -> &mut Self {
58        self.stroke_rgba = self.stroke_rgba.with_alpha(opacity);
59        self.fill_rgba = self.fill_rgba.with_alpha(opacity);
60        self
61    }
62}
63
64impl StrokeColor for Circle {
65    fn stroke_color(&self) -> AlphaColor<Srgb> {
66        self.stroke_rgba
67    }
68    fn set_stroke_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
69        self.stroke_rgba = color;
70        self
71    }
72    fn set_stroke_opacity(&mut self, opacity: f32) -> &mut Self {
73        self.stroke_rgba = self.stroke_rgba.with_alpha(opacity);
74        self
75    }
76}
77
78impl FillColor for Circle {
79    fn fill_color(&self) -> AlphaColor<Srgb> {
80        self.fill_rgba
81    }
82    fn set_fill_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
83        self.fill_rgba = color;
84        self
85    }
86    fn set_fill_opacity(&mut self, opacity: f32) -> &mut Self {
87        self.fill_rgba = self.fill_rgba.with_alpha(opacity);
88        self
89    }
90}
91
92impl From<Circle> for Arc {
93    fn from(value: Circle) -> Self {
94        let Circle {
95            radius,
96            stroke_rgba,
97            stroke_width,
98            ..
99        } = value;
100        Self {
101            radius,
102            angle: 2.0 * PI,
103            stroke_rgba,
104            stroke_width,
105        }
106    }
107}
108
109impl From<Circle> for VItem {
110    fn from(value: Circle) -> Self {
111        let fill_rgba = value.fill_rgba;
112        VItem::from(Arc::from(value)).with(|item| {
113            item.set_fill_color(fill_rgba);
114        })
115    }
116}
117
118impl Extract for Circle {
119    type Target = CoreItem;
120    fn extract_into(&self, buf: &mut Vec<Self::Target>) {
121        VItem::from(self.clone()).extract_into(buf);
122    }
123}