1#include "transfer_function.h"
3#include <cgv/media/ticks.h>
4#include <cgv/utils/algorithm.h>
19 color_points_.clear();
20 opacity_points_.clear();
25 color_points_.clear();
30 opacity_points_.clear();
35 color_points_ = colors;
36 sort_points_and_update_domain(color_points_);
37 ensure_control_points_cover_domain(color_points_);
38 ensure_control_points_cover_domain(opacity_points_);
42 std::vector<float> positions;
44 std::vector<cgv::rgb> colors = scheme.
quantize(n);
49 opacity_points_ = opacities;
50 std::for_each(opacity_points_.begin(), opacity_points_.end(), [](
const opacity_point_type& point) { cgv::math::saturate(point.second); });
51 sort_points_and_update_domain(opacity_points_);
52 ensure_control_points_cover_domain(opacity_points_);
53 ensure_control_points_cover_domain(color_points_);
58 color_points_.push_back({ x,
color });
59 sort_points_and_update_domain(color_points_);
60 ensure_control_points_cover_domain(opacity_points_);
61 ensure_control_points_cover_domain(color_points_);
66 opacity_points_.push_back({ x, cgv::math::saturate(opacity) });
67 sort_points_and_update_domain(opacity_points_);
68 ensure_control_points_cover_domain(color_points_);
69 ensure_control_points_cover_domain(opacity_points_);
73 if(index < color_points_.size()) {
74 color_points_[index].second =
color;
82 auto it = find_point(color_points_, x);
83 if(it != color_points_.end()) {
92 if(index < opacity_points_.size()) {
93 opacity_points_[index].second = opacity;
101 auto it = find_point(opacity_points_, x);
102 if(it != opacity_points_.end()) {
103 it->second = opacity;
111 if(remove_point(color_points_, x)) {
119 if(remove_point(opacity_points_, x)) {
130 float lower_bound = current_domain[0] < domain[0] ? domain[0] : current_domain[0];
131 float upper_bound = current_domain[1] > domain[1] ? domain[1] : current_domain[1];
133 if(!color_points_.empty() && color_points_.front().first != domain[0])
135 if(!opacity_points_.empty() && opacity_points_.front().first != domain[0])
138 if(!color_points_.empty() && color_points_.back().first != domain[1])
140 if(!opacity_points_.empty() && opacity_points_.back().first != domain[1])
144 const auto is_point_out_of_range = [domain](
const auto& point) {
145 return point.first < domain[0] || point.first > domain[1];
148 const auto remove_points_out_of_range = [domain, &is_point_out_of_range](
auto& points) {
150 bool removed =
false;
154 auto it = std::find_if(points.begin(), points.end(), is_point_out_of_range);
155 if(it != points.end()) {
165 bool removed_color_points = remove_points_out_of_range(color_points_);
166 bool removed_opacity_points = remove_points_out_of_range(opacity_points_);
167 if(removed_color_points || removed_opacity_points)
170 sort_points_and_update_domain(color_points_);
176 if(current_domain == domain)
179 const auto map_point = [
this, current_domain, domain](
auto& point) {
180 point.first =
map_range_safe(point.first, current_domain[0], current_domain[1], domain[0], domain[1]);
183 if(!color_points_.empty())
184 std::for_each(color_points_.begin(), color_points_.end(), map_point);
186 if(!opacity_points_.empty())
187 std::for_each(opacity_points_.begin(), opacity_points_.end(), map_point);
194 value = cgv::math::clamp(value, domain[0], domain[1]);
206 if(
is_unknown(value) || color_points_.empty())
208 return interpolate(color_points_, value, color_interpolation_);
212 if(opacity_points_.empty())
214 return interpolate(opacity_points_, value, opacity_interpolation_);
221 std::vector<cgv::rgba> values;
222 values.reserve(count);
223 std::transform(colors.begin(), colors.end(), opacities.begin(), std::back_inserter(values), [](
const cgv::rgba&
color,
float opacity) {
224 return cgv::rgba(color, opacity);
231 if(color_points_.empty())
232 return std::vector<cgv::rgb>(count, { 0.0f });
234 std::vector<cgv::rgb> colors =
quantize(color_points_, count, color_interpolation_);
236 std::reverse(colors.begin(), colors.end());
241 if(opacity_points_.empty())
242 return std::vector<float>(count, 1.0f);
243 std::vector<float> opacities =
quantize(opacity_points_, count, opacity_interpolation_);
245 std::reverse(opacities.begin(), opacities.end());
259 return compute_ticks(domain[0], domain[1], request_count);
263 if(color_interpolation_ != interpolation || opacity_interpolation_ != interpolation) {
264 color_interpolation_ = interpolation;
265 opacity_interpolation_ = interpolation;
271 if(color_interpolation_ != interpolation) {
272 color_interpolation_ = interpolation;
278 if(opacity_interpolation_ != interpolation) {
279 opacity_interpolation_ = interpolation;
284bool transfer_function::update_domain() {
288 if(!color_points_.empty()) {
289 domain[0] = color_points_.front().first;
290 domain[1] = color_points_.back().first;
292 if(!opacity_points_.empty()) {
293 domain[0] = std::min(domain[0], opacity_points_.front().first);
294 domain[1] = std::max(domain[1], opacity_points_.back().first);
297 if(old_domain != domain) {
OutputIt zip(const InputIt1 first1, const InputIt1 last1, const InputIt2 first2, OutputIt d_first)
Zip two sequences together to form a single sequene of pairs and store the results in an output range...
void subdivision_sequence(OutputIt output_first, ParamT start, ParamT stop, size_t n)
Generate a sequence of n uniformly-spaced values in [start,stop] and store the result in an output ra...
this header is dependency free