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}