1use std::{cmp::Ordering, ops::Range};
2
3use color::{AlphaColor, ColorSpace, Srgb};
4use glam::{DAffine2, DMat3, DMat4, DVec3, IVec3, Vec3Swizzles, dvec3, ivec3};
5use itertools::Itertools;
6use log::warn;
7
8use crate::{
9 components::{Anchor, ScaleHint, vpoint::wrap_point_func_with_anchor, width::Width},
10 items::Group,
11};
12
13pub trait Interpolatable {
18 fn lerp(&self, target: &Self, t: f64) -> Self;
20}
21
22impl<T: Interpolatable> Interpolatable for Group<T> {
23 fn lerp(&self, target: &Self, t: f64) -> Self {
24 self.into_iter()
25 .zip(target)
26 .map(|(a, b)| a.lerp(b, t))
27 .collect()
28 }
29}
30
31impl Interpolatable for f32 {
32 fn lerp(&self, target: &Self, t: f64) -> Self {
33 self + (target - self) * t as f32
34 }
35}
36
37impl Interpolatable for f64 {
38 fn lerp(&self, target: &Self, t: f64) -> Self {
39 self + (target - self) * t
40 }
41}
42
43impl Interpolatable for DVec3 {
44 fn lerp(&self, target: &Self, t: f64) -> Self {
45 self + (target - self) * t
46 }
47}
48
49impl<CS: ColorSpace> Interpolatable for AlphaColor<CS> {
50 fn lerp(&self, other: &Self, t: f64) -> Self {
51 AlphaColor::lerp_rect(*self, *other, t as f32)
53 }
54}
55
56impl Interpolatable for DMat4 {
57 fn lerp(&self, other: &Self, t: f64) -> Self {
58 let mut result = DMat4::ZERO;
59 for i in 0..4 {
60 for j in 0..4 {
61 result.col_mut(i)[j] = self.col(i)[j].lerp(&other.col(i)[j], t);
62 }
63 }
64 result
65 }
66}
67
68pub trait With {
82 fn with(mut self, f: impl Fn(&mut Self)) -> Self
84 where
85 Self: Sized,
86 {
87 f(&mut self);
88 self
89 }
90}
91
92impl<T> With for T {}
93
94pub trait Alignable {
102 fn is_aligned(&self, other: &Self) -> bool;
104 fn align_with(&mut self, other: &mut Self);
106}
107
108impl Alignable for DVec3 {
109 fn align_with(&mut self, _other: &mut Self) {}
110 fn is_aligned(&self, _other: &Self) -> bool {
111 true
112 }
113}
114
115impl<T: Alignable> Alignable for Group<T> {
117 fn is_aligned(&self, other: &Self) -> bool {
118 self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a.is_aligned(b))
119 }
120 fn align_with(&mut self, other: &mut Self) {
121 self.iter_mut().zip(other).for_each(|(a, b)| {
122 a.align_with(b);
123 });
124 }
125}
126
127pub trait Opacity {
130 fn set_opacity(&mut self, opacity: f32) -> &mut Self;
132}
133
134impl<T: Opacity, I> Opacity for I
135where
136 for<'a> &'a mut I: IntoIterator<Item = &'a mut T>,
137{
138 fn set_opacity(&mut self, opacity: f32) -> &mut Self {
139 self.into_iter().for_each(|x| {
140 x.set_opacity(opacity);
141 });
142 self
143 }
144}
145
146pub trait Partial {
149 fn get_partial(&self, range: Range<f64>) -> Self;
151 fn get_partial_closed(&self, range: Range<f64>) -> Self;
153}
154
155pub trait Empty {
158 fn empty() -> Self;
160}
161
162pub trait FillColor {
165 fn fill_color(&self) -> AlphaColor<Srgb>;
167 fn set_fill_opacity(&mut self, opacity: f32) -> &mut Self;
169 fn set_fill_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self;
171}
172
173impl<T: FillColor> FillColor for [T] {
174 fn fill_color(&self) -> color::AlphaColor<color::Srgb> {
175 self[0].fill_color()
176 }
177 fn set_fill_color(&mut self, color: color::AlphaColor<color::Srgb>) -> &mut Self {
178 self.iter_mut().for_each(|x| {
179 x.set_fill_color(color);
180 });
181 self
182 }
183 fn set_fill_opacity(&mut self, opacity: f32) -> &mut Self {
184 self.iter_mut().for_each(|x| {
185 x.set_fill_opacity(opacity);
186 });
187 self
188 }
189}
190
191pub trait StrokeColor {
194 fn stroke_color(&self) -> AlphaColor<Srgb>;
196 fn set_stroke_opacity(&mut self, opacity: f32) -> &mut Self;
198 fn set_stroke_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self;
200}
201
202impl<T: StrokeColor> StrokeColor for [T] {
203 fn stroke_color(&self) -> AlphaColor<Srgb> {
204 self[0].stroke_color()
205 }
206 fn set_stroke_color(&mut self, color: color::AlphaColor<color::Srgb>) -> &mut Self {
207 self.iter_mut().for_each(|x| {
208 x.set_stroke_color(color);
209 });
210 self
211 }
212 fn set_stroke_opacity(&mut self, opacity: f32) -> &mut Self {
213 self.iter_mut().for_each(|x| {
214 x.set_stroke_opacity(opacity);
215 });
216 self
217 }
218}
219
220pub trait StrokeWidth {
223 fn apply_stroke_func(&mut self, f: impl for<'a> Fn(&'a mut [Width])) -> &mut Self;
226 fn set_stroke_width(&mut self, width: f32) -> &mut Self {
228 self.apply_stroke_func(|widths| widths.fill(width.into()))
229 }
230}
231
232impl<T: StrokeWidth> StrokeWidth for [T] {
233 fn apply_stroke_func(
234 &mut self,
235 f: impl for<'a> Fn(&'a mut [crate::components::width::Width]),
236 ) -> &mut Self {
237 self.iter_mut().for_each(|x| {
238 x.apply_stroke_func(&f);
239 });
240 self
241 }
242}
243
244pub trait Color: FillColor + StrokeColor {
249 fn set_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
251 self.set_fill_color(color);
252 self.set_stroke_color(color);
253 self
254 }
255}
256
257impl<T: FillColor + StrokeColor + ?Sized> Color for T {}
258
259pub trait BoundingBox {
262 fn get_bounding_box(&self) -> [DVec3; 3];
264 fn get_bounding_box_point(&self, edge: IVec3) -> DVec3 {
268 let bb = self.get_bounding_box();
269 let signum = (edge.signum() + IVec3::ONE).as_uvec3();
270
271 dvec3(
272 bb[signum.x as usize].x,
273 bb[signum.y as usize].y,
274 bb[signum.z as usize].z,
275 )
276 }
277 fn get_bounding_box_corners(&self) -> [DVec3; 8] {
282 [-1, 1]
283 .into_iter()
284 .cartesian_product([-1, 1])
285 .cartesian_product([-1, 1])
286 .map(|((x, y), z)| self.get_bounding_box_point(ivec3(x, y, z)))
287 .collect::<Vec<_>>()
288 .try_into()
289 .unwrap()
290 }
291}
292
293impl BoundingBox for DVec3 {
294 fn get_bounding_box(&self) -> [DVec3; 3] {
295 [*self, *self, *self]
296 }
297}
298
299impl<T: BoundingBox> BoundingBox for [T] {
300 fn get_bounding_box(&self) -> [DVec3; 3] {
301 let [min, max] = self
302 .iter()
303 .map(|x| x.get_bounding_box())
304 .map(|[min, _, max]| [min, max])
305 .reduce(|[acc_min, acc_max], [min, max]| [acc_min.min(min), acc_max.max(max)])
306 .unwrap_or([DVec3::ZERO, DVec3::ZERO]);
307 if min == max {
308 warn!("Empty bounding box, is the slice empty?")
309 }
310 [min, (min + max) / 2.0, max]
311 }
312}
313
314pub trait PointsFunc {
317 fn apply_points_func(&mut self, f: impl for<'a> Fn(&'a mut [DVec3])) -> &mut Self;
319 fn apply_affine(&mut self, affine: DAffine2) -> &mut Self {
321 self.apply_points_func(|points| {
322 points.iter_mut().for_each(|p| {
323 let transformed = affine.transform_point2(p.xy());
324 p.x = transformed.x;
325 p.y = transformed.y;
326 });
327 });
328 self
329 }
330}
331
332pub trait Shift: BoundingBox {
335 fn shift(&mut self, shift: DVec3) -> &mut Self;
337 fn put_anchor_on(&mut self, anchor: Anchor, point: DVec3) -> &mut Self {
341 self.shift(point - anchor.get_pos(self));
342 self
343 }
344 fn put_center_on(&mut self, point: DVec3) -> &mut Self {
346 self.put_anchor_on(Anchor::CENTER, point)
347 }
348}
349
350impl<T: Shift> Shift for [T] {
351 fn shift(&mut self, shift: DVec3) -> &mut Self {
352 self.iter_mut().for_each(|x| {
353 x.shift(shift);
354 });
355 self
356 }
357}
358
359pub trait Rotate {
362 fn rotate_by_anchor(&mut self, angle: f64, axis: DVec3, anchor: Anchor) -> &mut Self;
366 fn rotate(&mut self, angle: f64, axis: DVec3) -> &mut Self {
370 self.rotate_by_anchor(angle, axis, Anchor::CENTER)
371 }
372}
373
374impl<T: Rotate + BoundingBox> Rotate for [T] {
375 fn rotate_by_anchor(&mut self, angle: f64, axis: DVec3, anchor: Anchor) -> &mut Self {
376 let anchor = Anchor::Point(anchor.get_pos(self));
377 self.iter_mut().for_each(|x| {
378 x.rotate_by_anchor(angle, axis, anchor);
379 });
380 self
381 }
382}
383
384pub trait Scale: BoundingBox {
387 fn scale_by_anchor(&mut self, scale: DVec3, anchor: Anchor) -> &mut Self;
391 fn scale(&mut self, scale: DVec3) -> &mut Self {
395 self.scale_by_anchor(scale, Anchor::CENTER)
396 }
397 fn calc_scale_ratio(&self, hint: ScaleHint) -> DVec3 {
401 let bb = self.get_bounding_box();
402 match hint {
403 ScaleHint::X(v) => dvec3(v / (bb[2].x - bb[0].x), 1.0, 1.0),
404 ScaleHint::Y(v) => dvec3(1.0, v / (bb[2].y - bb[0].y), 1.0),
405 ScaleHint::Z(v) => dvec3(1.0, 1.0, v / (bb[2].z - bb[0].z)),
406 ScaleHint::PorportionalX(v) => DVec3::splat(v / (bb[2].x - bb[0].x)),
407 ScaleHint::PorportionalY(v) => DVec3::splat(v / (bb[2].y - bb[0].y)),
408 ScaleHint::PorportionalZ(v) => DVec3::splat(v / (bb[2].z - bb[0].z)),
409 }
410 }
411 fn scale_to(&mut self, hint: ScaleHint) -> &mut Self {
415 self.scale(self.calc_scale_ratio(hint));
416 self
417 }
418}
419
420impl<T: Scale> Scale for [T] {
421 fn scale_by_anchor(&mut self, scale: DVec3, anchor: Anchor) -> &mut Self {
422 let anchor = match anchor {
423 Anchor::Point(p) => p,
424 Anchor::Edge(e) => self.get_bounding_box_point(e),
425 };
426 self.iter_mut().for_each(|x| {
427 x.scale_by_anchor(scale, Anchor::Point(anchor));
428 });
429 self
430 }
431}
432
433impl Shift for DVec3 {
434 fn shift(&mut self, shift: DVec3) -> &mut Self {
435 *self += shift;
436 self
437 }
438}
439
440impl Rotate for DVec3 {
441 fn rotate_by_anchor(&mut self, angle: f64, axis: DVec3, anchor: Anchor) -> &mut Self {
442 let rotation = DMat3::from_axis_angle(axis, angle);
443 let p = match anchor {
444 Anchor::Point(point) => point,
445 Anchor::Edge(edge) => self.get_bounding_box_point(edge),
446 };
447 wrap_point_func_with_anchor(|p| *p = rotation * *p, p)(self);
448 if self.x.abs() < 1e-10 {
449 self.x = 0.0;
450 }
451 if self.y.abs() < 1e-10 {
452 self.y = 0.0;
453 }
454 if self.z.abs() < 1e-10 {
455 self.z = 0.0;
456 }
457 self
458 }
459}
460
461impl Scale for DVec3 {
462 fn scale_by_anchor(&mut self, scale: DVec3, anchor: Anchor) -> &mut Self {
463 let p = match anchor {
464 Anchor::Point(point) => point,
465 Anchor::Edge(edge) => self.get_bounding_box_point(edge),
466 };
467 wrap_point_func_with_anchor(|p| *p *= scale, p)(self);
468 self
469 }
470}
471
472pub trait Arrange: Shift {
475 fn arrange(&mut self, pos_func: impl Fn(usize) -> DVec3);
479 fn arrange_cols(&mut self, ncols: usize, pos_func: impl Fn(usize, usize) -> DVec3);
483 fn arrange_rows(&mut self, nrows: usize, pos_func: impl Fn(usize, usize) -> DVec3);
487}
488
489impl<T: Shift> Arrange for [T] {
490 fn arrange(&mut self, pos_func: impl Fn(usize) -> DVec3) {
491 self.iter_mut().enumerate().for_each(|(i, item)| {
492 item.put_center_on(pos_func(i));
493 });
494 }
495 fn arrange_cols(&mut self, ncols: usize, pos_func: impl Fn(usize, usize) -> DVec3) {
496 let pos_func = |idx: usize| {
497 let row = idx / ncols;
498 let col = idx % ncols;
499 pos_func(row, col)
500 };
501 self.arrange(pos_func);
502 }
503 fn arrange_rows(&mut self, nrows: usize, pos_func: impl Fn(usize, usize) -> DVec3) {
504 let ncols = self.len().div_ceil(nrows);
505 self.arrange_cols(ncols, pos_func);
506 }
507}
508
509pub trait ScaleStrokeExt: Scale + StrokeWidth {
512 fn scale_with_stroke_by_anchor(&mut self, scale: DVec3, anchor: Anchor) -> &mut Self {
514 self.scale_by_anchor(scale, anchor);
515
516 let scales = [scale.x, scale.y, scale.z];
517 let idx = scales
518 .iter()
519 .map(|x: &f64| if *x > 1.0 { *x } else { 1.0 / *x })
520 .position_max_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal))
521 .unwrap_or(0);
522 let scale = scales[idx];
523 self.apply_stroke_func(|widths| widths.iter_mut().for_each(|w| w.0 *= scale as f32));
524 self
525 }
526 fn scale_with_stroke(&mut self, scale: DVec3) -> &mut Self {
528 self.scale_with_stroke_by_anchor(scale, Anchor::CENTER)
529 }
530 fn scale_to_with_stroke(&mut self, hint: ScaleHint) -> &mut Self {
534 let scale = self.calc_scale_ratio(hint);
535 self.scale_with_stroke(scale)
536 }
537}
538
539impl<T: Scale + StrokeWidth + ?Sized> ScaleStrokeExt for T {}