1use crate::smooth_array::SmoothArray;
2use crate::{Curve, CurvePoint, Distance};
3use num_traits::Float;
4use std::marker::PhantomData;
5
6pub struct LinearSpeed<F: Float, P: CurvePoint<F> + Distance<F>, C: Curve<F, P>> {
8 curve: C,
9 length: F,
10 table: SmoothArray<F>,
11 phantom_data: PhantomData<P>,
12}
13
14impl<F: Float, P: CurvePoint<F> + Distance<F>, C: Curve<F, P>> LinearSpeed<F, P, C> {
15 pub fn new(curve: C, table_size: usize, steps_count: usize) -> Self {
16 let mut table = SmoothArray::with_steps_count(table_size);
17
18 let mut last_point = curve.value_at(F::zero());
19 let mut total_length = F::zero();
20
21 let mut t_by_offset: Vec<(F, F)> = Vec::with_capacity(steps_count + 1);
22 t_by_offset.push((F::zero(), F::zero()));
23
24 let inverted_steps = F::one() / F::from(steps_count).unwrap();
25
26 for i in 1..=steps_count {
27 let t = F::from(i).unwrap() * inverted_steps;
28 let point = curve.value_at(t);
29 let segment_length = last_point.distance(&point);
30 total_length = total_length + segment_length;
31 t_by_offset.push((total_length, t));
32 last_point = point;
33 }
34
35 let inverted_length = F::one() / total_length;
36 t_by_offset.windows(2).for_each(|window| {
37 let (offset1, t1) = window[0];
38 let (offset2, t2) = window[1];
39 table.line(
40 (offset1 * inverted_length, t1),
41 (offset2 * inverted_length, t2),
42 );
43 });
44
45 Self {
46 curve,
47 length: total_length,
48 table,
49 phantom_data: Default::default(),
50 }
51 }
52}
53
54impl<F: Float, P: CurvePoint<F> + Distance<F>, C: Curve<F, P>> Curve<F, P>
55 for LinearSpeed<F, P, C>
56{
57 fn value_at(&self, t: F) -> P {
58 self.curve.value_at(t)
59 }
60
61 fn tangent_at(&self, t: F) -> P {
62 let t = t.clamp(F::zero(), F::one());
63 let t = self.table.value_at(t);
64 self.curve.tangent_at(t).scale(self.table.tangent_at(t))
65 }
66
67 fn start_point(&self) -> P {
68 self.curve.start_point()
69 }
70
71 fn end_point(&self) -> P {
72 self.curve.end_point()
73 }
74
75 fn estimate_length(&self, _precision: F) -> F {
76 self.length
77 }
78}