Jump to content

belov

Members
  • Posts

    10
  • Joined

  • Last visited

  1. Короче, вот код, разбирайтесь сами :) Простой фильтр - интерполятор экспонентой double SimpleFilter::doGetCurveValue(double d) const { // d должно быть в диапазоне [0, 1] if(getDeadzoneX() >= d) return 0; if(getSaturationX() <= d) return getSaturationY(); d = (d - getDeadzoneX()) / (getSaturationX() - getDeadzoneX()); const double curvature = getCurvature().front(); if(0.0 != curvature) d = (exp(10.0 * curvature * d) - 1.0) / (exp(10.0 * curvature) - 1.0); return d * (getSaturationY() - getDeadzoneY()) + getDeadzoneY(); } Вот интерполятор кубическим сплайном: // полноценное вычисление кубического сплайна довольно дорого, // поэтому диапазон [0, range] разбиваем на steps интервалов и // рассчитываем значения кривой в этих точках. // если требуется значение между двумя предрассчитанными точками, то // выбирается минимальное значение // каждое значение curvature должно быть в диапазоне [0, 1] // по умолчанию весь диапазон разбивается на 1000 участков // после изменения saturation, deadzone, curvature, range // необходимо вызвать функцию build для нового расчета фильтра // функция build разбивает интервал range на steps точек и // рассчитывает значение функци в каждой точке void CubicFilter::build(int steps) { values_.clear(); const vector<double>& curvature = getCurvature(); if(curvature.size() < 4) { return; } const int n = (int)curvature.size(); const double xCurveStep = 1.0 / (n - 1); step_ = 1.0 / steps; vector<double> y2(n); vector<double> u(n); y2[0] = 0.0; u[0] = 0.0; for(int i = 1; i <= n - 2; ++i) { const double sig = 0.5; const double p = sig * y2[ i - 1] + 2.0; y2 = (sig - 1.0) / p; u = (curvature[i + 1] - curvature) / xCurveStep - (curvature - curvature[i - 1]) / xCurveStep; u = (6.0 * u / (2.0 * xCurveStep) - sig * u[i - 1]) / p; } y2[n - 1] = 0.0; for(int k = n - 2; k >= 0; --k) { y2[k] = y2[k] * y2[k + 1] + u[k]; } const double cy = (getSaturationY() - getDeadzoneY()); for(double x = 0; 1.0 > x; x += step_) values_.push_back(calcValue(y2, x) * cy + getDeadzoneY()); values_.push_back(calcValue(y2, 1.0) * cy + getDeadzoneY()); } double CubicFilter::doGetCurveValue(double d) const { // d должно быть в диапазоне [0, 1] if(getDeadzoneX() >= d) return 0; if(getSaturationX() <= d) return getSaturationY(); if(values_.empty()) return 0; const double value = values_[int(d / step_)]; if(value > getSaturationY()) return getSaturationY(); if(value < getDeadzoneY()) return getDeadzoneY(); return value; }
×
×
  • Create New...