ranim_items/vitem/geometry/
parallelogram.rs1use ranim_core::{
2 Extract,
3 color::{AlphaColor, Srgb},
4 core_item::{CoreItem, vitem::DEFAULT_STROKE_WIDTH},
5 glam::DVec3,
6 traits::{
7 Aabb, Discard, FillColor, Opacity, RotateTransform, ScaleTransform, ShiftTransform,
8 StrokeColor, StrokeWidth, With,
9 },
10 utils::bezier::PathBuilder,
11};
12
13use crate::vitem::{
14 VItem,
15 geometry::{Polygon, Rectangle, Square},
16};
17
18#[derive(Debug, Clone, ranim_macros::Interpolatable)]
20pub struct Parallelogram {
21 pub origin: DVec3,
23 pub basis: (DVec3, DVec3),
25 pub stroke_rgba: AlphaColor<Srgb>,
27 pub stroke_width: f32,
29 pub fill_rgba: AlphaColor<Srgb>,
31}
32
33impl Parallelogram {
34 pub fn new(origin: DVec3, basis: (DVec3, DVec3)) -> Self {
36 Self {
37 origin,
38 basis,
39 stroke_rgba: AlphaColor::WHITE,
40 stroke_width: DEFAULT_STROKE_WIDTH,
41 fill_rgba: AlphaColor::TRANSPARENT,
42 }
43 }
44
45 pub fn vertices(&self) -> [DVec3; 4] {
47 let &Parallelogram {
48 origin,
49 basis: (u, v),
50 ..
51 } = self;
52 [origin, origin + u, origin + u + v, origin + v]
53 }
54}
55
56impl Aabb for Parallelogram {
57 fn aabb(&self) -> [DVec3; 2] {
58 self.vertices().aabb()
59 }
60}
61
62impl ShiftTransform for Parallelogram {
63 fn shift(&mut self, offset: DVec3) -> &mut Self {
64 self.origin += offset;
65 self
66 }
67}
68
69impl RotateTransform for Parallelogram {
70 fn rotate_on_axis(&mut self, axis: DVec3, angle: f64) -> &mut Self {
71 self.origin.rotate_on_axis(axis, angle);
72 self.basis.0.rotate_on_axis(axis, angle);
73 self.basis.1.rotate_on_axis(axis, angle);
74 self
75 }
76}
77
78impl ScaleTransform for Parallelogram {
79 fn scale(&mut self, scale: DVec3) -> &mut Self {
80 self.origin.scale(scale).discard();
81 self.basis.0 *= scale;
82 self.basis.1 *= scale;
83 self
84 }
85}
86
87impl StrokeColor for Parallelogram {
88 fn stroke_color(&self) -> AlphaColor<Srgb> {
89 self.stroke_rgba
90 }
91
92 fn set_stroke_opacity(&mut self, opacity: f32) -> &mut Self {
93 self.stroke_rgba = self.stroke_rgba.with_alpha(opacity);
94 self
95 }
96
97 fn set_stroke_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
98 self.stroke_rgba = color;
99 self
100 }
101}
102
103impl FillColor for Parallelogram {
104 fn fill_color(&self) -> AlphaColor<Srgb> {
105 self.fill_rgba
106 }
107
108 fn set_fill_opacity(&mut self, opacity: f32) -> &mut Self {
109 self.fill_rgba = self.fill_rgba.with_alpha(opacity);
110 self
111 }
112
113 fn set_fill_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
114 self.fill_rgba = color;
115 self
116 }
117}
118
119impl Opacity for Parallelogram {
120 fn set_opacity(&mut self, opacity: f32) -> &mut Self {
121 self.set_stroke_opacity(opacity).set_fill_opacity(opacity);
122 self
123 }
124}
125
126impl From<Rectangle> for Parallelogram {
127 fn from(value: Rectangle) -> Self {
128 let Rectangle {
129 basis,
130 p0,
131 size,
132 stroke_rgba,
133 stroke_width,
134 fill_rgba,
135 } = value;
136 let (u, v) = basis.uv();
137 let basis = (u * size.x, v * size.y);
138 Self {
139 origin: p0,
140 basis,
141 stroke_rgba,
142 stroke_width,
143 fill_rgba,
144 }
145 }
146}
147
148impl From<Square> for Parallelogram {
149 fn from(value: Square) -> Self {
150 let Square {
151 basis,
152 center,
153 size,
154 stroke_rgba,
155 stroke_width,
156 fill_rgba,
157 } = value;
158 let (u, v) = basis.uv();
159 let basis = (u * size, v * size);
160 let origin = center - (u + v) * size / 2.;
161 Self {
162 origin,
163 basis,
164 stroke_rgba,
165 stroke_width,
166 fill_rgba,
167 }
168 }
169}
170
171impl From<Parallelogram> for Polygon {
172 fn from(value: Parallelogram) -> Self {
173 let Parallelogram {
174 stroke_rgba,
175 stroke_width,
176 fill_rgba,
177 ..
178 } = value;
179 Polygon::new(value.vertices().to_vec()).with(|item| {
180 item.set_stroke_color(stroke_rgba).set_fill_color(fill_rgba);
181 item.stroke_width = stroke_width;
182 })
183 }
184}
185
186impl From<Parallelogram> for VItem {
187 fn from(value: Parallelogram) -> Self {
188 let Parallelogram {
189 origin,
190 basis: (u, v),
191 stroke_rgba,
192 stroke_width,
193 fill_rgba,
194 } = value;
195 VItem::from_vpoints(
196 PathBuilder::new()
197 .move_to(origin)
198 .line_to(origin + u)
199 .line_to(origin + u + v)
200 .line_to(origin + v)
201 .close_path()
202 .vpoints()
203 .into(),
204 )
205 .with(|item| {
206 item.set_fill_color(fill_rgba)
207 .set_stroke_color(stroke_rgba)
208 .set_stroke_width(stroke_width)
209 .discard()
210 })
211 }
212}
213
214impl Extract for Parallelogram {
215 type Target = CoreItem;
216
217 fn extract_into(&self, buf: &mut Vec<Self::Target>) {
218 VItem::from(self.clone()).extract_into(buf)
219 }
220}