diff --git a/SimoxUtility/CMakeLists.txt b/SimoxUtility/CMakeLists.txt index 81e193c2933f7e3ab47eef53db83a619935dac27..c0e2539f397d1333ac1441216c7eac6d03a38f6f 100644 --- a/SimoxUtility/CMakeLists.txt +++ b/SimoxUtility/CMakeLists.txt @@ -93,6 +93,7 @@ SET(INCLUDES algorithm/for_each_if.h algorithm/apply.hpp algorithm/get_map_keys_values.h + algorithm/minmax.h algorithm/string/string_tools.h algorithm/string/string_conversion.h algorithm/string/string_conversion_eigen.h diff --git a/SimoxUtility/algorithm.h b/SimoxUtility/algorithm.h index 53e55e3b48d89ff17a21649b83f055116f6699c2..e8217b97bca1c0b684dbe4c62dd1911271b507f0 100644 --- a/SimoxUtility/algorithm.h +++ b/SimoxUtility/algorithm.h @@ -4,4 +4,5 @@ #include "algorithm/for_each_if.h" #include "algorithm/get_map_keys_values.h" +#include "algorithm/minmax.h" #include "algorithm/string.h" diff --git a/SimoxUtility/algorithm/minmax.h b/SimoxUtility/algorithm/minmax.h new file mode 100644 index 0000000000000000000000000000000000000000..c4347ed8e2806d17024eb06cbb750cae88d8aca3 --- /dev/null +++ b/SimoxUtility/algorithm/minmax.h @@ -0,0 +1,43 @@ +#pragma once + +#include <algorithm> +#include <functional> +#include <vector> + + +namespace simox::alg +{ + + /// Return a function comparing the results of applying `unaryFunc` to values of type `T`. + template <class T, class Scalar> + std::function<bool(const T&, const T&)> get_compare_fn(const std::function<Scalar(const T&)> unaryFunc) + { + return [unaryFunc](const auto& lhs, const auto& rhs) + { + return unaryFunc(lhs) < unaryFunc(rhs); + }; + } + + /// @brief Get the maximum of applying `unaryFunc` to `values`. + template <class T, class Scalar> + Scalar min(const std::vector<T>& values, std::function<Scalar(const T&)> unaryFunc) + { + return unaryFunc(*std::min_element(values.begin(), values.end(), get_compare_fn(unaryFunc))); + } + + /// @brief Get the maximum of applying `unaryFunc` to `values` + template <class T, class Scalar> + Scalar max(const std::vector<T>& values, std::function<Scalar(const T&)> unaryFunc) + { + return unaryFunc(*std::max_element(values.begin(), values.end(), get_compare_fn(unaryFunc))); + } + + /// @brief Get minimum and maximum of applying `unaryFunc` to `values` + template <class T, class Scalar> + std::pair<Scalar, Scalar> minmax(const std::vector<T>& values, std::function<Scalar(const T&)> unaryFunc) + { + const auto [min, max] = std::minmax_element(values.begin(), values.end(), get_compare_fn(unaryFunc)); + return std::make_pair(*min, *max); + } + +} diff --git a/SimoxUtility/color/ColorMap.h b/SimoxUtility/color/ColorMap.h index ebead5ddaaa6a4e9cc8651651ecd08b054e3bce8..2cb6bdcd6333d127f78abf3969b1801ae1625129 100644 --- a/SimoxUtility/color/ColorMap.h +++ b/SimoxUtility/color/ColorMap.h @@ -1,11 +1,13 @@ #pragma once #include <algorithm> +#include <functional> #include <initializer_list> #include <map> #include <string> #include <SimoxUtility/algorithm/apply.hpp> +#include <SimoxUtility/algorithm/minmax.h> #include "Color.h" #include "interpolation.h" @@ -78,6 +80,24 @@ namespace simox::color void set_vmax(float vmax) { this->_vmax = vmax; } void set_vmin(const std::vector<float>& values) { set_vmin(*std::max_element(values.begin(), values.end())); } void set_vmax(const std::vector<float>& values) { set_vmax(*std::max_element(values.begin(), values.end())); } + /** + * @brief Set the value minimum to the minimum of `values`, measured by `unaryFunc`. + * You may have to specify the template argument (when template argument deduction fails). + */ + template <class T> + void set_vmin(const std::vector<T>& values, std::function<float(const T&)> unaryFunc) + { + set_vmax(simox::alg::min(values, unaryFunc)); + } + /** + * @brief Set the value maximum to the maximum of `values`, measured by `unaryFunc`. + * You may have to specify the template argument (when template argument deduction fails). + */ + template <class T> + void set_vmax(const std::vector<T>& values, std::function<float(const T&)> unaryFunc) + { + set_vmax(simox::alg::max(values, unaryFunc)); + } /// Sets the value limits, i.e. scales the color map to the range [vmin, vmax]. void set_vlimits(float vmin, float vmax) @@ -91,9 +111,20 @@ namespace simox::color set_vmin(*min); set_vmax(*max); } + /** + * @brief Set the value minimum and maximum to the minimum and maximum of `values`, measured by `unaryFunc`. + * You may have to specify the template argument (when template argument deduction fails). + */ + template <class T> + void set_vlimits(const std::vector<T>& values, std::function<float(const T&)> unaryFunc) + { + const auto [min, max] = simox::alg::minmax(simox::alg::min(values, unaryFunc)); + set_vmin(unaryFunc(min)); + set_vmax(unaryFunc(max)); + } - /// Get this colormap reversed (but defined in the same value range as this). + /// Get this colormap reversed (but defined in the same value range as `*this`). ColorMap reversed() const;