1 module mutils.timeline.trace;
2 
3 import mutils.container.sorted_vector;
4 import mutils.container.vector;
5 import mutils.linalg.algorithm;
6 import mutils.timeline.utils;
7 
8 /**
9  *
10  * Class to get interpolated(mix) T value in given time, useful for contigious paths 
11  * 
12  */
13 struct Trace(T, alias mixFunction = mix) {
14 	SortedVector!(DataPoint, "a.time < b.time") data;
15 	TimeIndexGetter indexGetter;
16 
17 	struct DataPoint {
18 		T point;
19 		float time = 0;
20 	}
21 
22 	void add(T point, float time) {
23 		data ~= DataPoint(point, time);
24 	}
25 
26 	void remove(size_t i) {
27 		data.remove(i);
28 	}
29 
30 	T get(ref TimeIndexGetter getter, ref float time, bool loop) {
31 		uint[2] ti = getter.index(data[], time);
32 		DataPoint curr = data[ti[0]];
33 		DataPoint next = data[ti[1]];
34 		if (ti[0] == ti[1]) {
35 			if (loop) {
36 				time = 0;
37 			}
38 			return curr.point;
39 		}
40 		float blend = (time - curr.time) / (next.time - curr.time);
41 		return mixFunction(curr.point, next.point, blend);
42 	}
43 
44 	T get(float time) {
45 		uint[2] ti = indexGetter.index(data[], time);
46 		DataPoint curr = data[ti[0]];
47 		DataPoint next = data[ti[1]];
48 		if (ti[0] == ti[1]) {
49 			return curr.point;
50 		}
51 		float blend = (time - curr.time) / (next.time - curr.time);
52 		return mixFunction(curr.point, next.point, blend);
53 	}
54 
55 }
56 
57 unittest {
58 	import mutils.linalg.vec;
59 
60 	alias vec2i = Vec!(int, 2); //ints because there are no precision errors
61 	alias TraceVec2i = Trace!(vec2i);
62 	TraceVec2i trace;
63 	trace.add(vec2i(0, 0), 0);
64 	trace.add(vec2i(0, 0), 2);
65 	trace.add(vec2i(2, 2), 1);
66 	trace.add(vec2i(2, 2), 3);
67 
68 	assert(trace.data[2].point == vec2i(0, 0));
69 
70 	assert(trace.get(-10) == vec2i(0, 0));
71 	assert(trace.get(0) == vec2i(0, 0));
72 	assert(trace.get(1) == vec2i(2, 2));
73 	assert(trace.get(2.5) == vec2i(1, 1));
74 	assert(trace.get(5) == vec2i(2, 2));
75 	assert(trace.get(-10) == vec2i(0, 0));
76 	assert(trace.get(0) == vec2i(0, 0));
77 }