1use crate::*;
2use enum_dispatch::enum_dispatch;
3
4use std::{
5 collections::BTreeMap,
6 iter::FromIterator,
7 ops::{Add, Mul, Sub},
8};
9
10mod sample;
11pub use sample::*;
12
13#[derive(Clone, Debug, PartialEq, Hash)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25#[cfg_attr(
26 feature = "serde",
27 serde(bound(
28 serialize = "K: Serialize + Ord, V: Serialize",
29 deserialize = "K: Deserialize<'de> + Ord, V: Deserialize<'de>",
30 ))
31)]
32#[cfg_attr(feature = "facet", derive(Facet))]
33#[cfg_attr(feature = "facet", facet(opaque))]
34#[cfg_attr(feature = "rkyv", derive(Archive, RkyvSerialize, RkyvDeserialize))]
35pub struct KeyDataMap<K, V> {
36 #[cfg(not(feature = "interpolation"))]
38 pub values: BTreeMap<K, V>,
39 #[cfg(feature = "interpolation")]
40 pub values: BTreeMap<K, (V, Option<crate::Key<V>>)>,
41}
42
43pub type TimeDataMap<V> = KeyDataMap<Time, V>;
45
46impl<K: Eq, V: Eq> Eq for KeyDataMap<K, V> {}
48
49#[cfg(not(feature = "interpolation"))]
51impl<K, V> AsRef<BTreeMap<K, V>> for KeyDataMap<K, V> {
52 fn as_ref(&self) -> &BTreeMap<K, V> {
53 &self.values
54 }
55}
56
57impl<K: Ord, V> KeyDataMap<K, V> {
58 #[inline]
60 pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
61 #[cfg(not(feature = "interpolation"))]
62 {
63 self.values.iter()
64 }
65 #[cfg(feature = "interpolation")]
66 {
67 self.values.iter().map(|(k, (v, _))| (k, v))
68 }
69 }
70
71 #[inline]
73 pub fn is_empty(&self) -> bool {
74 self.values.is_empty()
75 }
76
77 #[inline]
79 pub fn len(&self) -> usize {
80 self.values.len()
81 }
82
83 #[inline]
87 pub fn remove(&mut self, key: &K) -> Option<V> {
88 #[cfg(not(feature = "interpolation"))]
89 {
90 self.values.remove(key)
91 }
92 #[cfg(feature = "interpolation")]
93 {
94 self.values.remove(key).map(|(v, _)| v)
95 }
96 }
97}
98
99impl<K: Ord, V> From<BTreeMap<K, V>> for KeyDataMap<K, V> {
101 fn from(values: BTreeMap<K, V>) -> Self {
102 #[cfg(not(feature = "interpolation"))]
103 {
104 Self { values }
105 }
106 #[cfg(feature = "interpolation")]
107 {
108 Self {
109 values: values.into_iter().map(|(k, v)| (k, (v, None))).collect(),
110 }
111 }
112 }
113}
114
115#[enum_dispatch]
117pub trait TimeDataMapControl<T> {
118 fn len(&self) -> usize;
120 fn is_empty(&self) -> bool;
122 fn is_animated(&self) -> bool;
124}
125
126impl<V> TimeDataMapControl<V> for KeyDataMap<Time, V> {
127 fn len(&self) -> usize {
128 self.values.len()
129 }
130
131 fn is_empty(&self) -> bool {
132 self.values.is_empty()
133 }
134
135 fn is_animated(&self) -> bool {
136 self.values.len() > 1
137 }
138}
139
140#[cfg(feature = "builtin-types")]
141impl<K, V> crate::DataTypeOps for KeyDataMap<K, V>
142where
143 V: crate::DataTypeOps,
144{
145 fn data_type(&self) -> crate::DataType {
146 #[cfg(not(feature = "interpolation"))]
148 {
149 self.values
150 .values()
151 .next()
152 .map(|v| v.data_type())
153 .unwrap_or(DataType::Real)
154 }
155 #[cfg(feature = "interpolation")]
156 {
157 self.values
158 .values()
159 .next()
160 .map(|(v, _)| v.data_type())
161 .unwrap_or(DataType::Real)
162 }
163 }
164
165 fn type_name(&self) -> &'static str {
166 #[cfg(not(feature = "interpolation"))]
168 {
169 self.values
170 .values()
171 .next()
172 .map(|v| v.type_name())
173 .unwrap_or("unknown")
174 }
175 #[cfg(feature = "interpolation")]
176 {
177 self.values
178 .values()
179 .next()
180 .map(|(v, _)| v.type_name())
181 .unwrap_or("unknown")
182 }
183 }
184}
185
186#[cfg(feature = "builtin-types")]
188macro_rules! impl_from_at_time {
189 ($($t:ty),+) => {
190 $(
191 impl From<(Time, $t)> for TimeDataMap<$t> {
192 fn from((time, value): (Time, $t)) -> Self {
193 TimeDataMap::from(BTreeMap::from([(time, value)]))
194 }
195 }
196 )+
197 };
198}
199
200#[cfg(feature = "builtin-types")]
201impl_from_at_time!(
202 Boolean, Real, Integer, String, Color, BooleanVec, RealVec, IntegerVec, StringVec, ColorVec,
203 Data
204);
205
206#[cfg(all(feature = "builtin-types", feature = "curves"))]
207impl_from_at_time!(RealCurve, ColorCurve);
208
209#[cfg(all(feature = "builtin-types", feature = "vector2"))]
210impl_from_at_time!(Vector2);
211#[cfg(all(feature = "builtin-types", feature = "vector3"))]
212impl_from_at_time!(Vector3);
213#[cfg(all(feature = "builtin-types", feature = "matrix3"))]
214impl_from_at_time!(Matrix3);
215#[cfg(all(feature = "builtin-types", feature = "normal3"))]
216impl_from_at_time!(Normal3);
217#[cfg(all(feature = "builtin-types", feature = "point3"))]
218impl_from_at_time!(Point3);
219#[cfg(all(feature = "builtin-types", feature = "matrix4"))]
220impl_from_at_time!(Matrix4);
221
222#[cfg(all(
223 feature = "builtin-types",
224 feature = "vector2",
225 feature = "vec_variants"
226))]
227impl_from_at_time!(Vector2Vec);
228#[cfg(all(
229 feature = "builtin-types",
230 feature = "vector3",
231 feature = "vec_variants"
232))]
233impl_from_at_time!(Vector3Vec);
234#[cfg(all(
235 feature = "builtin-types",
236 feature = "matrix3",
237 feature = "vec_variants"
238))]
239impl_from_at_time!(Matrix3Vec);
240#[cfg(all(
241 feature = "builtin-types",
242 feature = "normal3",
243 feature = "vec_variants"
244))]
245impl_from_at_time!(Normal3Vec);
246#[cfg(all(
247 feature = "builtin-types",
248 feature = "point3",
249 feature = "vec_variants"
250))]
251impl_from_at_time!(Point3Vec);
252#[cfg(all(
253 feature = "builtin-types",
254 feature = "matrix4",
255 feature = "vec_variants"
256))]
257impl_from_at_time!(Matrix4Vec);
258
259impl<K: Ord, V> KeyDataMap<K, V> {
260 pub fn insert(&mut self, key: K, value: V) {
262 #[cfg(not(feature = "interpolation"))]
263 {
264 self.values.insert(key, value);
265 }
266 #[cfg(feature = "interpolation")]
267 {
268 self.values.insert(key, (value, None));
269 }
270 }
271
272 pub fn get(&self, key: &K) -> Option<&V> {
274 #[cfg(not(feature = "interpolation"))]
275 {
276 self.values.get(key)
277 }
278 #[cfg(feature = "interpolation")]
279 {
280 self.values.get(key).map(|(v, _)| v)
281 }
282 }
283}
284
285impl<K, V> KeyDataMap<K, V>
286where
287 K: Ord + Copy + Into<f32>,
288 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
289{
290 pub fn interpolate(&self, key: K) -> V {
291 #[cfg(not(feature = "interpolation"))]
292 {
293 interpolate(&self.values, key)
294 }
295 #[cfg(feature = "interpolation")]
296 {
297 interpolate_with_specs(&self.values, key)
298 }
299 }
300}
301
302#[cfg(feature = "interpolation")]
304impl<K: Ord, V> KeyDataMap<K, V> {
305 pub fn insert_with_interpolation(&mut self, key: K, value: V, spec: crate::Key<V>) {
310 self.values.insert(key, (value, Some(spec)));
311 }
312
313 pub fn interpolation(&self, key: &K) -> Option<&crate::Key<V>> {
317 self.values.get(key)?.1.as_ref()
318 }
319
320 pub fn set_interpolation_at(&mut self, key: &K, spec: crate::Key<V>) -> crate::Result<()> {
325 if let Some(entry) = self.values.get_mut(key) {
326 entry.1 = Some(spec);
327 Ok(())
328 } else {
329 Err(crate::Error::KeyNotFound)
330 }
331 }
332
333 pub fn clear_interpolation(&mut self) {
337 for (_, interp) in self.values.values_mut() {
338 *interp = None;
339 }
340 }
341
342 pub fn has_interpolation(&self) -> bool {
346 self.values.values().any(|(_, interp)| interp.is_some())
347 }
348}
349
350impl<K: Ord, V, U> FromIterator<(K, U)> for KeyDataMap<K, V>
351where
352 U: Into<V>,
353{
354 fn from_iter<I>(iter: I) -> Self
355 where
356 I: IntoIterator<Item = (K, U)>,
357 {
358 Self::from(BTreeMap::from_iter(
359 iter.into_iter().map(|(k, v)| (k, v.into())),
360 ))
361 }
362}
363
364impl<K: Ord + Copy + Into<f32>, V> KeyDataMap<K, V> {
365 pub fn closest_sample(&self, key: K) -> &V {
366 let k_f32: f32 = key.into();
367 #[cfg(not(feature = "interpolation"))]
368 {
369 let mut range = self.values.range(key..);
370 let greater_or_equal = range.next();
371
372 let mut range = self.values.range(..key);
373 let less_than = range.next_back();
374
375 match (less_than, greater_or_equal) {
376 (Some((lower_k, lower_v)), Some((upper_k, upper_v))) => {
377 let lo: f32 = (*lower_k).into();
378 let hi: f32 = (*upper_k).into();
379 if (k_f32 - lo).abs() <= (hi - k_f32).abs() {
380 lower_v
381 } else {
382 upper_v
383 }
384 }
385 (Some(entry), None) | (None, Some(entry)) => entry.1,
386 (None, None) => {
387 unreachable!("KeyDataMap can never be empty")
388 }
389 }
390 }
391 #[cfg(feature = "interpolation")]
392 {
393 let mut range = self.values.range(key..);
394 let greater_or_equal = range.next();
395
396 let mut range = self.values.range(..key);
397 let less_than = range.next_back();
398
399 match (less_than, greater_or_equal) {
400 (Some((lower_k, (lower_v, _))), Some((upper_k, (upper_v, _)))) => {
401 let lo: f32 = (*lower_k).into();
402 let hi: f32 = (*upper_k).into();
403 if (k_f32 - lo).abs() <= (hi - k_f32).abs() {
404 lower_v
405 } else {
406 upper_v
407 }
408 }
409 (Some((_, (v, _))), None) | (None, Some((_, (v, _)))) => v,
410 (None, None) => {
411 unreachable!("KeyDataMap can never be empty")
412 }
413 }
414 }
415 }
416
417 pub fn sample_at(&self, key: K) -> Option<&V> {
419 self.get(&key)
420 }
421
422 pub fn sample_at_or_before(&self, key: K) -> Option<&V> {
424 #[cfg(not(feature = "interpolation"))]
425 {
426 self.values.range(..=key).next_back().map(|(_, v)| v)
427 }
428 #[cfg(feature = "interpolation")]
429 {
430 self.values.range(..=key).next_back().map(|(_, (v, _))| v)
431 }
432 }
433
434 pub fn sample_at_or_after(&self, key: K) -> Option<&V> {
436 #[cfg(not(feature = "interpolation"))]
437 {
438 self.values.range(key..).next().map(|(_, v)| v)
439 }
440 #[cfg(feature = "interpolation")]
441 {
442 self.values.range(key..).next().map(|(_, (v, _))| v)
443 }
444 }
445
446 pub fn sample_surrounding<const N: usize>(&self, key: K) -> SmallVec<[(K, &V); N]> {
451 let before_count = N / 2;
453
454 #[cfg(not(feature = "interpolation"))]
455 {
456 let mut result = self
457 .values
458 .range(..key)
459 .rev()
460 .take(before_count)
461 .map(|(k, v)| (*k, v))
462 .collect::<SmallVec<[_; N]>>();
463 result.reverse();
464
465 let after_count = N - result.len();
467 result.extend(
468 self.values
469 .range(key..)
470 .take(after_count)
471 .map(|(k, v)| (*k, v)),
472 );
473 result
474 }
475
476 #[cfg(feature = "interpolation")]
477 {
478 let mut result = self
479 .values
480 .range(..key)
481 .rev()
482 .take(before_count)
483 .map(|(k, (v, _))| (*k, v))
484 .collect::<SmallVec<[_; N]>>();
485 result.reverse();
486
487 let after_count = N - result.len();
489 result.extend(
490 self.values
491 .range(key..)
492 .take(after_count)
493 .map(|(k, (v, _))| (*k, v)),
494 );
495 result
496 }
497 }
498}
499
500#[cfg(feature = "matrix3")]
507#[derive(Clone)]
508struct Trans2(f32, f32);
509
510#[cfg(feature = "matrix3")]
511impl Add for Trans2 {
512 type Output = Self;
513 fn add(self, rhs: Self) -> Self {
514 Trans2(self.0 + rhs.0, self.1 + rhs.1)
515 }
516}
517
518#[cfg(feature = "matrix3")]
519impl Sub for Trans2 {
520 type Output = Self;
521 fn sub(self, rhs: Self) -> Self {
522 Trans2(self.0 - rhs.0, self.1 - rhs.1)
523 }
524}
525
526#[cfg(feature = "matrix3")]
527impl Mul<f32> for Trans2 {
528 type Output = Self;
529 fn mul(self, s: f32) -> Self {
530 Trans2(self.0 * s, self.1 * s)
531 }
532}
533
534#[cfg(feature = "matrix3")]
536#[derive(Clone)]
537struct DiagStretch(f32, f32);
538
539#[cfg(feature = "matrix3")]
540impl Add for DiagStretch {
541 type Output = Self;
542 fn add(self, rhs: Self) -> Self {
543 DiagStretch(self.0 + rhs.0, self.1 + rhs.1)
544 }
545}
546
547#[cfg(feature = "matrix3")]
548impl Sub for DiagStretch {
549 type Output = Self;
550 fn sub(self, rhs: Self) -> Self {
551 DiagStretch(self.0 - rhs.0, self.1 - rhs.1)
552 }
553}
554
555#[cfg(feature = "matrix3")]
556impl Mul<f32> for DiagStretch {
557 type Output = Self;
558 fn mul(self, s: f32) -> Self {
559 DiagStretch(self.0 * s, self.1 * s)
560 }
561}
562
563#[cfg(feature = "matrix3")]
565#[inline(always)]
566fn interpolate_rotation(map: &BTreeMap<Time, f32>, time: Time) -> f32 {
567 if map.len() == 1 {
568 return *map.values().next().unwrap();
569 }
570
571 let first = map.iter().next().unwrap();
572 let last = map.iter().next_back().unwrap();
573
574 if time <= *first.0 {
575 return *first.1;
576 }
577
578 if time >= *last.0 {
579 return *last.1;
580 }
581
582 let lower = map.range(..=time).next_back().unwrap();
583 let upper = map.range(time..).next().unwrap();
584
585 let t0 = f32::from(*lower.0);
586 let t1 = f32::from(*upper.0);
587 let a0 = *lower.1;
588 let a1 = *upper.1;
589
590 let t: f32 = (f32::from(time) - t0) / (t1 - t0);
592
593 use std::f32::consts::{PI, TAU};
595 let mut diff = a1 - a0;
596 if diff > PI {
597 diff -= TAU;
598 } else if diff < -PI {
599 diff += TAU;
600 }
601 a0 + diff * t
602}
603
604#[cfg(feature = "interpolation")]
607fn bezier_handle_to_slope<V>(
608 handle: &crate::BezierHandle<V>,
609 t1: f32,
610 t2: f32,
611 _v1: &V,
612 _v2: &V,
613) -> Option<V>
614where
615 V: Clone + Add<Output = V> + Sub<Output = V> + Mul<f32, Output = V>,
616{
617 match handle {
618 crate::BezierHandle::SlopePerSecond(s) => Some(s.clone()),
619 crate::BezierHandle::SlopePerFrame(s) => {
620 let frames = (t2 - t1).max(f32::EPSILON);
621 Some(s.clone() * (frames / (t2 - t1)))
622 }
623 crate::BezierHandle::Delta { time, value } => {
624 let time_f32: f32 = (*time).into();
625 if time_f32.abs() <= f32::EPSILON {
626 None
627 } else {
628 Some(value.clone() * (1.0 / time_f32))
629 }
630 }
631 crate::BezierHandle::Angle(_) => None, }
633}
634
635#[cfg(feature = "interpolation")]
636#[allow(clippy::too_many_arguments)]
637fn smooth_tangent<K, V>(
638 t1: f32,
639 v1: &V,
640 t2: f32,
641 v2: &V,
642 map: &BTreeMap<K, (V, Option<crate::Key<V>>)>,
643 _key: K,
644 anchor: K,
645 incoming: bool,
646) -> V
647where
648 K: Ord + Copy + Into<f32>,
649 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
650{
651 use smallvec::SmallVec;
652
653 let mut window = SmallVec::<[(K, V); 2]>::new();
655
656 if incoming {
657 if let Some(prev) = map.range(..anchor).next_back() {
658 window.push((*prev.0, prev.1.0.clone()));
659 }
660 window.push((anchor, v1.clone()));
661 } else {
662 window.push((anchor, v1.clone()));
663 if let Some(next) = map.range(anchor..).nth(1) {
664 window.push((*next.0, next.1.0.clone()));
665 }
666 }
667
668 if window.len() == 2 {
669 let (k0, p0) = &window[0];
670 let (k1, p1) = &window[1];
671 let k0_f: f32 = (*k0).into();
672 let k1_f: f32 = (*k1).into();
673 let dt = (k1_f - k0_f).max(f32::EPSILON);
674 (p1.clone() - p0.clone()) * (1.0 / dt)
675 } else {
676 (v2.clone() - v1.clone()) * (1.0 / (t2 - t1).max(f32::EPSILON))
678 }
679}
680
681#[cfg(feature = "interpolation")]
682fn evaluate_mixed_bezier<K, V>(
683 key: K,
684 k1: K,
685 v1: &V,
686 slope_out: &V,
687 k2: K,
688 v2: &V,
689 slope_in: &V,
690) -> V
691where
692 K: Copy + Into<f32>,
693 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
694{
695 use crate::interpolation::bezier_helpers::*;
696
697 let (p1, p2) = control_points_from_slopes(k1.into(), v1, slope_out, k2.into(), v2, slope_in);
698
699 evaluate_bezier_component_wise(
700 key.into(),
701 (k1.into(), v1),
702 (p1.0, &p1.1),
703 (p2.0, &p2.1),
704 (k2.into(), v2),
705 )
706}
707
708#[cfg(feature = "interpolation")]
713#[inline(always)]
714pub(crate) fn interpolate_with_specs<K, V>(
715 map: &BTreeMap<K, (V, Option<crate::Key<V>>)>,
716 key: K,
717) -> V
718where
719 K: Ord + Copy + Into<f32>,
720 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
721{
722 if map.len() == 1 {
723 return map.values().next().unwrap().0.clone();
724 }
725
726 let first = map.iter().next().unwrap();
727 let last = map.iter().next_back().unwrap();
728
729 if key <= *first.0 {
730 return first.1.0.clone();
731 }
732
733 if key >= *last.0 {
734 return last.1.0.clone();
735 }
736
737 let lower = map.range(..key).next_back().unwrap();
739 let upper = map.range(key..).next().unwrap();
740
741 if lower.0 == upper.0 {
743 return lower.1.0.clone();
744 }
745
746 let (k1, (v1, spec1)) = lower;
747 let (k2, (v2, spec2)) = upper;
748
749 let interp_out = spec1.as_ref().map(|s| &s.interpolation_out);
751 let interp_in = spec2.as_ref().map(|s| &s.interpolation_in);
752
753 match (interp_out, interp_in) {
754 (Some(crate::Interpolation::Hold), _) | (_, Some(crate::Interpolation::Hold)) => v1.clone(),
756
757 (
759 Some(crate::Interpolation::Bezier(out_handle)),
760 Some(crate::Interpolation::Bezier(in_handle)),
761 ) => {
762 use crate::interpolation::bezier_helpers::*;
763
764 if let (Some(slope_out), Some(slope_in)) = (
765 bezier_handle_to_slope(out_handle, (*k1).into(), (*k2).into(), v1, v2),
766 bezier_handle_to_slope(in_handle, (*k1).into(), (*k2).into(), v1, v2),
767 ) {
768 let (p1, p2) = control_points_from_slopes(
769 (*k1).into(),
770 v1,
771 &slope_out,
772 (*k2).into(),
773 v2,
774 &slope_in,
775 );
776
777 evaluate_bezier_component_wise(
778 key.into(),
779 ((*k1).into(), v1),
780 (p1.0, &p1.1),
781 (p2.0, &p2.1),
782 ((*k2).into(), v2),
783 )
784 } else {
785 linear_interp(*k1, *k2, v1, v2, key)
787 }
788 }
789
790 (Some(crate::Interpolation::Bezier(out_handle)), Some(crate::Interpolation::Smooth)) => {
792 if let Some(slope_out) =
793 bezier_handle_to_slope(out_handle, (*k1).into(), (*k2).into(), v1, v2)
794 {
795 let slope_in =
796 smooth_tangent((*k1).into(), v1, (*k2).into(), v2, map, key, *k1, false);
797
798 evaluate_mixed_bezier(key, *k1, v1, &slope_out, *k2, v2, &slope_in)
799 } else {
800 linear_interp(*k1, *k2, v1, v2, key)
801 }
802 }
803 (Some(crate::Interpolation::Smooth), Some(crate::Interpolation::Bezier(in_handle))) => {
804 if let Some(slope_in) =
805 bezier_handle_to_slope(in_handle, (*k1).into(), (*k2).into(), v1, v2)
806 {
807 let slope_out =
808 smooth_tangent((*k1).into(), v1, (*k2).into(), v2, map, key, *k1, true);
809
810 evaluate_mixed_bezier(key, *k1, v1, &slope_out, *k2, v2, &slope_in)
811 } else {
812 linear_interp(*k1, *k2, v1, v2, key)
813 }
814 }
815
816 (Some(crate::Interpolation::Smooth), Some(crate::Interpolation::Smooth)) | (None, None) => {
818 let values_only: BTreeMap<K, V> =
819 map.iter().map(|(k, (v, _))| (*k, v.clone())).collect();
820 interpolate(&values_only, key)
821 }
822
823 _ => linear_interp(*k1, *k2, v1, v2, key),
825 }
826}
827
828#[inline(always)]
829pub(crate) fn interpolate<K, V>(map: &BTreeMap<K, V>, key: K) -> V
830where
831 K: Ord + Copy + Into<f32>,
832 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
833{
834 if map.len() == 1 {
835 return map.values().next().unwrap().clone();
836 }
837
838 let first = map.iter().next().unwrap();
839 let last = map.iter().next_back().unwrap();
840
841 if key <= *first.0 {
842 return first.1.clone();
843 }
844
845 if key >= *last.0 {
846 return last.1.clone();
847 }
848
849 let lower = map.range(..key).next_back().unwrap();
850 let upper = map.range(key..).next().unwrap();
851
852 let mut window = SmallVec::<[(K, &V); 4]>::new();
857
858 window.extend(map.range(..*lower.0).rev().take(2).map(|(k, v)| (*k, v)));
860
861 window.push((*lower.0, lower.1));
863
864 if lower.0 != upper.0 {
865 window.push((*upper.0, upper.1));
866 }
867
868 window.extend(map.range(*upper.0..).skip(1).take(1).map(|(k, v)| (*k, v)));
870
871 window.reverse();
873
874 match window.len() {
875 4 => {
876 let (t0, p0) = window[0];
877 let (t1, p1) = window[1];
878 let (t2, p2) = window[2];
879 let (t3, p3) = window[3];
880 hermite_interp(HermiteParams {
881 t0,
882 t1,
883 t2,
884 t3,
885 p0,
886 p1,
887 p2,
888 p3,
889 t: key,
890 })
891 }
892 3 => {
893 let (t0, p0) = window[0];
894 let (t1, p1) = window[1];
895 let (t2, p2) = window[2];
896 quadratic_interp(t0, t1, t2, p0, p1, p2, key)
897 }
898 2 => {
899 let (x0, y0) = window[0];
900 let (x1, y1) = window[1];
901 linear_interp(x0, x1, y0, y1, key)
902 }
903 1 => {
904 window[0].1.clone()
906 }
907 0 => {
908 panic!("Interpolation window is empty - this is a bug in token-value-map")
910 }
911 _ => {
912 let (t0, p0) = window[0];
914 let (t1, p1) = window[1];
915 let (t2, p2) = window[2];
916 let (t3, p3) = window[3];
917 hermite_interp(HermiteParams {
918 t0,
919 t1,
920 t2,
921 t3,
922 p0,
923 p1,
924 p2,
925 p3,
926 t: key,
927 })
928 }
929 }
930}
931
932#[inline(always)]
933fn linear_interp<V, T>(x0: T, x1: T, y0: &V, y1: &V, x: T) -> V
934where
935 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
936 T: Into<f32>,
937{
938 let x0 = x0.into();
939 let x1 = x1.into();
940 let x = x.into();
941 let alpha = (x - x0) / (x1 - x0);
942 y0.clone() + (y1.clone() - y0.clone()) * alpha
943}
944
945#[inline(always)]
946fn quadratic_interp<V, T>(x0: T, x1: T, x2: T, y0: &V, y1: &V, y2: &V, x: T) -> V
947where
948 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
949 T: Into<f32>,
950{
951 let x0 = x0.into();
952 let x1 = x1.into();
953 let x2 = x2.into();
954 let x = x.into();
955 let a = (x - x1) * (x - x2) / ((x0 - x1) * (x0 - x2));
956 let b = (x - x0) * (x - x2) / ((x1 - x0) * (x1 - x2));
957 let c = (x - x0) * (x - x1) / ((x2 - x0) * (x2 - x1));
958
959 y0.clone() * a + y1.clone() * b + y2.clone() * c
960}
961
962struct HermiteParams<V, T> {
963 t0: T,
964 t1: T,
965 t2: T,
966 t3: T,
967 p0: V,
968 p1: V,
969 p2: V,
970 p3: V,
971 t: T,
972}
973
974#[inline(always)]
975fn hermite_interp<V, T>(params: HermiteParams<&V, T>) -> V
976where
977 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
978 T: Into<f32>,
979{
980 let t0 = params.t0.into();
981 let t1 = params.t1.into();
982 let t2 = params.t2.into();
983 let t3 = params.t3.into();
984 let t = params.t.into();
985
986 let tau = if (t2 - t1).abs() < f32::EPSILON {
988 0.0 } else {
990 (t - t1) / (t2 - t1)
991 };
992
993 let tension1 = if (t1 - t0).abs() < f32::EPSILON {
997 1.0
998 } else {
999 (t2 - t1) / (t1 - t0)
1000 };
1001 let tension2 = if (t3 - t2).abs() < f32::EPSILON {
1002 1.0
1003 } else {
1004 (t2 - t1) / (t3 - t2)
1005 };
1006
1007 let m1 = (params.p2.clone() - params.p0.clone()) * (0.5 * tension1);
1009 let m2 = (params.p3.clone() - params.p1.clone()) * (0.5 * tension2);
1010
1011 let tau2 = tau * tau;
1013 let tau3 = tau2 * tau;
1014
1015 let h00 = 2.0 * tau3 - 3.0 * tau2 + 1.0;
1016 let h10 = tau3 - 2.0 * tau2 + tau;
1017 let h01 = -2.0 * tau3 + 3.0 * tau2;
1018 let h11 = tau3 - tau2;
1019
1020 params.p1.clone() * h00 + m1 * h10 + params.p2.clone() * h01 + m2 * h11
1022}
1023
1024#[cfg(feature = "matrix3")]
1029#[inline(always)]
1030fn decompose_matrix(matrix: &crate::math::Mat3Impl) -> (Trans2, f32, DiagStretch) {
1031 use crate::math::mat3;
1032
1033 let tx = mat3(matrix, 0, 2);
1035 let ty = mat3(matrix, 1, 2);
1036
1037 let a = mat3(matrix, 0, 0);
1039 let b = mat3(matrix, 0, 1);
1040 let c = mat3(matrix, 1, 0);
1041 let d = mat3(matrix, 1, 1);
1042
1043 let e = (a + d) * 0.5;
1045 let f = (a - d) * 0.5;
1046 let g = (c + b) * 0.5;
1047 let h = (c - b) * 0.5;
1048
1049 let q = (e * e + h * h).sqrt();
1050 let r = (f * f + g * g).sqrt();
1051
1052 let s1 = q + r;
1053 let s2 = q - r;
1054
1055 let theta1 = g.atan2(f);
1056 let theta2 = h.atan2(e);
1057
1058 let rotation_angle = (theta2 + theta1) * 0.5;
1060
1061 (Trans2(tx, ty), rotation_angle, DiagStretch(s1, s2))
1062}
1063
1064#[cfg(feature = "matrix3")]
1068#[inline(always)]
1069fn recompose_matrix(
1070 translation: Trans2,
1071 rotation_angle: f32,
1072 stretch: DiagStretch,
1073) -> crate::math::Mat3Impl {
1074 let cos = rotation_angle.cos();
1075 let sin = rotation_angle.sin();
1076
1077 crate::math::mat3_from_column_slice(&[
1079 stretch.0 * cos,
1080 stretch.0 * sin,
1081 0.0,
1082 -stretch.1 * sin,
1083 stretch.1 * cos,
1084 0.0,
1085 translation.0,
1086 translation.1,
1087 1.0,
1088 ])
1089}