1 module plot2d.interp;
2 
3 auto lineInterp(RV, RK)(RV vals, RK keys, float t)
4 {
5     import std.range;
6 
7     typeof(keys.front) ak = keys.front, bk = keys.front;
8     typeof(vals.front) av = vals.front, bv = vals.front;
9 
10     if (t < keys.front) return vals.front;
11     
12     bool pair = true;
13 
14     foreach (k, v; lockstep(keys, vals))
15     {
16         if (t < k)
17         {
18             bk = k;
19             bv = v;
20             pair = true;
21             break;
22         }
23         ak = k;
24         av = v;
25         pair = false;
26     }
27 
28     if (!pair) return av;
29 
30     auto c = (t - ak) / (bk - ak);
31     return av + (bv - av) * c;
32 }
33 
34 unittest
35 {
36     import std.math;
37     auto v = [1.0f, 4, 5];
38     auto k = [0.0f, 1.0f, 2.0f];
39 
40     enum eps = float.epsilon;
41     assert(fabs(lineInterp(v, k, -1) - v[0]) < eps);
42     assert(fabs(lineInterp(v, k,  0) - v[0]) < eps);
43     assert(fabs(lineInterp(v, k,  0.5) - 2.5) < eps);
44     assert(fabs(lineInterp(v, k,  1) - 4) < eps);
45     assert(fabs(lineInterp(v, k,  1.5) - 4.5) < eps);
46     assert(fabs(lineInterp(v, k,  2) - 5) < eps);
47     assert(fabs(lineInterp(v, k,  3) - 5) < eps);
48 }
49 
50 T bezierInterp(size_t N, T)(auto ref const T[N] p, float t)
51 {
52     static if (N > 2)
53     {
54         T[N-1] tmp;
55         foreach (i; 0 .. N-1)
56             tmp[i] = p[i] + (p[i+1] - p[i]) * t;
57         return bezierInterp(tmp, t);
58     }
59     else static if (N==2)
60         return p[0] + (p[1] - p[0]) * t;
61     else static assert(0, "need min 2 values for interpolation");
62 }