ranim_items/vitem/geometry/
ellipse.rs1use ranim_core::{
2 Extract,
3 color::{AlphaColor, Srgb},
4 core_item::{
5 CoreItem,
6 vitem::{Basis2d, DEFAULT_STROKE_WIDTH},
7 },
8 glam::{DVec2, DVec3},
9 traits::{
10 Aabb, Discard, FillColor, Opacity, RotateTransform, ShiftTransform, StrokeColor, With,
11 },
12};
13
14use crate::vitem::{
15 VItem,
16 geometry::{Circle, EllipticArc},
17};
18
19#[derive(Clone, Debug, ranim_macros::Interpolatable)]
21pub struct Ellipse {
22 pub basis: Basis2d,
24 pub center: DVec3,
26 pub radius: DVec2,
28
29 pub stroke_rgba: AlphaColor<Srgb>,
31 pub stroke_width: f32,
33 pub fill_rgba: AlphaColor<Srgb>,
35}
36
37impl Ellipse {
38 pub fn new(radius: DVec2) -> Self {
40 Self {
41 basis: Basis2d::default(),
42 center: DVec3::ZERO,
43 radius,
44 stroke_rgba: AlphaColor::WHITE,
45 stroke_width: DEFAULT_STROKE_WIDTH,
46 fill_rgba: AlphaColor::TRANSPARENT,
47 }
48 }
49}
50
51impl From<Circle> for Ellipse {
52 fn from(value: Circle) -> Self {
53 let Circle {
54 basis,
55 center,
56 radius,
57 stroke_rgba,
58 stroke_width,
59 fill_rgba,
60 } = value;
61 Self {
62 basis,
63 center,
64 radius: DVec2::splat(radius),
65 stroke_rgba,
66 stroke_width,
67 fill_rgba,
68 }
69 }
70}
71
72impl From<Ellipse> for VItem {
73 fn from(value: Ellipse) -> Self {
74 let fill_rgba = value.fill_rgba;
75 VItem::from(EllipticArc::from(value)).with(|item| item.set_fill_color(fill_rgba).discard())
76 }
77}
78
79impl Aabb for Ellipse {
80 fn aabb(&self) -> [DVec3; 2] {
81 let center = self.center;
82 let (u, v) = self.basis.uv();
83 let DVec2 { x: rx, y: ry } = self.radius;
84 let r = u * rx + v * ry;
85 [center - r, center + r].aabb()
86 }
87}
88
89impl ShiftTransform for Ellipse {
90 fn shift(&mut self, offset: DVec3) -> &mut Self {
91 self.center += offset;
92 self
93 }
94}
95
96impl RotateTransform for Ellipse {
97 fn rotate_on_axis(&mut self, axis: DVec3, angle: f64) -> &mut Self {
98 self.basis.rotate_on_axis(axis, angle);
99 self.center.rotate_on_axis(axis, angle);
100 self
101 }
102}
103
104impl StrokeColor for Ellipse {
105 fn stroke_color(&self) -> AlphaColor<Srgb> {
106 self.stroke_rgba
107 }
108
109 fn set_stroke_opacity(&mut self, opacity: f32) -> &mut Self {
110 self.stroke_rgba = self.stroke_rgba.with_alpha(opacity);
111 self
112 }
113
114 fn set_stroke_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
115 self.stroke_rgba = color;
116 self
117 }
118}
119
120impl FillColor for Ellipse {
121 fn fill_color(&self) -> AlphaColor<Srgb> {
122 self.fill_rgba
123 }
124
125 fn set_fill_opacity(&mut self, opacity: f32) -> &mut Self {
126 self.fill_rgba = self.fill_rgba.with_alpha(opacity);
127 self
128 }
129
130 fn set_fill_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
131 self.fill_rgba = color;
132 self
133 }
134}
135
136impl Opacity for Ellipse {
137 fn set_opacity(&mut self, opacity: f32) -> &mut Self {
138 self.set_fill_opacity(opacity).set_stroke_opacity(opacity);
139 self
140 }
141}
142
143impl Extract for Ellipse {
144 type Target = CoreItem;
145
146 fn extract_into(&self, buf: &mut Vec<Self::Target>) {
147 VItem::from(self.clone()).extract_into(buf);
148 }
149}