#pragma once #include "base/buffer_vector.hpp" #include "base/logging.hpp" #include namespace df { template class ValueMapping { /// double = interpolation point [0.0, 1.0] /// TValue = output value using TRangePoint = std::pair; using TRangeVector = buffer_vector; using TRangeIter = typename TRangeVector::const_iterator; public: ValueMapping() = default; void AddRangePoint(double t, TValue const & v) { #ifdef DEBUG if (!m_ranges.empty()) ASSERT(m_ranges.back().first < t, ()); #endif m_ranges.emplace_back(t, v); } TValue GetValue(double t) { TRangePoint startPoint, endPoint; GetRangePoints(t, startPoint, endPoint); double normT = t - startPoint.first; double rangeT = endPoint.first - startPoint.first; double rangeV = endPoint.second - startPoint.second; return startPoint.second + rangeV * normT / rangeT; } private: void GetRangePoints(double t, TRangePoint & startPoint, TRangePoint & endPoint) { ASSERT(t >= 0.0 && t <= 1.0, ()); ASSERT(m_ranges.size() > 1, ()); TRangeIter startIter = m_ranges.begin(); if (t < startIter->first) { startPoint.first = 0.0; startPoint.second = TValue(); endPoint = *startIter; return; } TRangeIter endIter = startIter + 1; while (t > endIter->first) { endIter++; ASSERT(m_ranges.end() != endIter, ()); } ASSERT(startIter->first <= t && t <= endIter->first, ()); startPoint = *startIter; endPoint = *endIter; } private: TRangeVector m_ranges; }; }