cgv
Loading...
Searching...
No Matches
transfer_function.h
1#pragma once
2
3#include <algorithm>
4#include <vector>
5
6#include <cgv/math/interpolate.h>
7#include <cgv/math/fvec.h>
8
9#include "color.h"
10#include "color_scale.h"
11#include "color_scheme.h"
12
13#include "lib_begin.h"
14
15namespace cgv {
16namespace media {
17
21class CGV_API transfer_function : public color_scale {
22public:
24 enum class InterpolationMode {
25 kStep,
26 kLinear,
27 kSmooth
28 };
29
33 using opacity_type = float;
35 using color_point_type = std::pair<float, color_type>;
37 using opacity_point_type = std::pair<float, opacity_type>;
38
41
46 transfer_function(std::initializer_list<color_point_type> colors);
47
54 transfer_function(std::initializer_list<color_point_type> colors, std::initializer_list<opacity_point_type> opacities);
55
59 bool is_opaque() const override {
60 return opacity_points_.empty();
61 }
62
65 bool is_discrete() const override {
66 return false;
67 }
68
72 bool empty() const {
73 return color_points_.empty() && opacity_points_.empty();
74 }
75
77 void clear();
78
80 void clear_color_points();
81
83 void clear_opacity_points();
84
89 void set_color_points(const std::vector<color_point_type>& colors);
90
96 void set_color_points_from_scheme(const cgv::media::continuous_color_scheme& scheme, size_t n);
97
103 void set_opacity_points(const std::vector<opacity_point_type>& opacities);
104
110 void add_color_point(float x, const color_type& color);
111
118 void add_opacity_point(float x, float opacity);
119
125 bool set_color(size_t index, const color_type& color);
126
132 bool set_color_at(float x, const color_type& color);
133
139 bool set_opacity(size_t index, const opacity_type& opacity);
140
146 bool set_opacity_at(float x, const opacity_type& opacity);
147
152 bool remove_color_point(float x);
153
158 bool remove_opacity_point(float x);
159
163 const size_t get_color_point_count() const {
164 return color_points_.size();
165 }
166
170 const size_t get_opacity_point_count() const {
171 return opacity_points_.size();
172 }
173
177 const std::vector<color_point_type>& get_color_points() const {
178 return color_points_;
179 }
180
184 const std::vector<opacity_point_type>& get_opacity_points() const {
185 return opacity_points_;
186 }
187
194 void set_domain(cgv::vec2 domain) override;
195
200 void rescale(cgv::vec2 domain);
201
203 float normalize_value(float value) const override;
204
206 cgv::rgba map_value(float value) const override;
207
209 cgv::rgb get_mapped_color(float value) const override;
210
212 float get_mapped_opacity(float value) const override;
213
215 std::vector<cgv::rgba> quantize(size_t count) const override;
216
219 std::vector<cgv::rgb> quantize_color(size_t count) const;
220
223 std::vector<float> quantize_opacity(size_t count) const;
224
226 std::vector<float> get_ticks(size_t request_count) const override;
227
231 void set_interpolation(InterpolationMode interpolation);
232
236 void set_color_interpolation(InterpolationMode interpolation);
237
242 return color_interpolation_;
243 }
244
248 void set_opacity_interpolation(InterpolationMode interpolation);
249
254 return opacity_interpolation_;
255 }
256
257private:
264 template<typename value_type>
265 typename std::vector<std::pair<float, value_type>>::iterator find_point(std::vector<std::pair<float, value_type>>& points, float x) {
266 return std::find_if(points.begin(), points.end(), [&x](const std::pair<float, value_type>& point) { return point.first == x; });
267 }
268
275 template<typename value_type>
276 bool remove_point(std::vector<std::pair<float, value_type>>& points, float x) {
277 auto it = find_point(points, x);
278 if(it == points.end() || it == points.begin() || it == --points.end())
279 return false;
280 points.erase(it);
281 return true;
282 }
283
289 template<typename value_type>
290 void ensure_control_points_cover_domain(std::vector<std::pair<float, value_type>>& points) {
291 if(!points.empty()) {
292 cgv::vec2 domain = get_domain();
293 if(domain[0] < points.front().first)
294 points.insert(points.begin(), { domain[0], points.front().second });
295 if(domain[1] > points.back().first)
296 points.push_back({ domain[1], points.back().second });
297 }
298 }
299
304 template<typename value_type>
305 void sort_points_and_update_domain(std::vector<std::pair<float, value_type>>& points) {
306 std::sort(points.begin(), points.end(), [](const auto& lhs, const auto& rhs) { return lhs.first < rhs.first; });
307 // Only call modified if this did not already happen in update_domain.
308 if(!update_domain())
309 modified();
310 }
311
318 template<typename value_type>
319 value_type interpolate_step(const std::vector<std::pair<float, value_type>>& points, float x) const {
320 return cgv::math::detail::interpolate_piece(points, x, [](const value_type& a, const value_type& b, float t_local) { return a; });
321 }
322
329 template<typename value_type>
330 std::vector<value_type> interpolate_step_n(const std::vector<std::pair<float, value_type>>& points, size_t n) const {
331 return cgv::math::detail::interpolate_n(points, [](const value_type& a, const value_type& b, float t_local) { return a; }, n);
332 }
333
341 template<typename value_type>
342 value_type interpolate(const std::vector<std::pair<float, value_type>>& points, float x, InterpolationMode interpolation) const {
343 switch(interpolation) {
344 case InterpolationMode::kStep:
345 return interpolate_step(points, x);
346 case InterpolationMode::kSmooth:
347 return cgv::math::interpolate_smooth_cubic(points, x);
348 default:
349 return cgv::math::interpolate_linear(points, x);
350 }
351 }
352
360 template<typename value_type>
361 std::vector<value_type> quantize(const std::vector<std::pair<float, value_type>>& points, size_t n, InterpolationMode interpolation) const {
362 switch(interpolation) {
363 case InterpolationMode::kStep:
364 return interpolate_step_n(points, n);
365 case InterpolationMode::kSmooth:
366 return cgv::math::interpolate_smooth_cubic_n(points, n);
367 default:
368 return cgv::math::interpolate_linear_n(points, n);
369 }
370 }
371
377 bool update_domain();
378
380 InterpolationMode color_interpolation_ = InterpolationMode::kLinear;
382 InterpolationMode opacity_interpolation_ = InterpolationMode::kLinear;
384 std::vector<color_point_type> color_points_;
386 std::vector<opacity_point_type> opacity_points_;
387};
388
389} // namespace media
390} // namespace cgv
391
392#include <cgv/config/lib_end.h>
Base class defining an interface for color scales.
Definition color_scale.h:22
This class represents a continuous color scheme using an interpolator to convert continuous scalar va...
Implementation of a color_scale with a continuous input domain that maps explicit domain values to co...
InterpolationMode
The interpolation modes supported by the transfer function.
std::pair< float, opacity_type > opacity_point_type
The used opacity control point type.
transfer_function()
Construct using default arguments.
const std::vector< opacity_point_type > & get_opacity_points() const
Get the opacity control points.
bool is_discrete() const override
See color_scale::is_discrete().
const std::vector< color_point_type > & get_color_points() const
Get the color control points.
InterpolationMode get_color_interpolation() const
Get the interpolation mode of the color function.
std::pair< float, color_type > color_point_type
The used color control point type.
const size_t get_opacity_point_count() const
Get the opacity control point count.
bool empty() const
Check whether the transfer function is empty.
bool is_opaque() const override
Return whether the color scale maps to opacity.
const size_t get_color_point_count() const
Get the color control point count.
InterpolationMode get_opacity_interpolation() const
Get the interpolation mode of the opacity function.
float opacity_type
The used opacity type.
this header is dependency free
Definition print.h:11
cgv::media::color< float, cgv::media::RGB > rgb
declare rgb color type with 32 bit components
Definition color.h:896