This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Indoor/math/Interpolator.h
2018-10-25 11:50:12 +02:00

105 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* © Copyright 2014 Urheberrechtshinweis
* Alle Rechte vorbehalten / All Rights Reserved
*
* Programmcode ist urheberrechtlich geschuetzt.
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
* Keine Verwendung ohne explizite Genehmigung.
* (vgl. § 106 ff UrhG / § 97 UrhG)
*/
#ifndef INTERPOLATOR_H
#define INTERPOLATOR_H
#include "../Assertions.h"
#include "../Exception.h"
#include "../data/Timestamp.h"
#include <vector>
#include <algorithm>
/**
* interpolate between two adjacent values based on their key
*/
template <typename Key, typename Value> class Interpolator {
public:
/** value at key */
struct InterpolatorEntry {
Key key;
Value value;
InterpolatorEntry(const Key key, const Value& value) : key(key), value(value) {;}
};
protected:
/** all added entries, SORTED by their key */
std::vector<InterpolatorEntry> entries;
public:
/** add a new value with its key. entries must be added in sorted order! */
void add(const Key key, const Value& value) {
Assert::isTrue (entries.empty() || entries.back().key < key, "entries must be ordered!");
entries.push_back(InterpolatorEntry(key, value));
}
/** get the smallest added key */
Key getMinKey() const {return entries.front().key;}
/** get the largest added key */
Key getMaxKey() const {return entries.back().key;}
/** get the interpolated value for the given key */
Value get(const Key key) const {
const int idx2 = getIdxAfter(key);
if (idx2 == 0) {return entries.front().value;} // key < everything within the list
if (idx2 == -1) {return entries.back().value;} // key > everything within the list
// interpolate
const int idx1 = (idx2 > 0) ? (idx2 - 1) : (idx2);
const float percent = getPercent(key, entries[idx1].key, entries[idx2].key); //(key - entries[idx1].key) / (float) (entries[idx2].key - entries[idx1].key);
const Value res = entries[idx1].value + (entries[idx2].value - entries[idx1].value) * percent;
return res;
}
/** get a list of all raw entries */
const std::vector<InterpolatorEntry>& getEntries() const {
return entries;
}
protected:
/** special interpolation for the timestamp class */
static inline float getPercent(const Timestamp key, const Timestamp t1, const Timestamp t2) {
return (key - t1).ms() / (float) (t2 - t1).ms();
}
/** interpolation for generic datatypes [int, float, double, ..] */
template <typename T> static inline float getPercent(const T key, const T t1, const T t2) {
return (key - t1) / (float) (t2 - t1);
}
/** get the nearest index for the given key */
int getIdxAfter(const Key key) const {
// compare key against one entry
static auto comp = [] (const Key& key, const InterpolatorEntry& ie1) {return key < ie1.key;};
// find the next entry > than key
const auto it = std::upper_bound(entries.begin(), entries.end(), key, comp);
// none found? (key > everything within the list)
return (it == entries.end()) ? (-1) : (it-entries.begin());
//if (it == entries.end()) {throw Exception("key not found: " + std::to_string(key));}
//return it - entries.begin();
}
};
#endif // INTERPOLATOR_H