diff options
Diffstat (limited to 'qfunctionconfigurator/functionconfig.cpp')
-rw-r--r-- | qfunctionconfigurator/functionconfig.cpp | 319 |
1 files changed, 124 insertions, 195 deletions
diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp index 97a6db24..a4d03ed8 100644 --- a/qfunctionconfigurator/functionconfig.cpp +++ b/qfunctionconfigurator/functionconfig.cpp @@ -1,11 +1,3 @@ -/* Copyright (c) 2012, 2013 Stanisław Halik <sthalik@misaki.pl> - - * Permission to use, copy, modify, and/or distribute this - * software for any purpose with or without fee is hereby granted, - * provided that the above copyright notice and this permission - * notice appear in all copies. - */ - #include <QMutexLocker> #include <QCoreApplication> #include <QPointF> @@ -14,259 +6,193 @@ #include <QtAlgorithms> #include <QtAlgorithms> #include <QSettings> -#include <math.h> #include <QPixmap> +#include <algorithm> -// -// Constructor with List of Points in argument. -// -FunctionConfig::FunctionConfig(QString title, int intMaxInput, int intMaxOutput) : - _mutex(QMutex::Recursive) -{ - _title = title; - _points = QList<QPointF>(); - _data = 0; - _size = 0; - lastValueTracked = QPointF(0,0); - _tracking_active = false; - _max_Input = intMaxInput; // Added WVR 20120805 - _max_Output = intMaxOutput; - QSettings settings("opentrack"); // Registry settings (in HK_USER) - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); - loadSettings(iniFile); - reload(); -} - -void FunctionConfig::setTrackingActive(bool blnActive) +void Map::setTrackingActive(bool blnActive) { - _tracking_active = blnActive; + activep = blnActive; } -FunctionConfig::FunctionConfig() : +Map::Map() : _mutex(QMutex::Recursive), - _data(0), - _size(0), - _tracking_active(false), - _max_Input(0), - _max_Output(0) + activep(false), + max_x(0), + max_y(0) { } -// -// Calculate the value of the function, given the input 'x'. -// Used to draw the curve and, most importantly, to translate input to output. -// The return-value is also stored internally, so the Widget can show the current value, when the Tracker is running. -// -float FunctionConfig::getValue(float x) { +float Map::getValue(float x) { QMutexLocker foo(&_mutex); - int x2 = (int) (std::min<float>(std::max<float>(x, -360), 360) * MEMOIZE_PRECISION); + int x2 = x * (double) MEMOIZE_PRECISION; float ret = getValueInternal(x2); - lastValueTracked.setX(x); - lastValueTracked.setY(ret); - return ret; + last_input_value.setX(x); + last_input_value.setY(ret); + return ret; } -// -// The return-value is also stored internally, so the Widget can show the current value, when the Tracker is running. -// -bool FunctionConfig::getLastPoint(QPointF& point ) { +bool Map::getLastPoint(QPointF& point ) { QMutexLocker foo(&_mutex); - point = lastValueTracked; - return _tracking_active; + point = last_input_value; + return activep; } -float FunctionConfig::getValueInternal(int x) { +float Map::getValueInternal(int x) { float sign = x < 0 ? -1 : 1; - x = x < 0 ? -x : x; + x = std::abs(x); float ret; - if (!_data) - ret = 0; - else if (_size == 0) - ret = 0; - else if (x < 0) - ret = 0; - else if (x < _size && x >= 0) - ret = _data[x]; - else - ret = _data[_size - 1]; - return ret * sign; + int sz = cur.data.size(); + if (sz == 0) + ret = 0; + else + ret = cur.data[std::max(std::min(x, sz-1), 0)]; + return ret * sign; } static __inline QPointF ensureInBounds(QList<QPointF> points, int i) { - int siz = points.size(); - if (siz == 0 || i < 0) - return QPointF(0, 0); - if (siz > i) - return points[i]; - return points[siz - 1]; + int siz = points.size(); + if (siz == 0 || i < 0) + return QPointF(0, 0); + if (siz > i) + return points[i]; + return points[siz - 1]; } static bool sortFn(const QPointF& one, const QPointF& two) { - return one.x() < two.x(); + return one.x() < two.x(); } -void FunctionConfig::reload() { - _size = 0; - - if (_points.size()) - qStableSort(_points.begin(), _points.end(), sortFn); - - if (_data) - delete[] _data; - _data = NULL; - if (_points.size()) { - _data = new float[_size = MEMOIZE_PRECISION * _points[_points.size() - 1].x()]; - - for (int i = 0; i < _size; i++) - _data[i] = -1e6; - - for (int k = 0; k < _points[0].x() * MEMOIZE_PRECISION; k++) { - if (k < _size) - _data[k] = _points[0].y() * k / (_points[0].x() * MEMOIZE_PRECISION); +void Map::reload() { + if (cur.input.size()) + { + auto& input = cur.input; + auto& data = cur.data; + + qStableSort(input.begin(), input.end(), sortFn); + data = std::vector<float>(MEMOIZE_PRECISION * input[input.size() - 1].x()); + + const int sz = data.size(); + + for (int i = 0; i < sz; i++) + data[i] = -1; + + for (int k = 0; k < input[0].x() * MEMOIZE_PRECISION; k++) { + if (k < sz) + data[k] = input[0].y() * k / (input[0].x() * MEMOIZE_PRECISION); } - - for (int i = 0; i < _points.size(); i++) { - QPointF p0 = ensureInBounds(_points, i - 1); - QPointF p1 = ensureInBounds(_points, i); - QPointF p2 = ensureInBounds(_points, i + 1); - QPointF p3 = ensureInBounds(_points, i + 2); - - int end = p2.x() * MEMOIZE_PRECISION; + + for (int i = 0; i < sz; i++) { + QPointF p0 = ensureInBounds(input, i - 1); + QPointF p1 = ensureInBounds(input, i); + QPointF p2 = ensureInBounds(input, i + 1); + QPointF p3 = ensureInBounds(input, i + 2); + + int end = std::min<int>(sz, p2.x() * MEMOIZE_PRECISION); int start = p1.x() * MEMOIZE_PRECISION; - - for (int j = start; j < end && j < _size; j++) { + + for (int j = start; j < end; j++) { double t = (j - start) / (double) (end - start); double t2 = t*t; double t3 = t*t*t; - + int x = .5 * ((2. * p1.x()) + (-p0.x() + p2.x()) * t + (2. * p0.x() - 5. * p1.x() + 4. * p2.x() - p3.x()) * t2 + (-p0.x() + 3. * p1.x() - 3. * p2.x() + p3.x()) * t3) * MEMOIZE_PRECISION; - + float y = .5 * ((2. * p1.y()) + - (-p0.y() + p2.y()) * t + - (2. * p0.y() - 5. * p1.y() + 4. * p2.y() - p3.y()) * t2 + - (-p0.y() + 3. * p1.y() - 3. * p2.y() + p3.y()) * t3); - - if (x >= 0 && x < _size) - _data[x] = y; + (-p0.y() + p2.y()) * t + + (2. * p0.y() - 5. * p1.y() + 4. * p2.y() - p3.y()) * t2 + + (-p0.y() + 3. * p1.y() - 3. * p2.y() + p3.y()) * t3); + + if (x >= 0 && x < sz) + data[x] = y; } - } - - float last = 0; - - for (int i = 0; i < _size; i++) - { - if (_data[i] == -1e6) - _data[i] = last; - last = _data[i]; - } - } -} - -FunctionConfig::~FunctionConfig() { - if (_data) - delete[] _data; + } + + float last = 0; + for (int i = 0; i < sz; i++) + { + if (data[i] <= 0) + data[i] = last; + last = data[i]; + } + } + else + cur.data.clear(); } -// -// Remove a Point from the Function. -// Used by the Widget. -// -void FunctionConfig::removePoint(int i) { +void Map::removePoint(int i) { QMutexLocker foo(&_mutex); - if (i >= 0 && i < _points.size()) + if (i >= 0 && i < cur.input.size()) { - _points.removeAt(i); + cur.input.removeAt(i); reload(); } } -// -// Add a Point to the Function. -// Used by the Widget and by loadSettings. -// -void FunctionConfig::addPoint(QPointF pt) { +void Map::addPoint(QPointF pt) { QMutexLocker foo(&_mutex); - _points.append(pt); - reload(); + cur.input.append(pt); + reload(); } -// -// Move a Function Point. -// Used by the Widget. -// -void FunctionConfig::movePoint(int idx, QPointF pt) { +void Map::movePoint(int idx, QPointF pt) { QMutexLocker foo(&_mutex); - if (idx >= 0 && idx < _points.size()) + if (idx >= 0 && idx < cur.input.size()) { - _points[idx] = pt; + cur.input[idx] = pt; reload(); } } -// -// Return the List of Points. -// Used by the Widget. -// -QList<QPointF> FunctionConfig::getPoints() { - QList<QPointF> ret; +const QList<QPointF> Map::getPoints() { QMutexLocker foo(&_mutex); - for (int i = 0; i < _points.size(); i++) { - ret.append(_points[i]); - } - return ret; + return cur.input; +} + +void Map::invalidate_unsaved_settings() +{ + cur = saved; + reload(); } -// -// Load the Points for the Function from the INI-file designated by settings. -// Settings for a specific Curve are loaded from their own Group in the INI-file. -// -void FunctionConfig::loadSettings(QSettings& settings) { +void Map::loadSettings(QSettings& settings, const QString& title) { QMutexLocker foo(&_mutex); QPointF newPoint; + QList<QPointF> points; + settings.beginGroup(QString("Curves-%1").arg(title)); - QList<QPointF> points; - settings.beginGroup(QString("Curves-%1").arg(_title)); - int max = settings.value("point-count", 0).toInt(); - for (int i = 0; i < max; i++) { - newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toFloat(), - settings.value(QString("point-%1-y").arg(i), 0).toFloat()); - // - // Make sure the new Point fits in the Function Range. - // Maybe this can be improved? - // - if (newPoint.x() > _max_Input) { - newPoint.setX(_max_Input); - } - if (newPoint.y() > _max_Output) { - newPoint.setY(_max_Output); - } - points.append(newPoint); - } + for (int i = 0; i < max; i++) { + newPoint = QPointF(settings.value(QString("point-%1-x").arg(i), 0).toFloat(), + settings.value(QString("point-%1-y").arg(i), 0).toFloat()); + if (newPoint.x() > max_x) { + newPoint.setX(max_x); + } + if (newPoint.y() > max_y) { + newPoint.setY(max_y); + } + points.append(newPoint); + } + settings.endGroup(); - _points = points; - reload(); + cur.input = points; + reload(); + saved = cur; } -// -// Save the Points for the Function to the INI-file designated by settings. -// Settings for a specific Curve are saved in their own Group in the INI-file. -// The number of Points is also saved, to make loading more convenient. -// -void FunctionConfig::saveSettings(QSettings& settings) { +void Map::saveSettings(QSettings& settings, const QString& title) { QMutexLocker foo(&_mutex); - settings.beginGroup(QString("Curves-%1").arg(_title)); - int max = _points.size(); - settings.setValue("point-count", max); - for (int i = 0; i < max; i++) { - settings.setValue(QString("point-%1-x").arg(i), _points[i].x()); - settings.setValue(QString("point-%1-y").arg(i), _points[i].y()); + settings.beginGroup(QString("Curves-%1").arg(title)); + int max = cur.input.size(); + settings.setValue("point-count", max); + + for (int i = 0; i < max; i++) { + settings.setValue(QString("point-%1-x").arg(i), cur.input[i].x()); + settings.setValue(QString("point-%1-y").arg(i), cur.input[i].y()); } for (int i = max; true; i++) @@ -277,5 +203,8 @@ void FunctionConfig::saveSettings(QSettings& settings) { settings.remove(x); settings.remove(QString("point-%1-y").arg(i)); } - settings.endGroup(); + + saved = cur; + + settings.endGroup(); } |