59 lines
1.6 KiB
C++
59 lines
1.6 KiB
C++
#ifndef INTERPOLATOR_H
|
|
#define INTERPOLATOR_H
|
|
|
|
#include <vector>
|
|
#include <algorithm>
|
|
|
|
|
|
namespace K {
|
|
|
|
/**
|
|
* this class allows adding values with some sort of key.
|
|
* hereafter it is possible to interpolate between two values
|
|
* using a provided key.
|
|
*/
|
|
template <typename Key, typename Value> class Interpolator {
|
|
|
|
/** combine key and value within one struct */
|
|
struct KeyedEntry {
|
|
Key key;
|
|
Value val;
|
|
KeyedEntry(const Key key, const Value& val) : key(key), val(val) {;}
|
|
};
|
|
|
|
public:
|
|
|
|
/** all entries within the interpolator */
|
|
std::vector<KeyedEntry> values;
|
|
|
|
public:
|
|
|
|
/** add a new timed entry */
|
|
void add(const Key key, const Value& val) {
|
|
values.push_back(KeyedEntry(key, val));
|
|
}
|
|
|
|
/** get the interpolated value for the given key */
|
|
Value get(const Key key) const {
|
|
auto comp = [] (const Key& key, const KeyedEntry& e) {return key < e.key;};
|
|
auto it = std::upper_bound(values.begin(), values.end(), key, comp); // first element > key
|
|
const KeyedEntry eH = *it; // greater than key
|
|
const KeyedEntry eL = *(--it); // smaller than key
|
|
const Key diff = eH.key - eL.key; // distance between upper and lower bound
|
|
const float vL = float(eH.key - key) / float(diff); // influence factor for the smaller one
|
|
const float vH = float(key - eL.key) / float(diff); // influence factor for the larger one
|
|
return (eH.val * vH) + (eL.val * vL); // interpolate
|
|
}
|
|
|
|
/** ensure the first key starts at 0 */
|
|
void makeRelative() {
|
|
const Key firstKey = values[0].key;
|
|
for (KeyedEntry& e : values) {e.key -= firstKey;}
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif // INTERPOLATOR_H
|