// // Created by kifir on 7/29/24. // #pragma once #include class ValueProvider2D { public: virtual std::optional getValue(float x) const = 0; }; template class Map2D : public ValueProvider2D { public: Map2D(const char* const name); void initTable(const TValue (&values)[TLength], const TBin (&bins)[TLength]); virtual std::optional getValue(const float x) const; private: const char* const m_name; const TValue (*m_values)[TLength] = nullptr; const TBin (*m_bins)[TLength] = nullptr; }; template Map2D::Map2D(const char* const name) : m_name(name) { } template void Map2D::initTable(const TValue (&values)[TLength], const TBin (&bins)[TLength]) { m_values = &values; m_bins = &bins; } template std::optional Map2D::getValue(const float x) const { if (!m_bins) { criticalError("Access to uninitialized bins: %s", m_name); return {}; } else if (!m_values) { criticalError("Access to uninitialized values: %s", m_name); return {}; } else if ((1 < TLength) && ((*m_bins)[0] == 0.0f) && ((*m_bins)[1] == 0.0f)) { // bins are uninitialized, but it isn't critical - maybe old configuration return {}; } else { return std::make_optional(interpolate2d(x, *m_bins, *m_values)); } }