plottery_lib/shapes/
shape.rs

1pub use crate::shapes::circle::Circle;
2pub use crate::shapes::path::Path;
3pub use crate::shapes::rect::Rect;
4
5use crate::{
6    geometry::TransformMatrix,
7    traits::{ClosestPoint, Normalize, Scale, Scale2D, Transform, Translate},
8    BoundingBox, Plottable, Rotate, Rotate90, SampleSettings, V2,
9};
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Serialize, Deserialize, PartialEq)]
13pub enum Shape {
14    Circle(Circle),
15    Rect(Rect),
16    Path(Path),
17}
18
19impl Plottable for Shape {
20    fn get_points(&self, sample_settings: &SampleSettings) -> Vec<V2> {
21        match self {
22            Shape::Circle(c) => c.get_points(sample_settings),
23            Shape::Rect(r) => r.get_points(sample_settings),
24            Shape::Path(p) => p.get_points(sample_settings),
25        }
26    }
27
28    fn length(&self) -> f32 {
29        match self {
30            Shape::Circle(c) => c.length(),
31            Shape::Rect(r) => r.length(),
32            Shape::Path(p) => p.length(),
33        }
34    }
35
36    fn is_closed(&self) -> bool {
37        match self {
38            Shape::Circle(c) => c.is_closed(),
39            Shape::Rect(r) => r.is_closed(),
40            Shape::Path(p) => p.is_closed(),
41        }
42    }
43}
44
45impl Clone for Shape {
46    fn clone(&self) -> Self {
47        match self {
48            Shape::Circle(c) => Shape::Circle(c.clone()),
49            Shape::Rect(r) => Shape::Rect(r.clone()),
50            Shape::Path(p) => Shape::Path(p.clone()),
51        }
52    }
53}
54
55impl Rotate for Shape {
56    fn rotate(&self, angle: &crate::Angle) -> Self {
57        match self {
58            Shape::Circle(c) => Shape::Circle(c.rotate(angle)),
59            Shape::Rect(r) => {
60                Path::new_shape_from(vec![r.bl(), r.tl(), r.tr(), r.br(), r.bl()]).rotate(angle)
61            }
62            Shape::Path(p) => Shape::Path(p.rotate(angle)),
63        }
64    }
65    fn rotate_mut(&mut self, angle: &crate::Angle) {
66        match self {
67            Shape::Circle(c) => c.rotate_mut(angle),
68            Shape::Rect(r) => {
69                *self =
70                    Path::new_shape_from(vec![r.bl(), r.tl(), r.tr(), r.br(), r.bl()]).rotate(angle)
71            }
72            Shape::Path(p) => p.rotate_mut(angle),
73        }
74    }
75
76    fn rotate_around(&self, pivot: &V2, angle: &crate::Angle) -> Self {
77        match self {
78            Shape::Circle(c) => Shape::Circle(c.rotate_around(pivot, angle)),
79            Shape::Rect(r) => Path::new_shape_from(vec![r.bl(), r.tl(), r.tr(), r.br(), r.bl()])
80                .rotate_around(pivot, angle),
81            Shape::Path(p) => Shape::Path(p.rotate_around(pivot, angle)),
82        }
83    }
84    fn rotate_around_mut(&mut self, pivot: &V2, angle: &crate::Angle) {
85        match self {
86            Shape::Circle(c) => c.rotate_around_mut(pivot, angle),
87            Shape::Rect(r) => {
88                *self = Path::new_shape_from(vec![r.bl(), r.tl(), r.tr(), r.br(), r.bl()])
89                    .rotate_around(pivot, angle)
90            }
91            Shape::Path(p) => p.rotate_around_mut(pivot, angle),
92        }
93    }
94}
95
96impl Rotate90 for Shape {
97    fn rotate_90(&self) -> Self {
98        match self {
99            Shape::Circle(c) => Shape::Circle(c.rotate_90()),
100            Shape::Rect(r) => Shape::Rect(r.rotate_90()),
101            Shape::Path(p) => Shape::Path(p.rotate_90()),
102        }
103    }
104    fn rotate_90_mut(&mut self) {
105        match self {
106            Shape::Circle(c) => c.rotate_90_mut(),
107            Shape::Rect(r) => r.rotate_90_mut(),
108            Shape::Path(p) => p.rotate_90_mut(),
109        }
110    }
111
112    fn rotate_180(&self) -> Self {
113        match self {
114            Shape::Circle(c) => Shape::Circle(c.rotate_180()),
115            Shape::Rect(r) => Shape::Rect(r.rotate_180()),
116            Shape::Path(p) => Shape::Path(p.rotate_180()),
117        }
118    }
119    fn rotate_180_mut(&mut self) {
120        match self {
121            Shape::Circle(c) => c.rotate_180_mut(),
122            Shape::Rect(r) => r.rotate_180_mut(),
123            Shape::Path(p) => p.rotate_180_mut(),
124        }
125    }
126
127    fn rotate_270(&self) -> Self {
128        match self {
129            Shape::Circle(c) => Shape::Circle(c.rotate_270()),
130            Shape::Rect(r) => Shape::Rect(r.rotate_270()),
131            Shape::Path(p) => Shape::Path(p.rotate_270()),
132        }
133    }
134    fn rotate_270_mut(&mut self) {
135        match self {
136            Shape::Circle(c) => c.rotate_270_mut(),
137            Shape::Rect(r) => r.rotate_270_mut(),
138            Shape::Path(p) => p.rotate_270_mut(),
139        }
140    }
141
142    fn rotate_90_around(&self, pivot: &V2) -> Self {
143        match self {
144            Shape::Circle(c) => Shape::Circle(c.rotate_90_around(pivot)),
145            Shape::Rect(r) => Shape::Rect(r.rotate_90_around(pivot)),
146            Shape::Path(p) => Shape::Path(p.rotate_90_around(pivot)),
147        }
148    }
149    fn rotate_90_around_mut(&mut self, pivot: &V2) {
150        match self {
151            Shape::Circle(c) => c.rotate_90_around_mut(pivot),
152            Shape::Rect(r) => r.rotate_90_around_mut(pivot),
153            Shape::Path(p) => p.rotate_90_around_mut(pivot),
154        }
155    }
156
157    fn rotate_180_around(&self, pivot: &V2) -> Self {
158        match self {
159            Shape::Circle(c) => Shape::Circle(c.rotate_180_around(pivot)),
160            Shape::Rect(r) => Shape::Rect(r.rotate_180_around(pivot)),
161            Shape::Path(p) => Shape::Path(p.rotate_180_around(pivot)),
162        }
163    }
164    fn rotate_180_around_mut(&mut self, pivot: &V2) {
165        match self {
166            Shape::Circle(c) => c.rotate_180_around_mut(pivot),
167            Shape::Rect(r) => r.rotate_180_around_mut(pivot),
168            Shape::Path(p) => p.rotate_180_around_mut(pivot),
169        }
170    }
171
172    fn rotate_270_around(&self, pivot: &V2) -> Self {
173        match self {
174            Shape::Circle(c) => Shape::Circle(c.rotate_270_around(pivot)),
175            Shape::Rect(r) => Shape::Rect(r.rotate_270_around(pivot)),
176            Shape::Path(p) => Shape::Path(p.rotate_270_around(pivot)),
177        }
178    }
179
180    fn rotate_270_around_mut(&mut self, pivot: &V2) {
181        match self {
182            Shape::Circle(c) => c.rotate_270_around_mut(pivot),
183            Shape::Rect(r) => r.rotate_270_around_mut(pivot),
184            Shape::Path(p) => p.rotate_270_around_mut(pivot),
185        }
186    }
187}
188
189impl Translate for Shape {
190    fn translate(&self, dist: &V2) -> Self {
191        match self {
192            Shape::Circle(c) => Shape::Circle(c.translate(dist)),
193            Shape::Rect(r) => Shape::Rect(r.translate(dist)),
194            Shape::Path(p) => Shape::Path(p.translate(dist)),
195        }
196    }
197
198    fn translate_mut(&mut self, dist: &V2) {
199        match self {
200            Shape::Circle(c) => c.translate_mut(dist),
201            Shape::Rect(r) => r.translate_mut(dist),
202            Shape::Path(p) => p.translate_mut(dist),
203        }
204    }
205}
206
207impl Scale for Shape {
208    fn scale(&self, scale: f32) -> Self {
209        match self {
210            Shape::Circle(c) => Shape::Circle(c.scale(scale)),
211            Shape::Rect(r) => Shape::Rect(r.scale(scale)),
212            Shape::Path(p) => Shape::Path(p.scale(scale)),
213        }
214    }
215
216    fn scale_mut(&mut self, scale: f32) {
217        match self {
218            Shape::Circle(c) => c.scale_mut(scale),
219            Shape::Rect(r) => r.scale_mut(scale),
220            Shape::Path(p) => p.scale_mut(scale),
221        }
222    }
223}
224
225impl Scale2D for Shape {
226    fn scale_2d(&self, factor: &V2) -> Self {
227        match self {
228            Shape::Circle(c) => {
229                let mut points = c.get_points(&SampleSettings::default());
230                for p in &mut points {
231                    *p *= factor;
232                }
233                Path::new_shape_from(points)
234            }
235            Shape::Rect(r) => Shape::Rect(r.scale_2d(factor)),
236            Shape::Path(p) => Shape::Path(p.scale_2d(factor)),
237        }
238    }
239
240    fn scale_2d_mut(&mut self, factor: &V2) {
241        match self {
242            Shape::Circle(c) => {
243                let mut points = c.get_points(&SampleSettings::default());
244                for p in &mut points {
245                    *p *= factor;
246                }
247                *self = Path::new_shape_from(points);
248            }
249            Shape::Rect(r) => r.scale_2d_mut(factor),
250            Shape::Path(p) => p.scale_2d_mut(factor),
251        }
252    }
253}
254
255impl Normalize for Shape {}
256
257impl BoundingBox for Shape {
258    fn bounding_box(&self) -> Option<Rect> {
259        match self {
260            Shape::Circle(c) => c.bounding_box(),
261            Shape::Rect(r) => r.bounding_box(),
262            Shape::Path(p) => p.bounding_box(),
263        }
264    }
265}
266
267impl Transform for Shape {
268    fn transform(&self, matrix: &TransformMatrix) -> Self {
269        match self {
270            Shape::Circle(c) => Shape::Path(
271                c.get_points(&SampleSettings::default())
272                    .iter()
273                    .map(|p| matrix.mul_vector(p))
274                    .collect::<Path>(),
275            ),
276            Shape::Rect(r) => {
277                let points = vec![
278                    matrix.mul_vector(&r.bl()),
279                    matrix.mul_vector(&r.tl()),
280                    matrix.mul_vector(&r.tr()),
281                    matrix.mul_vector(&r.br()),
282                    matrix.mul_vector(&r.bl()),
283                ];
284                Path::new_shape_from(points)
285            }
286            Shape::Path(p) => Shape::Path(p.transform(matrix)),
287        }
288    }
289
290    fn transform_mut(&mut self, matrix: &TransformMatrix) {
291        match self {
292            Shape::Circle(c) => {
293                let points = c
294                    .get_points(&SampleSettings::default())
295                    .iter()
296                    .map(|p| matrix.mul_vector(p))
297                    .collect::<Path>();
298                *self = Shape::Path(points);
299            }
300            Shape::Rect(r) => {
301                let points = vec![
302                    matrix.mul_vector(&r.bl()),
303                    matrix.mul_vector(&r.tl()),
304                    matrix.mul_vector(&r.tr()),
305                    matrix.mul_vector(&r.br()),
306                    matrix.mul_vector(&r.bl()),
307                ];
308                *self = Path::new_shape_from(points);
309            }
310            Shape::Path(p) => p.transform_mut(matrix),
311        }
312    }
313}
314
315impl ClosestPoint for Shape {
316    fn closest_point(&self, sample_settings: &SampleSettings, point: &V2) -> Option<V2> {
317        match self {
318            Shape::Circle(c) => c.closest_point(sample_settings, point),
319            Shape::Rect(r) => r.closest_point(sample_settings, point),
320            Shape::Path(p) => p.closest_point(sample_settings, point),
321        }
322    }
323}