Interpolation.h

00001 #ifndef INTERPOLATION_H_
00002 #define INTERPOLATION_H_
00003 
00004 #include <map>
00005 #include <algorithm>
00006 
00026 template<class V>
00027 class Interpolated {
00028 protected:
00029   V value;
00030 
00031 public:
00032   bool isInterpolated;
00033 
00034 public:
00035   Interpolated(V v, bool isIntpl = true):
00036     value(v), isInterpolated(isIntpl) {}
00037 
00038   V& operator*() {
00039     return value;
00040   }
00041 
00042   V* operator->() {
00043     return &value;
00044   }
00045 
00046   bool operator==(const Interpolated<V>& other) {
00047     return other.value == value && other.isInterpolated == isInterpolated;
00048   }
00049 
00050   bool operator!=(const Interpolated<V>& other) {
00051     return other.value != value || other.isInterpolated != isInterpolated;
00052   }
00053 };
00054 
00060 template<class Pair, class Key>
00061 class PairLess {
00062 public:
00063   bool operator()(const Pair& p, const Key& v) {
00064     return p.first < v;
00065   }
00066 
00067   bool operator()(const Key& v, const Pair& p) {
00068     return v < p.first;
00069   }
00070 };
00071 
00083 template<class Key, class V, class Pair, class InputIterator>
00084 class NextSmaller {
00085 public:
00086   typedef Interpolated<V> interpolated;
00087 protected:
00088 
00089   PairLess<Pair, Key> comp;
00090   bool continueOutOfRange;
00091   V outOfRangeVal;
00092 public:
00093   NextSmaller():
00094     continueOutOfRange(true) {}
00095 
00096   NextSmaller(V oorv):
00097     continueOutOfRange(false), outOfRangeVal(oorv) {}
00098 
00099   void setOutOfRangeVal(V oorv){
00100     outOfRangeVal = oorv;
00101   }
00102 
00103   interpolated operator()(const InputIterator& first,
00104               const InputIterator& last,
00105               const Key& pos) const{
00106 
00107     InputIterator right = std::upper_bound(first, last, pos, comp);
00108 
00109     return operator()(first, last, pos, right);
00110   }
00111 
00112   interpolated operator()(const InputIterator& first,
00113               const InputIterator& last,
00114               const Key& pos,
00115               InputIterator upperBound) const{
00116     if(first == last){
00117       if(continueOutOfRange)
00118         return interpolated(V());
00119       else
00120         return interpolated(outOfRangeVal);
00121     }
00122 
00123     if(upperBound == first){
00124       if(continueOutOfRange)
00125         return interpolated(upperBound->second);
00126       else
00127         return interpolated(outOfRangeVal);
00128     }
00129 
00130     upperBound--;
00131     if(upperBound->first == pos)
00132       return interpolated(upperBound->second, false);
00133 
00134     return interpolated(upperBound->second);
00135   }
00136 };
00137 
00146 template<class Key, class V, class Pair, class InputIterator>
00147 class Nearest {
00148 public:
00149   typedef Interpolated<V> interpolated;
00150 protected:
00151 
00152   PairLess<Pair, Key> comp;
00153   bool continueOutOfRange;
00154   V outOfRangeVal;
00155 public:
00156   Nearest():
00157     continueOutOfRange(true) {}
00158 
00159   Nearest(V oorv):
00160     continueOutOfRange(false), outOfRangeVal(oorv) {}
00161 
00162   void setOutOfRangeVal(V oorv){
00163     outOfRangeVal = oorv;
00164   }
00165 
00166   interpolated operator()(const InputIterator& first,
00167               const InputIterator& last,
00168               const Key& pos) const{
00169 
00170     InputIterator right = std::upper_bound(first, last, pos, comp);
00171 
00172     return operator()(first, last, pos, right);
00173   }
00174 
00175   interpolated operator()(const InputIterator& first,
00176               const InputIterator& last,
00177               const Key& pos,
00178               InputIterator upperBound) const{
00179     if(first == last){
00180       if(continueOutOfRange)
00181         return interpolated(V());
00182       else
00183         return interpolated(outOfRangeVal);
00184     }
00185 
00186     if(upperBound == first){
00187       if(continueOutOfRange)
00188         return interpolated(upperBound->second);
00189       else
00190         return interpolated(outOfRangeVal);
00191     }
00192 
00193     InputIterator left = upperBound;
00194     --left;
00195 
00196     if(left->first == pos)
00197       return interpolated(left->second, false);
00198 
00199     InputIterator right = upperBound;
00200 
00201     if(right == last){
00202       if(continueOutOfRange)
00203         return interpolated(left->second);
00204       else
00205         return interpolated(outOfRangeVal);
00206     }
00207 
00208     if(pos - left->first < right->first - pos)
00209       return interpolated(left->second);
00210     else
00211       return interpolated(right->second);
00212   }
00213 };
00214 
00222 template<class Key, class V, class Pair, class InputIterator>
00223 class Linear {
00224 public:
00225   typedef Interpolated<V> interpolated;
00226 protected:
00227 
00228   PairLess<Pair, Key> comp;
00229   bool continueOutOfRange;
00230   V outOfRangeVal;
00231 public:
00232   Linear():
00233     continueOutOfRange(true) {}
00234 
00235   Linear(V oorv):
00236     continueOutOfRange(false), outOfRangeVal(oorv) {}
00237 
00238   void setOutOfRangeVal(V oorv){
00239     outOfRangeVal = oorv;
00240   }
00241 
00242   static double linearInterpolation(const Key& t,
00243                     const Key& t0, const Key& t1,
00244                     const V& v0, const V& v1){
00245     return v0 + (v1 - v0) * (double)((t - t0) / (t1 - t0));
00246   }
00247 
00248   interpolated operator()(const InputIterator& first,
00249               const InputIterator& last,
00250               const Key& pos) const{
00251 
00252     InputIterator right = std::upper_bound(first, last, pos, comp);
00253 
00254     return operator()(first, last, pos, right);
00255   }
00256 
00257   interpolated operator()(const InputIterator& first,
00258               const InputIterator& last,
00259               const Key& pos,
00260               InputIterator upperBound) const{
00261     if(first == last){
00262       if(continueOutOfRange)
00263         return interpolated(V());
00264       else
00265         return interpolated(outOfRangeVal);
00266     }
00267 
00268     if(upperBound == first){
00269       if(continueOutOfRange)
00270         return interpolated(upperBound->second);
00271       else
00272         return interpolated(outOfRangeVal);
00273     }
00274 
00275     InputIterator right = upperBound;
00276     InputIterator left = --upperBound;
00277 
00278     if(left->first == pos)
00279       return interpolated(left->second, false);
00280 
00281     if(right == last){
00282       if(continueOutOfRange)
00283         return interpolated(left->second);
00284       else
00285         return interpolated(outOfRangeVal);
00286     }
00287 
00288     return interpolated(linearInterpolation(pos, left->first, right->first, left->second, right->second));
00289   }
00290 };
00291 
00335 template<class Key, class V,
00336      class Pair = const typename std::map<Key, V>::value_type,
00337      class Iterator = const typename std::map<Key, V>::const_iterator,
00338      class Interpolator = NextSmaller<Key, V, Pair, Iterator> >
00339 class ConstInterpolateableIterator {
00340 public:
00342   typedef Interpolated<V> interpolated;
00343 protected:
00344   Iterator first;
00345   Iterator last;
00346 
00347   Iterator right;
00348 
00349   Key position;
00350   const Interpolator& interpolate;
00351 
00352   PairLess<Pair, Key> comp;
00353 public:
00358   ConstInterpolateableIterator(Iterator first, Iterator last, const Interpolator& intpl):
00359     first(first), last(last), right(first), position(), interpolate(intpl), comp(){
00360 
00361     jumpToBegin();
00362   }
00363 
00364   bool operator==(const ConstInterpolateableIterator& other) {
00365     return position == other.position && right == other.right;
00366   }
00367 
00372   void jumpTo(const Key& pos) {
00373     if(pos == position)
00374       return;
00375 
00376     if(first != last)
00377       right = std::upper_bound(first, last, pos, comp);
00378 
00379     position = pos;
00380   }
00381 
00385   void jumpToBegin() {
00386     right = first;
00387     if(right != last) {
00388       position = right->first;
00389       right++;
00390     } else {
00391       position = Key();
00392     }
00393   }
00394 
00403   void iterateTo(const Key& pos) {
00404     if(pos == position)
00405       return;
00406 
00407     while(right != last && !(pos < right->first))
00408       right++;
00409 
00410     position = pos;
00411   }
00412 
00421   void next() {
00422     if(hasNext()) {
00423       position = right->first;
00424       right++;
00425     } else
00426       position += 1;
00427   }
00428 
00429   Key getNextPosition(){
00430     if(hasNext())
00431       return right->first;
00432     else
00433       return position + 1;
00434   }
00435 
00440   bool inRange() const{
00441     if(first == last)
00442       return false;
00443 
00444     Iterator tail = last;
00445 
00446     return !(position < first->first) && !((--tail)->first < position);
00447   }
00448 
00454   bool hasNext() const{
00455     return right != last;
00456   }
00457 
00464   interpolated getValue() const{
00465 
00466     return interpolate(first, last, position, right);
00467   }
00468 
00469   interpolated getNextValue() const{
00470     if(right == last)
00471       return interpolate(first, last, position + 1, right);
00472     else{
00473       Iterator tmp = right;
00474       return interpolate(first, last, right->first, ++tmp);
00475     }
00476   }
00477 
00481   Key getPosition() const{
00482     return position;
00483   }
00484 
00485 };
00486 
00503 template<class Key, class V,
00504      class Container = std::map<Key, V>,
00505      class Interpolator = NextSmaller<Key, V, typename Container::value_type, typename Container::const_iterator> >
00506 class InterpolateableIterator:public ConstInterpolateableIterator<Key, V,
00507                                     typename Container::value_type,
00508                                     typename Container::iterator,
00509                                     Interpolator>
00510 {
00511 protected:
00512   typedef typename Container::value_type value_type;
00513   typedef typename Container::iterator Iterator;
00514   typedef ConstInterpolateableIterator<Key,V,
00515                       value_type,
00516                       Iterator,
00517                       Interpolator> BaseClassType;
00518 
00519   Container& cont;
00520 
00521 public:
00522   InterpolateableIterator(Container& cont, const Interpolator& intpl):
00523     BaseClassType(cont.begin(), cont.end(), intpl), cont(cont) {}
00524 
00529   void setValue(const V& value) {
00530     //container is empty or position is smaller first entry
00531     if(this->right == this->first) {
00532       //insert new entry before first entry and store new entry as new first
00533       this->first = cont.insert(this->first, value_type(this->position, value));
00534 
00535     } else {
00536       Iterator left = this->right;
00537       left--;
00538       if(left->first == this->position) {
00539         left->second = value;
00540       } else {
00541         cont.insert(this->right, value_type(this->position, value));
00542       }
00543     }
00544   }
00545 };
00546 
00558 template<class Key, class V,
00559      class Interpolator = NextSmaller<Key, V, typename std::map<Key, V>::value_type, typename std::map<Key, V>::const_iterator> >
00560 class InterpolateableMap:public std::map<Key, V> {
00561 public:
00562   typedef std::map<Key, V> map_type;
00563   typedef typename map_type::const_iterator const_iterator;
00564   typedef typename map_type::iterator iterator;
00565   typedef typename map_type::value_type value_type;
00566   typedef InterpolateableIterator<Key, V, map_type, Interpolator> intpl_iterator;
00567   typedef ConstInterpolateableIterator<Key, V, const map_type,
00568                       typename map_type::const_iterator,
00569                       Interpolator> const_intpl_iterator;
00570   typedef Interpolated<V> interpolated;
00571 
00572 protected:
00573 
00574   Interpolator interpolate;
00575 public:
00576 
00577   InterpolateableMap() {}
00578 
00579   InterpolateableMap(V oorv):
00580     interpolate(oorv) {}
00581 
00582   void setOutOfRangeVal(V oorv){
00583     interpolate.setOutOfRangeVal(oorv);
00584   }
00585 
00586   interpolated getIntplValue(const Key& pos) const {
00587     //if(this->empty())
00588     //  return interpolated(V(), true);
00589 
00590     const_iterator it = this->upper_bound(pos);
00591 
00592     //if(it != this->end() && it->first == pos)
00593     //  return interpolated(it->second, false);
00594 
00595 
00596     return interpolate(this->begin(), this->end(), pos, it);
00597   }
00598 
00599   const_intpl_iterator findIntpl(const Key& pos) const{
00600     const_intpl_iterator it(this->begin(), this->end(), interpolate);
00601 
00602     it.jumpTo(pos);
00603 
00604     return it;
00605   }
00606 
00607   const_intpl_iterator beginIntpl() const{
00608     const_intpl_iterator it(this->begin(), this->end, interpolate);
00609 
00610     return it;
00611   }
00612 
00613   intpl_iterator findIntpl(const Key& pos) {
00614     intpl_iterator it(*this, interpolate);
00615 
00616     it.jumpTo(pos);
00617 
00618     return it;
00619   }
00620 
00621   intpl_iterator beginIntpl() {
00622     intpl_iterator it(*this, interpolate);
00623 
00624     return it;
00625   }
00626 };
00627 #endif /*INTERPOLATION_H_*/