From 12b639970fc3ce08eada69d315470735fc23ef5f Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Mon, 28 Nov 2022 11:28:49 +0100 Subject: [PATCH] MathUtils: Add exponential interpolation Change-Id: I58bb26a6e921cbd1f5532bddcd6a6700ff80b94f Reviewed-by: Eike Ziller --- src/libs/utils/mathutils.cpp | 25 +++++++++++++++--- src/libs/utils/mathutils.h | 3 ++- tests/auto/utils/mathutils/tst_mathutils.cpp | 27 ++++++++++++++++++++ 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/libs/utils/mathutils.cpp b/src/libs/utils/mathutils.cpp index d9e18b18a33..f1bdc5999c8 100644 --- a/src/libs/utils/mathutils.cpp +++ b/src/libs/utils/mathutils.cpp @@ -39,9 +39,26 @@ int interpolateTangential(int x, int xHalfLife, int y1, int y2) return y1; if (y1 == y2) return y1; - const double mapped = atan2(double(x), double(xHalfLife)); - const double progress = y1 + (y2 - y1) * mapped * 2 / M_PI; - return qRound(progress); + const double angle = atan2((double)x, (double)xHalfLife); + const double result = y1 + (y2 - y1) * angle * 2 / M_PI; + return qRound(result); } -} // namespace Utils::Math +/*! + Exponential interpolation: + For x = 0 it returns y1. + For x = xHalfLife it returns 50 % of the distance between y1 and y2. + For x = infinity it returns y2. +*/ +int interpolateExponential(int x, int xHalfLife, int y1, int y2) +{ + if (x == 0) + return y1; + if (y1 == y2) + return y1; + const double exponent = pow(0.5, (double)x / xHalfLife); + const double result = y1 + (y2 - y1) * (1.0 - exponent); + return qRound(result); +} + +} // namespace Utils::MathUtils diff --git a/src/libs/utils/mathutils.h b/src/libs/utils/mathutils.h index 8a9af9e4e64..21f66ff5813 100644 --- a/src/libs/utils/mathutils.h +++ b/src/libs/utils/mathutils.h @@ -9,5 +9,6 @@ namespace Utils::MathUtils { QTCREATOR_UTILS_EXPORT int interpolateLinear(int x, int x1, int x2, int y1, int y2); QTCREATOR_UTILS_EXPORT int interpolateTangential(int x, int xHalfLife, int y1, int y2); +QTCREATOR_UTILS_EXPORT int interpolateExponential(int x, int xHalfLife, int y1, int y2); -} // namespace Utils::Math +} // namespace Utils::MathUtils diff --git a/tests/auto/utils/mathutils/tst_mathutils.cpp b/tests/auto/utils/mathutils/tst_mathutils.cpp index 30d2d8d6c59..a585868d994 100644 --- a/tests/auto/utils/mathutils/tst_mathutils.cpp +++ b/tests/auto/utils/mathutils/tst_mathutils.cpp @@ -16,6 +16,8 @@ private slots: void interpolateLinear(); void interpolateTangential_data(); void interpolateTangential(); + void interpolateExponential_data(); + void interpolateExponential(); }; void tst_MathUtils::interpolateLinear_data() @@ -72,6 +74,31 @@ void tst_MathUtils::interpolateTangential() QCOMPARE(y, result); } +void tst_MathUtils::interpolateExponential_data() +{ + QTest::addColumn("x"); + QTest::addColumn("xHalfLife"); + QTest::addColumn("y1"); + QTest::addColumn("y2"); + QTest::addColumn("result"); + + QTest::newRow("zero") << 0 << 8 << 10 << 20 << 10; + QTest::newRow("halfLife") << 8 << 8 << 10 << 20 << 15; + QTest::newRow("approxInfinity") << 1000 << 8 << 10 << 20 << 20; +} + +void tst_MathUtils::interpolateExponential() +{ + QFETCH(int, x); + QFETCH(int, xHalfLife); + QFETCH(int, y1); + QFETCH(int, y2); + QFETCH(int, result); + + const int y = MathUtils::interpolateExponential(x, xHalfLife, y1, y2); + QCOMPARE(y, result); +} + QTEST_GUILESS_MAIN(tst_MathUtils) #include "tst_mathutils.moc"