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 tracing::warn;
7
8use crate::components::width::Width;
9
10pub trait Interpolatable {
15 fn lerp(&self, target: &Self, t: f64) -> Self;
17}
18
19impl Interpolatable for f32 {
20 fn lerp(&self, target: &Self, t: f64) -> Self {
21 self + (target - self) * t as f32
22 }
23}
24
25impl Interpolatable for f64 {
26 fn lerp(&self, target: &Self, t: f64) -> Self {
27 self + (target - self) * t
28 }
29}
30
31impl Interpolatable for DVec3 {
32 fn lerp(&self, target: &Self, t: f64) -> Self {
33 self + (target - self) * t
34 }
35}
36
37impl<CS: ColorSpace> Interpolatable for AlphaColor<CS> {
38 fn lerp(&self, other: &Self, t: f64) -> Self {
39 AlphaColor::lerp_rect(*self, *other, t as f32)
41 }
42}
43
44impl Interpolatable for DMat4 {
45 fn lerp(&self, other: &Self, t: f64) -> Self {
46 let mut result = DMat4::ZERO;
47 for i in 0..4 {
48 for j in 0..4 {
49 result.col_mut(i)[j] = self.col(i)[j].lerp(&other.col(i)[j], t);
50 }
51 }
52 result
53 }
54}
55
56pub trait With {
70 fn with(mut self, f: impl Fn(&mut Self)) -> Self
72 where
73 Self: Sized,
74 {
75 f(&mut self);
76 self
77 }
78}
79
80impl<T> With for T {}
81
82pub trait Alignable: Clone {
90 fn is_aligned(&self, other: &Self) -> bool;
92 fn align_with(&mut self, other: &mut Self);
94}
95
96impl Alignable for DVec3 {
97 fn align_with(&mut self, _other: &mut Self) {}
98 fn is_aligned(&self, _other: &Self) -> bool {
99 true
100 }
101}
102
103pub trait Opacity {
106 fn set_opacity(&mut self, opacity: f32) -> &mut Self;
108}
109
110impl<T: Opacity, I> Opacity for I
111where
112 for<'a> &'a mut I: IntoIterator<Item = &'a mut T>,
113{
114 fn set_opacity(&mut self, opacity: f32) -> &mut Self {
115 self.into_iter().for_each(|x: &mut T| {
116 x.set_opacity(opacity);
117 });
118 self
119 }
120}
121
122pub trait Partial {
125 fn get_partial(&self, range: Range<f64>) -> Self;
127 fn get_partial_closed(&self, range: Range<f64>) -> Self;
129}
130
131pub trait Empty {
134 fn empty() -> Self;
136}
137
138pub trait FillColor {
141 fn fill_color(&self) -> AlphaColor<Srgb>;
143 fn set_fill_opacity(&mut self, opacity: f32) -> &mut Self;
145 fn set_fill_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self;
147}
148
149impl<T: FillColor> FillColor for [T] {
150 fn fill_color(&self) -> color::AlphaColor<color::Srgb> {
151 self[0].fill_color()
152 }
153 fn set_fill_color(&mut self, color: color::AlphaColor<color::Srgb>) -> &mut Self {
154 self.iter_mut().for_each(|x| {
155 x.set_fill_color(color);
156 });
157 self
158 }
159 fn set_fill_opacity(&mut self, opacity: f32) -> &mut Self {
160 self.iter_mut().for_each(|x| {
161 x.set_fill_opacity(opacity);
162 });
163 self
164 }
165}
166
167pub trait StrokeColor {
170 fn stroke_color(&self) -> AlphaColor<Srgb>;
172 fn set_stroke_opacity(&mut self, opacity: f32) -> &mut Self;
174 fn set_stroke_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self;
176}
177
178impl<T: StrokeColor> StrokeColor for [T] {
179 fn stroke_color(&self) -> AlphaColor<Srgb> {
180 self[0].stroke_color()
181 }
182 fn set_stroke_color(&mut self, color: color::AlphaColor<color::Srgb>) -> &mut Self {
183 self.iter_mut().for_each(|x| {
184 x.set_stroke_color(color);
185 });
186 self
187 }
188 fn set_stroke_opacity(&mut self, opacity: f32) -> &mut Self {
189 self.iter_mut().for_each(|x| {
190 x.set_stroke_opacity(opacity);
191 });
192 self
193 }
194}
195
196pub trait StrokeWidth {
199 fn stroke_width(&self) -> f32;
202 fn apply_stroke_func(&mut self, f: impl for<'a> Fn(&'a mut [Width])) -> &mut Self;
204 fn set_stroke_width(&mut self, width: f32) -> &mut Self {
206 self.apply_stroke_func(|widths| widths.fill(width.into()))
207 }
208}
209
210impl<T: StrokeWidth> StrokeWidth for [T] {
211 fn stroke_width(&self) -> f32 {
212 self[0].stroke_width()
213 }
214 fn apply_stroke_func(
215 &mut self,
216 f: impl for<'a> Fn(&'a mut [crate::components::width::Width]),
217 ) -> &mut Self {
218 self.iter_mut().for_each(|x| {
219 x.apply_stroke_func(&f);
220 });
221 self
222 }
223}
224
225pub trait Color: FillColor + StrokeColor {
230 fn set_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
232 self.set_fill_color(color);
233 self.set_stroke_color(color);
234 self
235 }
236}
237
238impl<T: FillColor + StrokeColor + ?Sized> Color for T {}
239
240pub trait BoundingBox {
243 fn get_bounding_box(&self) -> [DVec3; 3];
245 fn get_bounding_box_point(&self, edge: IVec3) -> DVec3 {
249 let bb = self.get_bounding_box();
250 let signum = (edge.signum() + IVec3::ONE).as_uvec3();
251
252 dvec3(
253 bb[signum.x as usize].x,
254 bb[signum.y as usize].y,
255 bb[signum.z as usize].z,
256 )
257 }
258 fn get_bounding_box_corners(&self) -> [DVec3; 8] {
263 [-1, 1]
264 .into_iter()
265 .cartesian_product([-1, 1])
266 .cartesian_product([-1, 1])
267 .map(|((x, y), z)| self.get_bounding_box_point(ivec3(x, y, z)))
268 .collect::<Vec<_>>()
269 .try_into()
270 .unwrap()
271 }
272}
273
274impl BoundingBox for DVec3 {
275 fn get_bounding_box(&self) -> [DVec3; 3] {
276 [*self, *self, *self]
277 }
278}
279
280impl<T: BoundingBox> BoundingBox for [T] {
281 fn get_bounding_box(&self) -> [DVec3; 3] {
282 let [min, max] = self
283 .iter()
284 .map(|x| x.get_bounding_box())
285 .map(|[min, _, max]| [min, max])
286 .reduce(|[acc_min, acc_max], [min, max]| [acc_min.min(min), acc_max.max(max)])
287 .unwrap_or([DVec3::ZERO, DVec3::ZERO]);
288 if min == max {
289 warn!("Empty bounding box, is the slice empty?")
290 }
291 [min, (min + max) / 2.0, max]
292 }
293}
294
295pub trait PointsFunc {
298 fn apply_points_func(&mut self, f: impl for<'a> Fn(&'a mut [DVec3])) -> &mut Self;
300 fn apply_affine(&mut self, affine: DAffine2) -> &mut Self {
302 self.apply_points_func(|points| {
303 points.iter_mut().for_each(|p| {
304 let transformed = affine.transform_point2(p.xy());
305 p.x = transformed.x;
306 p.y = transformed.y;
307 });
308 });
309 self
310 }
311}
312
313pub trait Shift: BoundingBox {
316 fn shift(&mut self, shift: DVec3) -> &mut Self;
318 fn put_anchor_on(&mut self, anchor: Anchor, point: DVec3) -> &mut Self {
322 self.shift(point - anchor.get_pos(self));
323 self
324 }
325 fn put_center_on(&mut self, point: DVec3) -> &mut Self {
327 self.put_anchor_on(Anchor::CENTER, point)
328 }
329}
330
331impl<T: Shift> Shift for [T] {
332 fn shift(&mut self, shift: DVec3) -> &mut Self {
333 self.iter_mut().for_each(|x| {
334 x.shift(shift);
335 });
336 self
337 }
338}
339
340pub trait Rotate {
343 fn rotate_by_anchor(&mut self, angle: f64, axis: DVec3, anchor: Anchor) -> &mut Self;
347 fn rotate(&mut self, angle: f64, axis: DVec3) -> &mut Self {
351 self.rotate_by_anchor(angle, axis, Anchor::CENTER)
352 }
353}
354
355impl<T: Rotate + BoundingBox> Rotate for [T] {
356 fn rotate_by_anchor(&mut self, angle: f64, axis: DVec3, anchor: Anchor) -> &mut Self {
357 let anchor = Anchor::Point(anchor.get_pos(self));
358 self.iter_mut().for_each(|x| {
359 x.rotate_by_anchor(angle, axis, anchor);
360 });
361 self
362 }
363}
364
365#[derive(Debug, Clone, Copy)]
371pub enum Anchor {
372 Point(DVec3),
374 Edge(IVec3),
384}
385
386impl Anchor {
387 pub const ORIGIN: Self = Self::Point(DVec3::ZERO);
389 pub const CENTER: Self = Self::Edge(IVec3::ZERO);
391
392 pub fn point(x: f64, y: f64, z: f64) -> Self {
394 Self::Point(dvec3(x, y, z))
395 }
396 pub fn edge(x: i32, y: i32, z: i32) -> Self {
398 Self::Edge(ivec3(x, y, z).clamp(IVec3::NEG_ONE, IVec3::ONE))
399 }
400
401 pub fn get_pos<T: BoundingBox + ?Sized>(self, bbox: &T) -> DVec3 {
403 match self {
404 Self::Point(x) => x,
405 Self::Edge(x) => bbox.get_bounding_box_point(x),
406 }
407 }
408}
409
410pub fn wrap_point_func_with_point(
413 f: impl Fn(&mut DVec3) + Copy,
414 point: DVec3,
415) -> impl Fn(&mut DVec3) + Copy {
416 move |points| {
417 *points -= point;
418 f(points);
419 *points += point;
420 }
421}
422
423#[derive(Debug, Clone, Copy)]
426pub enum ScaleHint {
427 X(f64),
429 Y(f64),
431 Z(f64),
433 PorportionalX(f64),
435 PorportionalY(f64),
437 PorportionalZ(f64),
439}
440
441pub trait Scale: BoundingBox {
444 fn scale_by_anchor(&mut self, scale: DVec3, anchor: Anchor) -> &mut Self;
448 fn scale(&mut self, scale: DVec3) -> &mut Self {
452 self.scale_by_anchor(scale, Anchor::CENTER)
453 }
454 fn calc_scale_ratio(&self, hint: ScaleHint) -> DVec3 {
458 let bb = self.get_bounding_box();
459 match hint {
460 ScaleHint::X(v) => dvec3(v / (bb[2].x - bb[0].x), 1.0, 1.0),
461 ScaleHint::Y(v) => dvec3(1.0, v / (bb[2].y - bb[0].y), 1.0),
462 ScaleHint::Z(v) => dvec3(1.0, 1.0, v / (bb[2].z - bb[0].z)),
463 ScaleHint::PorportionalX(v) => DVec3::splat(v / (bb[2].x - bb[0].x)),
464 ScaleHint::PorportionalY(v) => DVec3::splat(v / (bb[2].y - bb[0].y)),
465 ScaleHint::PorportionalZ(v) => DVec3::splat(v / (bb[2].z - bb[0].z)),
466 }
467 }
468 fn scale_to(&mut self, hint: ScaleHint) -> &mut Self {
472 self.scale(self.calc_scale_ratio(hint));
473 self
474 }
475 fn scale_to_min(&mut self, hints: &[ScaleHint]) -> &mut Self {
479 let scale = hints
480 .iter()
481 .map(|hint| self.calc_scale_ratio(*hint))
482 .reduce(|a, b| a.min(b))
483 .unwrap_or(DVec3::ONE);
484 self.scale(scale);
485 self
486 }
487 fn scale_to_max(&mut self, hints: &[ScaleHint]) -> &mut Self {
491 let scale = hints
492 .iter()
493 .map(|hint| self.calc_scale_ratio(*hint))
494 .reduce(|a, b| a.max(b))
495 .unwrap_or(DVec3::ONE);
496 self.scale(scale);
497 self
498 }
499}
500
501impl<T: Scale> Scale for [T] {
502 fn scale_by_anchor(&mut self, scale: DVec3, anchor: Anchor) -> &mut Self {
503 let anchor = match anchor {
504 Anchor::Point(p) => p,
505 Anchor::Edge(e) => self.get_bounding_box_point(e),
506 };
507 self.iter_mut().for_each(|x| {
508 x.scale_by_anchor(scale, Anchor::Point(anchor));
509 });
510 self
511 }
512}
513
514impl Shift for DVec3 {
515 fn shift(&mut self, shift: DVec3) -> &mut Self {
516 *self += shift;
517 self
518 }
519}
520
521impl Rotate for DVec3 {
522 fn rotate_by_anchor(&mut self, angle: f64, axis: DVec3, anchor: Anchor) -> &mut Self {
523 let rotation = DMat3::from_axis_angle(axis, angle);
524 let p = match anchor {
525 Anchor::Point(point) => point,
526 Anchor::Edge(edge) => self.get_bounding_box_point(edge),
527 };
528 wrap_point_func_with_point(|p| *p = rotation * *p, p)(self);
529 if self.x.abs() < 1e-10 {
530 self.x = 0.0;
531 }
532 if self.y.abs() < 1e-10 {
533 self.y = 0.0;
534 }
535 if self.z.abs() < 1e-10 {
536 self.z = 0.0;
537 }
538 self
539 }
540}
541
542impl Scale for DVec3 {
543 fn scale_by_anchor(&mut self, scale: DVec3, anchor: Anchor) -> &mut Self {
544 let p = match anchor {
545 Anchor::Point(point) => point,
546 Anchor::Edge(edge) => self.get_bounding_box_point(edge),
547 };
548 wrap_point_func_with_point(|p| *p *= scale, p)(self);
549 self
550 }
551}
552
553pub trait Arrange: Shift {
556 fn arrange(&mut self, pos_func: impl Fn(usize) -> DVec3);
560 fn arrange_cols(&mut self, ncols: usize, pos_func: impl Fn(usize, usize) -> DVec3);
564 fn arrange_rows(&mut self, nrows: usize, pos_func: impl Fn(usize, usize) -> DVec3);
568}
569
570impl<T: Shift> Arrange for [T] {
571 fn arrange(&mut self, pos_func: impl Fn(usize) -> DVec3) {
572 self.iter_mut().enumerate().for_each(|(i, item)| {
573 item.put_center_on(pos_func(i));
574 });
575 }
576 fn arrange_cols(&mut self, ncols: usize, pos_func: impl Fn(usize, usize) -> DVec3) {
577 let pos_func = |idx: usize| {
578 let row = idx / ncols;
579 let col = idx % ncols;
580 pos_func(row, col)
581 };
582 self.arrange(pos_func);
583 }
584 fn arrange_rows(&mut self, nrows: usize, pos_func: impl Fn(usize, usize) -> DVec3) {
585 let ncols = self.len().div_ceil(nrows);
586 self.arrange_cols(ncols, pos_func);
587 }
588}
589
590pub trait ScaleStrokeExt: Scale + StrokeWidth {
593 fn scale_with_stroke_by_anchor(&mut self, scale: DVec3, anchor: Anchor) -> &mut Self {
595 self.scale_by_anchor(scale, anchor);
596
597 let scales = [scale.x, scale.y, scale.z];
598 let idx = scales
599 .iter()
600 .map(|x: &f64| if *x > 1.0 { *x } else { 1.0 / *x })
601 .position_max_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::Equal))
602 .unwrap_or(0);
603 let scale = scales[idx];
604 self.apply_stroke_func(|widths| widths.iter_mut().for_each(|w| w.0 *= scale as f32));
605 self
606 }
607 fn scale_with_stroke(&mut self, scale: DVec3) -> &mut Self {
609 self.scale_with_stroke_by_anchor(scale, Anchor::CENTER)
610 }
611 fn scale_to_with_stroke(&mut self, hint: ScaleHint) -> &mut Self {
615 let scale = self.calc_scale_ratio(hint);
616 self.scale_with_stroke(scale)
617 }
618}
619
620impl<T: Scale + StrokeWidth + ?Sized> ScaleStrokeExt for T {}