cgv
Loading...
Searching...
No Matches
color_scheme.h
1#pragma once
2
3#include <functional>
4#include <map>
5#include <set>
6#include <cstring>
7#include <vector>
8
9#include <cgv/data/object_registry.h>
10#include <cgv/math/interpolate.h>
11
12#include "color.h"
13
14#include "lib_begin.h"
15
16namespace cgv {
17namespace media {
18
23static std::vector<cgv::rgb> to_colors(const char* data) {
24 std::vector<cgv::rgb> colors;
25 if(data) {
26 size_t count = std::strlen(data) / 6;
27 for(size_t i = 0; i < count; ++i) {
28 std::string hex(data + 6 * i, 6);
29 cgv::rgb color = { 0.0f };
30 if(from_hex(hex, color))
31 colors.push_back(color);
32 }
33 }
34 return colors;
35}
36
43template<size_t N>
44static std::vector<std::vector<cgv::rgb>> to_colors(const std::array<const char*, N>& data) {
45 std::vector<std::vector<cgv::rgb>> colors;
46 colors.reserve(N);
47 for(const char* entry : data)
48 colors.push_back(to_colors(entry));
49 return colors;
50}
51
53enum class ColorSchemeType {
54 kUndefined, // All others.
55 kSequential, // Continuously varying colors from a limited set of hues (typically 1 or 2). Typically used for ordered and quantitative data.
56 kDiverging, // Continuously varying colors with contrasting hues meeting at a neutral midpoint. Typically used when the data range covers a 'zero' point.
57 kCyclical, // Continuously varying colors where the start and end color match. Typically used when the lower and upper bound of the data range should be mapped to the same color.
58 kCategorical // Distinct colors with sharp boundaries. Typically used to represent unordered, discrete data categories.
59};
60
64 ColorSchemeType type = ColorSchemeType::kUndefined;
65};
66
69public:
72
74 continuous_color_scheme() : continuous_color_scheme(cgv::math::identity_interpolator<cgv::rgb, float>()) {}
75
80 continuous_color_scheme(const interpolator_type& interpolator, ColorSchemeType type = ColorSchemeType::kUndefined) {
81 this->type = type;
82 interpolator_ = interpolator.clone();
83 }
84
90 static continuous_color_scheme linear(const std::vector<cgv::rgb>& colors, ColorSchemeType type = ColorSchemeType::kUndefined) {
92 }
93
100 static continuous_color_scheme linear(const std::vector<std::pair<float, cgv::rgb>>& colors, ColorSchemeType type = ColorSchemeType::kUndefined) {
102 }
103
109 static continuous_color_scheme smooth(const std::vector<cgv::rgb>& colors, ColorSchemeType type = ColorSchemeType::kUndefined) {
111 }
112
118 static continuous_color_scheme function(std::function<cgv::rgb(float)> fn, ColorSchemeType type = ColorSchemeType::kUndefined) {
120 }
121
123 std::shared_ptr<const interpolator_type> get_interpolator() const {
124 return interpolator_;
125 }
126
131 cgv::rgb interpolate(float t) const {
132 return interpolator_->at(t);
133 }
134
139 std::vector<cgv::rgb> quantize(size_t n) const {
140 return interpolator_->quantize(n);
141 }
142
143private:
145 std::shared_ptr<const interpolator_type> interpolator_;
146};
147
150public:
153
158 discrete_color_scheme(const std::vector<cgv::rgb>& colors, ColorSchemeType type = ColorSchemeType::kUndefined) : discrete_color_scheme(std::vector<std::vector<cgv::rgb>>{ colors }, type) {}
159
165 discrete_color_scheme(const std::vector<std::vector<cgv::rgb>>& variants, ColorSchemeType type = ColorSchemeType::kUndefined) {
166 this->type = type;
167 variants_.clear();
168 for(const auto& variant : variants)
169 variants_.insert({ variant.size(), variant });
170 }
171
180 const std::vector<cgv::rgb> get_colors(size_t n) const {
181 if(variants_.empty())
182 return {};
183
184 // Return the variant with the exact requested size if available.
185 auto it = variants_.find(n);
186 if(it != variants_.end())
187 return it->second;
188
189 // Otherwise, find the next largest variant.
190 it = variants_.upper_bound(n);
191
192 if(type == ColorSchemeType::kCategorical) {
193 // For categorical-type schemes the colors are not interpolated, so return at least n colors or the maximum available amount.
194 if(it == variants_.end())
195 --it;
196 return it->second;
197 } else {
198 // For all other types the next-smaller variant is interpolated and quantized to n colors.
199 if(it != variants_.begin())
200 --it;
201
202 if(!it->second.empty())
204 else
205 return {};
206 }
207 }
208
209
210private:
212 std::map<size_t, std::vector<cgv::rgb>> variants_;
213};
214
216using continuous_color_scheme_registry = cgv::data::object_registry<continuous_color_scheme>;
218using discrete_color_scheme_registry = cgv::data::object_registry<discrete_color_scheme>;
219
221extern CGV_API continuous_color_scheme_registry& get_global_continuous_color_scheme_registry();
223extern CGV_API discrete_color_scheme_registry& get_global_discrete_color_scheme_registry();
224
230template<typename RegistryT, typename ColorSchemeT>
232public:
237 color_scheme_registry_helper(RegistryT& registry, const std::set<ColorSchemeType>& types) : registry_(registry), supported_types_(types) {}
238
243 void load(const std::string& name, const ColorSchemeT& scheme) {
244 loaded_count_ += registry_.add(name, scheme) ? 1 : 0;
245 }
246
251 bool can_load(ColorSchemeType type) const {
252 return supported_types_.empty() || supported_types_.find(type) != supported_types_.end();
253 }
254
256 size_t loaded_count() const {
257 return loaded_count_;
258 }
259
260private:
262 size_t loaded_count_ = 0;
264 RegistryT& registry_;
266 std::set<ColorSchemeType> supported_types_;
267};
268
270using continuous_color_scheme_registry_helper = color_scheme_registry_helper<continuous_color_scheme_registry, continuous_color_scheme>;
272using discrete_color_scheme_registry_helper = color_scheme_registry_helper<discrete_color_scheme_registry, discrete_color_scheme>;
273
274} // namespace media
275} // namespace cgv
276
277#include <cgv/config/lib_end.h>
An object registry allows registering and querying objects identified by a unique name.
virtual std::vector< ValueT > quantize(size_t n) const
Return a sequence of n uniformly-spaced samples from the interpolator within the parameter range [0,...
A helper class to simplify registering color schemes in a registry and counting the number of success...
color_scheme_registry_helper(RegistryT &registry, const std::set< ColorSchemeType > &types)
Construct using a reference to the used registry and supported set of types.
void load(const std::string &name, const ColorSchemeT &scheme)
Register a color scheme under the given name.
bool can_load(ColorSchemeType type) const
Return whether the registry helper can load the given type of color scheme.
size_t loaded_count() const
Return the count of successfully registered color schemes.
This class represents a continuous color scheme using an interpolator to convert continuous scalar va...
continuous_color_scheme(const interpolator_type &interpolator, ColorSchemeType type=ColorSchemeType::kUndefined)
Construct using the given interpolator and scheme type.
static continuous_color_scheme linear(const std::vector< std::pair< float, cgv::rgb > > &colors, ColorSchemeType type=ColorSchemeType::kUndefined)
Create a continuous_color_scheme using linear interpolation of the given control points consisting of...
std::shared_ptr< const interpolator_type > get_interpolator() const
Return the interpolator.
static continuous_color_scheme smooth(const std::vector< cgv::rgb > &colors, ColorSchemeType type=ColorSchemeType::kUndefined)
Create a continuous_color_scheme using uniform b-spline interpolation of the given colors.
std::vector< cgv::rgb > quantize(size_t n) const
Evaluate the color scheme at n uniformly-spaced positions within the range [0,1].
continuous_color_scheme()
Construct using an interpolator that represents the identity function, basically providing a grayscal...
static continuous_color_scheme function(std::function< cgv::rgb(float)> fn, ColorSchemeType type=ColorSchemeType::kUndefined)
Create a continuous_color_scheme using a functor as interpolator.
cgv::rgb interpolate(float t) const
Evaluate the color scheme at position t.
static continuous_color_scheme linear(const std::vector< cgv::rgb > &colors, ColorSchemeType type=ColorSchemeType::kUndefined)
Create a continuous_color_scheme using uniform linear interpolation of the given colors.
This class represents a discrete color scheme using sets of colors to convert discrete scalars to col...
const std::vector< cgv::rgb > get_colors(size_t n) const
Return a sequence of colors of the specified count.
discrete_color_scheme()
Construct an empty scheme.
discrete_color_scheme(const std::vector< std::vector< cgv::rgb > > &variants, ColorSchemeType type=ColorSchemeType::kUndefined)
Construct from a list of color sets and scheme type.
discrete_color_scheme(const std::vector< cgv::rgb > &colors, ColorSchemeType type=ColorSchemeType::kUndefined)
Construct from a set of colors and scheme type.
uint8_t from_hex(char c)
convert from hex character
Definition scan.cxx:60
this header is dependency free
Definition print.h:11
Base class for color schemes. Only holds color scheme type.
ColorSchemeType type
The type of this color scheme.