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