1use num_traits::{Float, NumCast};
2
3use super::{Approximation, Curve, Threshold};
4use crate::threshold::{And, DisplacementThreshold, VelocityThreshold};
5
6#[derive(Copy, Clone)]
9pub struct Sampler<'a, C, T>
10where
11 C: Curve + ?Sized,
12 T: Threshold,
13{
14 curve: &'a C,
16
17 sample_rate: f32,
19
20 threshold: T,
21
22 time: f32,
24
25 exhausted: bool,
28}
29
30impl<'a, C, T> Sampler<'a, C, T>
31where
32 C: Curve + ?Sized,
33 T: Threshold<Value = C::Value>,
34{
35 pub fn with_threshold(curve: &'a C, sample_rate: f32, threshold: T) -> Sampler<'a, C, T> {
39 Sampler {
40 curve,
41 sample_rate,
42 threshold,
43 time: 0.0,
44 exhausted: false,
45 }
46 }
47
48 pub fn keyed(self) -> KeyedIter<'a, C, T> {
51 KeyedIter(self)
52 }
53}
54
55impl<'a, C, T> Sampler<'a, C, And<VelocityThreshold<T>, DisplacementThreshold<T>>>
56where
57 C: Curve<Value = T> + ?Sized,
58 T: Float,
59{
60 pub fn new(
64 curve: &'a C,
65 sample_rate: f32,
66 ) -> Sampler<'a, C, And<VelocityThreshold<T>, DisplacementThreshold<T>>> {
67 Sampler::with_thresholds(
68 curve,
69 sample_rate,
70 <T as NumCast>::from(0.001).unwrap(),
71 <T as NumCast>::from(0.001).unwrap(),
72 )
73 }
74
75 pub fn with_thresholds(
82 curve: &'a C,
83 sample_rate: f32,
84 rest_velocity_threshold: T,
85 rest_displacement_threshold: T,
86 ) -> Sampler<'a, C, And<VelocityThreshold<T>, DisplacementThreshold<T>>> {
87 Sampler::with_threshold(
88 curve,
89 sample_rate,
90 And(
91 VelocityThreshold(rest_velocity_threshold),
92 DisplacementThreshold {
93 target: curve.target(),
94 sensitivity: rest_displacement_threshold,
95 },
96 ),
97 )
98 }
99}
100
101impl<'a, C, T> Iterator for Sampler<'a, C, T>
102where
103 C: Curve + ?Sized,
104 T: Threshold<Value = C::Value, Velocity = C::Velocity>,
105{
106 type Item = Approximation<C::Value, C::Velocity>;
107
108 fn next(&mut self) -> Option<Self::Item> {
109 if self.exhausted {
110 return None;
111 }
112
113 let mut approx = self.curve.approximate(self.time);
114 self.time = self.time + 1.0 / self.sample_rate;
115
116 if self.threshold.evaluate(&approx) {
120 self.exhausted = true;
121
122 approx.value = self.curve.target();
123 }
124
125 Some(approx)
126 }
127}
128
129pub struct KeyedIter<'a, C, T>(Sampler<'a, C, T>)
132where
133 C: Curve + ?Sized,
134 T: Threshold<Value = C::Value>;
135
136impl<'a, C, T> Iterator for KeyedIter<'a, C, T>
137where
138 C: Curve + ?Sized,
139 T: Threshold<Value = C::Value, Velocity = C::Velocity>,
140{
141 type Item = (f32, Approximation<C::Value, C::Velocity>);
142
143 fn next(&mut self) -> Option<Self::Item> {
144 let time = self.0.time;
145 Some((time, self.0.next()?))
146 }
147}