1#include "color_scale.h"
3#include <cgv/math/compare_float.h>
4#include <cgv/media/ticks.h>
15 if(is_clamped_ != clamped) {
16 is_clamped_ = clamped;
22 if(is_reversed_ != reverse) {
23 is_reversed_ = reverse;
30 return !
is_clamped() && (value < domain[0] || value > domain[1]);
34 float size = in_right - in_left;
35 if(cgv::math::is_zero(size))
37 return out_left + (out_right - out_left) * ((value - in_left) / size);
42 update_log_invariants();
46 mapping_transform_ = transform;
47 update_log_invariants();
52 if(pow_exponent_ != exponent) {
53 pow_exponent_ = exponent;
59 if(log_base_ != base) {
61 update_log_invariants();
67 if(is_diverging_ != diverging) {
68 is_diverging_ = diverging;
74 if(diverging_midpoint_ != midpoint) {
75 diverging_midpoint_ = midpoint;
84 value = cgv::math::clamp(value, domain[0], domain[1]);
91 switch(mapping_transform_) {
92 case ContinuousMappingTransform::kLinear:
94 if(value < diverging_midpoint_)
95 t =
map_range_safe(value, domain[0], diverging_midpoint_, 0.0f, 0.5f);
97 t =
map_range_safe(value, diverging_midpoint_, domain[1], 0.5f, 1.0f);
102 case ContinuousMappingTransform::kPow:
104 if(value < diverging_midpoint_) {
105 t =
map_range_safe(value, domain[0], diverging_midpoint_, 0.0f, 1.0f);
106 t = 0.5f * (1.0f - std::pow(1.0f - t, pow_exponent_));
108 t =
map_range_safe(value, diverging_midpoint_, domain[1], 0.0f, 1.0f);
109 t = 0.5f * std::pow(t, pow_exponent_) + 0.5f;
113 t = std::pow(t, pow_exponent_);
116 case ContinuousMappingTransform::kLog:
117 t = std::log(log_value_sign_ * value) / log_of_base_;
119 if(value < diverging_midpoint_) {
120 t =
map_range_safe(t, log_of_lower_bound_, log_of_midpoint_, 0.0f, 0.5f);
122 t =
map_range_safe(t, log_of_midpoint_, log_of_upper_bound_, 0.5f, 1.0f);
125 t =
map_range_safe(t, log_of_lower_bound_, log_of_upper_bound_, 0.0f, 1.0f);
129 t *= log_value_sign_;
145 std::vector<cgv::rgba> colors;
146 colors.reserve(count);
149 std::swap(domain[0], domain[1]);
150 cgv::math::sequence_transform(std::back_inserter(colors), [
this](
float t) {
return scheme_.
get_interpolator()->at(t); }, count, domain[0], domain[1]);
157 if(mapping_transform_ == ContinuousMappingTransform::kLog)
158 return compute_ticks_log(domain[0], domain[1], log_base_, request_count);
160 return compute_ticks(domain[0], domain[1], request_count);
168void continuous_color_scale::update_log_invariants() {
169 if(mapping_transform_ == ContinuousMappingTransform::kLog) {
172 if(domain[0] < 0.0f && domain[1] < 0.0f)
173 log_value_sign_ = -1.0f;
175 log_of_base_ = std::log(log_base_);
176 log_of_midpoint_ = std::log(log_value_sign_ * diverging_midpoint_) / log_of_base_;
177 log_of_lower_bound_ = std::log(log_value_sign_ * domain[0]) / log_of_base_;
178 log_of_upper_bound_ = std::log(log_value_sign_ * domain[1]) / log_of_base_;
185 value = cgv::math::clamp(value, domain[0], domain[1]);
197 return colors_.front();
199 return colors_.back();
201 return colors_[std::min(
static_cast<size_t>(std::floor(t *
static_cast<float>(colors_.size()))), colors_.size() - 1)];
205 index %= colors_.size();
206 return { colors_[index], 1.0f };
210 std::vector<cgv::rgba> colors;
212 for(
size_t i = 0; i < color_count; ++i) {
213 size_t index =
is_reversed() ? color_count - i - 1 : i;
214 colors.push_back(colors_[index]);
this header is dependency free