From fc2f3d79b5efbbd1df091a9459c276bd3fde3b53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 3 Sep 2019 15:14:02 +0200 Subject: [PATCH] [apps/shared] Create a class Range1D --- apps/shared/Makefile | 1 + apps/shared/range_1D.cpp | 48 ++++++++++++++++++++++++++++++++++++++++ apps/shared/range_1D.h | 31 ++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 apps/shared/range_1D.cpp create mode 100644 apps/shared/range_1D.h diff --git a/apps/shared/Makefile b/apps/shared/Makefile index aedf7d274..a8276a24d 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -52,6 +52,7 @@ app_shared_src = $(addprefix apps/shared/,\ parameter_text_field_delegate.cpp \ post_and_hardware_tests.cpp \ range_parameter_controller.cpp \ + range_1D.cpp \ regular_table_view_data_source.cpp \ round_cursor_view.cpp \ scrollable_exact_approximate_expressions_cell.cpp \ diff --git a/apps/shared/range_1D.cpp b/apps/shared/range_1D.cpp new file mode 100644 index 000000000..a63e699d3 --- /dev/null +++ b/apps/shared/range_1D.cpp @@ -0,0 +1,48 @@ +#include "range_1D.h" +#include +#include + +namespace Shared { + +static inline float minFloat(float x, float y) { return x < y ? x : y; } +static inline float maxFloat(float x, float y) { return x > y ? x : y; } + +void Range1D::setMin(float min, float lowerMaxFloat, float upperMaxFloat) { + min = clipped(min, false, lowerMaxFloat, upperMaxFloat); + if (std::isnan(min)) { + return; + } + m_min = min; + if (m_min >= m_max) { + m_max = min + defaultRangeLengthFor(min); + } + if (m_max - min < k_minFloat) { + m_max = clipped(min + k_minFloat, true, lowerMaxFloat, upperMaxFloat); + } +} + +void Range1D::setMax(float max, float lowerMaxFloat, float upperMaxFloat) { + max = clipped(max, true, lowerMaxFloat, upperMaxFloat); + if (std::isnan(max)) { + return; + } + m_max = max; + if (m_min >= m_max) { + m_min = max - defaultRangeLengthFor(max); + } + if (max-m_min < k_minFloat) { + m_min = clipped(max - k_minFloat, false, lowerMaxFloat, upperMaxFloat); + } +} + +float Range1D::defaultRangeLengthFor(float position) { + return std::pow(10.0f, std::floor(std::log10(std::fabs(position)))-1.0f); +} + +float Range1D::clipped(float x, bool isMax, float lowerMaxFloat, float upperMaxFloat) { + float maxF = isMax ? upperMaxFloat : lowerMaxFloat; + float minF = isMax ? -lowerMaxFloat : -upperMaxFloat; + return maxFloat(minF, minFloat(x, maxF)); +} + +} diff --git a/apps/shared/range_1D.h b/apps/shared/range_1D.h new file mode 100644 index 000000000..e95d625ef --- /dev/null +++ b/apps/shared/range_1D.h @@ -0,0 +1,31 @@ +#ifndef SHARED_RANGE_1D_H +#define SHARED_RANGE_1D_H + +#include +#include + +namespace Shared { + +class Range1D { +public: + constexpr static float k_minFloat = 1E-4f; + Range1D(float min = -10.0f, float max = 10.0f) : + m_min(min), + m_max(max) + {} + float min() const { return m_min; } + float max() const { return m_max; } + void setMin(float f, float lowerMaxFloat = INFINITY, float upperMaxFloat = INFINITY); + void setMax(float f, float lowerMaxFloat = INFINITY, float upperMaxFloat = INFINITY); + static float clipped(float x, bool isMax, float lowerMaxFloat, float upperMaxFloat); + static float defaultRangeLengthFor(float position); +private: + float m_min; + float m_max; +}; + +static_assert(Range1D::k_minFloat >= FLT_EPSILON, "InteractiveCurveViewRange's minimal float range is lower than float precision, it might draw uglily curves such as cos(x)^2+sin(x)^2"); + +} + +#endif