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 sample_closest_at(&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 #[deprecated(since = "0.2.3", note = "renamed to `sample_closest_at`")]
530 pub fn closest_sample(&self, key: K) -> &V {
531 self.sample_closest_at(key)
532 }
533}
534
535#[cfg(feature = "matrix3")]
542#[derive(Clone)]
543struct Trans2(f32, f32);
544
545#[cfg(feature = "matrix3")]
546impl Add for Trans2 {
547 type Output = Self;
548 fn add(self, rhs: Self) -> Self {
549 Trans2(self.0 + rhs.0, self.1 + rhs.1)
550 }
551}
552
553#[cfg(feature = "matrix3")]
554impl Sub for Trans2 {
555 type Output = Self;
556 fn sub(self, rhs: Self) -> Self {
557 Trans2(self.0 - rhs.0, self.1 - rhs.1)
558 }
559}
560
561#[cfg(feature = "matrix3")]
562impl Mul<f32> for Trans2 {
563 type Output = Self;
564 fn mul(self, s: f32) -> Self {
565 Trans2(self.0 * s, self.1 * s)
566 }
567}
568
569#[cfg(feature = "matrix3")]
571#[derive(Clone)]
572struct DiagStretch(f32, f32);
573
574#[cfg(feature = "matrix3")]
575impl Add for DiagStretch {
576 type Output = Self;
577 fn add(self, rhs: Self) -> Self {
578 DiagStretch(self.0 + rhs.0, self.1 + rhs.1)
579 }
580}
581
582#[cfg(feature = "matrix3")]
583impl Sub for DiagStretch {
584 type Output = Self;
585 fn sub(self, rhs: Self) -> Self {
586 DiagStretch(self.0 - rhs.0, self.1 - rhs.1)
587 }
588}
589
590#[cfg(feature = "matrix3")]
591impl Mul<f32> for DiagStretch {
592 type Output = Self;
593 fn mul(self, s: f32) -> Self {
594 DiagStretch(self.0 * s, self.1 * s)
595 }
596}
597
598#[cfg(feature = "matrix3")]
600#[inline(always)]
601fn interpolate_rotation(map: &BTreeMap<Time, f32>, time: Time) -> f32 {
602 if map.len() == 1 {
603 return *map.values().next().unwrap();
605 }
606
607 let first = map.iter().next().unwrap();
609 let last = map.iter().next_back().unwrap();
610
611 if time <= *first.0 {
612 return *first.1;
613 }
614
615 if time >= *last.0 {
616 return *last.1;
617 }
618
619 let lower = map.range(..=time).next_back().unwrap();
621 let upper = map.range(time..).next().unwrap();
622
623 let t0 = f32::from(*lower.0);
624 let t1 = f32::from(*upper.0);
625 let a0 = *lower.1;
626 let a1 = *upper.1;
627
628 let t: f32 = (f32::from(time) - t0) / (t1 - t0);
630
631 use std::f32::consts::{PI, TAU};
633 let mut diff = a1 - a0;
634 if diff > PI {
635 diff -= TAU;
636 } else if diff < -PI {
637 diff += TAU;
638 }
639 a0 + diff * t
640}
641
642#[cfg(feature = "interpolation")]
645fn bezier_handle_to_slope<V>(
646 handle: &crate::BezierHandle<V>,
647 t1: f32,
648 t2: f32,
649 _v1: &V,
650 _v2: &V,
651) -> Option<V>
652where
653 V: Clone + Add<Output = V> + Sub<Output = V> + Mul<f32, Output = V>,
654{
655 match handle {
656 crate::BezierHandle::SlopePerSecond(s) => Some(s.clone()),
657 crate::BezierHandle::SlopePerFrame(s) => {
658 let frames = (t2 - t1).max(f32::EPSILON);
659 Some(s.clone() * (frames / (t2 - t1)))
660 }
661 crate::BezierHandle::Delta { time, value } => {
662 let time_f32: f32 = (*time).into();
663 if time_f32.abs() <= f32::EPSILON {
664 None
665 } else {
666 Some(value.clone() * (1.0 / time_f32))
667 }
668 }
669 crate::BezierHandle::Angle(_) => None, }
671}
672
673#[cfg(feature = "interpolation")]
674#[allow(clippy::too_many_arguments)]
675fn smooth_tangent<K, V>(
676 t1: f32,
677 v1: &V,
678 t2: f32,
679 v2: &V,
680 map: &BTreeMap<K, (V, Option<crate::Key<V>>)>,
681 _key: K,
682 anchor: K,
683 incoming: bool,
684) -> V
685where
686 K: Ord + Copy + Into<f32>,
687 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
688{
689 use smallvec::SmallVec;
690
691 let mut window = SmallVec::<[(K, V); 2]>::new();
693
694 if incoming {
695 if let Some(prev) = map.range(..anchor).next_back() {
696 window.push((*prev.0, prev.1.0.clone()));
697 }
698 window.push((anchor, v1.clone()));
699 } else {
700 window.push((anchor, v1.clone()));
701 if let Some(next) = map.range(anchor..).nth(1) {
702 window.push((*next.0, next.1.0.clone()));
703 }
704 }
705
706 if window.len() == 2 {
707 let (k0, p0) = &window[0];
708 let (k1, p1) = &window[1];
709 let k0_f: f32 = (*k0).into();
710 let k1_f: f32 = (*k1).into();
711 let dt = (k1_f - k0_f).max(f32::EPSILON);
712 (p1.clone() - p0.clone()) * (1.0 / dt)
713 } else {
714 (v2.clone() - v1.clone()) * (1.0 / (t2 - t1).max(f32::EPSILON))
716 }
717}
718
719#[cfg(feature = "interpolation")]
720fn evaluate_mixed_bezier<K, V>(
721 key: K,
722 k1: K,
723 v1: &V,
724 slope_out: &V,
725 k2: K,
726 v2: &V,
727 slope_in: &V,
728) -> V
729where
730 K: Copy + Into<f32>,
731 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
732{
733 use crate::interpolation::bezier_helpers::*;
734
735 let (p1, p2) = control_points_from_slopes(k1.into(), v1, slope_out, k2.into(), v2, slope_in);
736
737 evaluate_bezier_component_wise(
738 key.into(),
739 (k1.into(), v1),
740 (p1.0, &p1.1),
741 (p2.0, &p2.1),
742 (k2.into(), v2),
743 )
744}
745
746#[cfg(feature = "interpolation")]
751#[inline(always)]
752pub(crate) fn interpolate_with_specs<K, V>(
753 map: &BTreeMap<K, (V, Option<crate::Key<V>>)>,
754 key: K,
755) -> V
756where
757 K: Ord + Copy + Into<f32>,
758 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
759{
760 if map.len() == 1 {
761 return map.values().next().unwrap().0.clone();
763 }
764
765 let first = map.iter().next().unwrap();
767 let last = map.iter().next_back().unwrap();
768
769 if key <= *first.0 {
770 return first.1.0.clone();
771 }
772
773 if key >= *last.0 {
774 return last.1.0.clone();
775 }
776
777 let lower = map.range(..key).next_back().unwrap();
779 let upper = map.range(key..).next().unwrap();
780
781 if lower.0 == upper.0 {
783 return lower.1.0.clone();
784 }
785
786 let (k1, (v1, spec1)) = lower;
787 let (k2, (v2, spec2)) = upper;
788
789 let interp_out = spec1.as_ref().map(|s| &s.interpolation_out);
791 let interp_in = spec2.as_ref().map(|s| &s.interpolation_in);
792
793 match (interp_out, interp_in) {
794 (Some(crate::Interpolation::Hold), _) | (_, Some(crate::Interpolation::Hold)) => v1.clone(),
796
797 (
799 Some(crate::Interpolation::Bezier(out_handle)),
800 Some(crate::Interpolation::Bezier(in_handle)),
801 ) => {
802 use crate::interpolation::bezier_helpers::*;
803
804 if let (Some(slope_out), Some(slope_in)) = (
805 bezier_handle_to_slope(out_handle, (*k1).into(), (*k2).into(), v1, v2),
806 bezier_handle_to_slope(in_handle, (*k1).into(), (*k2).into(), v1, v2),
807 ) {
808 let (p1, p2) = control_points_from_slopes(
809 (*k1).into(),
810 v1,
811 &slope_out,
812 (*k2).into(),
813 v2,
814 &slope_in,
815 );
816
817 evaluate_bezier_component_wise(
818 key.into(),
819 ((*k1).into(), v1),
820 (p1.0, &p1.1),
821 (p2.0, &p2.1),
822 ((*k2).into(), v2),
823 )
824 } else {
825 linear_interp(*k1, *k2, v1, v2, key)
827 }
828 }
829
830 (Some(crate::Interpolation::Bezier(out_handle)), Some(crate::Interpolation::Smooth)) => {
832 if let Some(slope_out) =
833 bezier_handle_to_slope(out_handle, (*k1).into(), (*k2).into(), v1, v2)
834 {
835 let slope_in =
836 smooth_tangent((*k1).into(), v1, (*k2).into(), v2, map, key, *k1, false);
837
838 evaluate_mixed_bezier(key, *k1, v1, &slope_out, *k2, v2, &slope_in)
839 } else {
840 linear_interp(*k1, *k2, v1, v2, key)
841 }
842 }
843 (Some(crate::Interpolation::Smooth), Some(crate::Interpolation::Bezier(in_handle))) => {
844 if let Some(slope_in) =
845 bezier_handle_to_slope(in_handle, (*k1).into(), (*k2).into(), v1, v2)
846 {
847 let slope_out =
848 smooth_tangent((*k1).into(), v1, (*k2).into(), v2, map, key, *k1, true);
849
850 evaluate_mixed_bezier(key, *k1, v1, &slope_out, *k2, v2, &slope_in)
851 } else {
852 linear_interp(*k1, *k2, v1, v2, key)
853 }
854 }
855
856 (Some(crate::Interpolation::Smooth), Some(crate::Interpolation::Smooth)) | (None, None) => {
858 let values_only: BTreeMap<K, V> =
859 map.iter().map(|(k, (v, _))| (*k, v.clone())).collect();
860 interpolate(&values_only, key)
861 }
862
863 _ => linear_interp(*k1, *k2, v1, v2, key),
865 }
866}
867
868#[inline(always)]
869pub(crate) fn interpolate<K, V>(map: &BTreeMap<K, V>, key: K) -> V
870where
871 K: Ord + Copy + Into<f32>,
872 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
873{
874 if map.len() == 1 {
875 return map.values().next().unwrap().clone();
877 }
878
879 let first = map.iter().next().unwrap();
881 let last = map.iter().next_back().unwrap();
882
883 if key <= *first.0 {
884 return first.1.clone();
885 }
886
887 if key >= *last.0 {
888 return last.1.clone();
889 }
890
891 let lower = map.range(..key).next_back().unwrap();
893 let upper = map.range(key..).next().unwrap();
894
895 let mut window = SmallVec::<[(K, &V); 4]>::new();
900
901 window.extend(map.range(..*lower.0).rev().take(2).map(|(k, v)| (*k, v)));
903
904 window.push((*lower.0, lower.1));
906
907 if lower.0 != upper.0 {
908 window.push((*upper.0, upper.1));
909 }
910
911 window.extend(map.range(*upper.0..).skip(1).take(1).map(|(k, v)| (*k, v)));
913
914 window.reverse();
916
917 match window.len() {
918 4 => {
919 let (t0, p0) = window[0];
920 let (t1, p1) = window[1];
921 let (t2, p2) = window[2];
922 let (t3, p3) = window[3];
923 hermite_interp(HermiteParams {
924 t0,
925 t1,
926 t2,
927 t3,
928 p0,
929 p1,
930 p2,
931 p3,
932 t: key,
933 })
934 }
935 3 => {
936 let (t0, p0) = window[0];
937 let (t1, p1) = window[1];
938 let (t2, p2) = window[2];
939 quadratic_interp(t0, t1, t2, p0, p1, p2, key)
940 }
941 2 => {
942 let (x0, y0) = window[0];
943 let (x1, y1) = window[1];
944 linear_interp(x0, x1, y0, y1, key)
945 }
946 1 => {
947 window[0].1.clone()
949 }
950 0 => {
951 panic!("Interpolation window is empty - this is a bug in token-value-map")
953 }
954 _ => {
955 let (t0, p0) = window[0];
957 let (t1, p1) = window[1];
958 let (t2, p2) = window[2];
959 let (t3, p3) = window[3];
960 hermite_interp(HermiteParams {
961 t0,
962 t1,
963 t2,
964 t3,
965 p0,
966 p1,
967 p2,
968 p3,
969 t: key,
970 })
971 }
972 }
973}
974
975#[inline(always)]
976fn linear_interp<V, T>(x0: T, x1: T, y0: &V, y1: &V, x: T) -> V
977where
978 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
979 T: Into<f32>,
980{
981 let x0 = x0.into();
982 let x1 = x1.into();
983 let x = x.into();
984 let alpha = (x - x0) / (x1 - x0);
985 y0.clone() + (y1.clone() - y0.clone()) * alpha
986}
987
988#[inline(always)]
989fn quadratic_interp<V, T>(x0: T, x1: T, x2: T, y0: &V, y1: &V, y2: &V, x: T) -> V
990where
991 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
992 T: Into<f32>,
993{
994 let x0 = x0.into();
995 let x1 = x1.into();
996 let x2 = x2.into();
997 let x = x.into();
998 let a = (x - x1) * (x - x2) / ((x0 - x1) * (x0 - x2));
999 let b = (x - x0) * (x - x2) / ((x1 - x0) * (x1 - x2));
1000 let c = (x - x0) * (x - x1) / ((x2 - x0) * (x2 - x1));
1001
1002 y0.clone() * a + y1.clone() * b + y2.clone() * c
1003}
1004
1005struct HermiteParams<V, T> {
1006 t0: T,
1007 t1: T,
1008 t2: T,
1009 t3: T,
1010 p0: V,
1011 p1: V,
1012 p2: V,
1013 p3: V,
1014 t: T,
1015}
1016
1017#[inline(always)]
1018fn hermite_interp<V, T>(params: HermiteParams<&V, T>) -> V
1019where
1020 V: Clone + Add<Output = V> + Mul<f32, Output = V> + Sub<Output = V>,
1021 T: Into<f32>,
1022{
1023 let t0 = params.t0.into();
1024 let t1 = params.t1.into();
1025 let t2 = params.t2.into();
1026 let t3 = params.t3.into();
1027 let t = params.t.into();
1028
1029 let tau = if (t2 - t1).abs() < f32::EPSILON {
1031 0.0 } else {
1033 (t - t1) / (t2 - t1)
1034 };
1035
1036 let tension1 = if (t1 - t0).abs() < f32::EPSILON {
1040 1.0
1041 } else {
1042 (t2 - t1) / (t1 - t0)
1043 };
1044 let tension2 = if (t3 - t2).abs() < f32::EPSILON {
1045 1.0
1046 } else {
1047 (t2 - t1) / (t3 - t2)
1048 };
1049
1050 let m1 = (params.p2.clone() - params.p0.clone()) * (0.5 * tension1);
1052 let m2 = (params.p3.clone() - params.p1.clone()) * (0.5 * tension2);
1053
1054 let tau2 = tau * tau;
1056 let tau3 = tau2 * tau;
1057
1058 let h00 = 2.0 * tau3 - 3.0 * tau2 + 1.0;
1059 let h10 = tau3 - 2.0 * tau2 + tau;
1060 let h01 = -2.0 * tau3 + 3.0 * tau2;
1061 let h11 = tau3 - tau2;
1062
1063 params.p1.clone() * h00 + m1 * h10 + params.p2.clone() * h01 + m2 * h11
1065}
1066
1067#[cfg(feature = "matrix3")]
1072#[inline(always)]
1073fn decompose_matrix(matrix: &crate::math::Mat3Impl) -> (Trans2, f32, DiagStretch) {
1074 use crate::math::mat3;
1075
1076 let tx = mat3(matrix, 0, 2);
1078 let ty = mat3(matrix, 1, 2);
1079
1080 let a = mat3(matrix, 0, 0);
1082 let b = mat3(matrix, 0, 1);
1083 let c = mat3(matrix, 1, 0);
1084 let d = mat3(matrix, 1, 1);
1085
1086 let e = (a + d) * 0.5;
1088 let f = (a - d) * 0.5;
1089 let g = (c + b) * 0.5;
1090 let h = (c - b) * 0.5;
1091
1092 let q = (e * e + h * h).sqrt();
1093 let r = (f * f + g * g).sqrt();
1094
1095 let s1 = q + r;
1096 let s2 = q - r;
1097
1098 let theta1 = g.atan2(f);
1099 let theta2 = h.atan2(e);
1100
1101 let rotation_angle = (theta2 + theta1) * 0.5;
1103
1104 (Trans2(tx, ty), rotation_angle, DiagStretch(s1, s2))
1105}
1106
1107#[cfg(feature = "matrix3")]
1111#[inline(always)]
1112fn recompose_matrix(
1113 translation: Trans2,
1114 rotation_angle: f32,
1115 stretch: DiagStretch,
1116) -> crate::math::Mat3Impl {
1117 let cos = rotation_angle.cos();
1118 let sin = rotation_angle.sin();
1119
1120 crate::math::mat3_from_column_slice(&[
1122 stretch.0 * cos,
1123 stretch.0 * sin,
1124 0.0,
1125 -stretch.1 * sin,
1126 stretch.1 * cos,
1127 0.0,
1128 translation.0,
1129 translation.1,
1130 1.0,
1131 ])
1132}