cgv
Loading...
Searching...
No Matches
plot2d.cxx
1#include "plot2d.h"
2#include <libs/cgv_gl/gl/gl.h>
3#include <cgv/media/color_scale.h>
4#include <cgv/render/attribute_array_binding.h>
5#include <cgv/math/ftransform.h>
6
7namespace cgv {
8 namespace plot {
9
11plot2d_config::plot2d_config(const std::string& _name) : plot_base_config(_name, 2)
12{
13 configure_chart(CT_LINE_CHART);
14};
15
17void plot2d_config::configure_chart(ChartType chart_type)
18{
20 show_lines = chart_type == CT_LINE_CHART;
21}
22
24plot2d::plot2d(const std::string& title, unsigned nr_attributes) : plot_base(2, nr_attributes)
25{
26 multi_axis_modes = new bool[2 + nr_attributes];
27 std::fill(multi_axis_modes, multi_axis_modes+(2+nr_attributes), false);
28 sub_plot_delta = vec3(0.0f);
29 disable_depth_mask = false;
30 //legend_components = LC_ANY;
33 acs[0].name = "x";
34 acs[1].name = "y";
35 for (unsigned ai =0; ai < nr_attributes; ++ai)
36 acs[ai+2].name = std::string("attribute_")+cgv::utils::to_string(ai);
37}
38
39plot2d::~plot2d()
40{
41 delete[] multi_axis_modes;
42}
43
44bool plot2d::compute_sample_coordinate_interval(int i, int ai, float& samples_min, float& samples_max)
45{
46 // compute bounding box
47 bool found_sample = false;
48 float min_value, max_value;
49 for (unsigned j = 0; j < samples[i].size(); ++j) {
50 if (found_sample) {
51 min_value = std::min(min_value, samples[i][j](ai));
52 max_value = std::max(max_value, samples[i][j](ai));
53 }
54 else {
55 min_value = samples[i][j](ai);
56 max_value = samples[i][j](ai);
57 found_sample = true;
58 }
59 }
60 if (found_sample) {
61 samples_min = min_value;
62 samples_max = max_value;
63 return true;
64 }
65 return false;
66}
67
68unsigned plot2d::add_sub_plot(const std::string& name)
69{
70 // determine index of new sub plot
71 unsigned i = get_nr_sub_plots();
72
73 // create new config
74 if (i == 0)
75 configs.push_back(new plot2d_config(name));
76 else {
77 configs.push_back(new plot2d_config(ref_sub_plot2d_config(i - 1)));
78 ref_sub_plot_config(i).name = name;
79 }
80
81 // create new point container
82 samples.push_back(std::vector<vec2>());
83 strips.push_back(std::vector<unsigned>());
85 attribute_source_arrays.back().attribute_sources.push_back(attribute_source(i, 0, 0, 2 * sizeof(float)));
86 attribute_source_arrays.back().attribute_sources.push_back(attribute_source(i, 1, 0, 2 * sizeof(float)));
87 // return sub plot index
88 return i;
89}
90
92{
93 delete configs[i];
94 configs[i] = 0;
95 configs.erase(configs.begin() + i);
96 samples.erase(samples.begin() + i);
97 strips.erase(strips.begin() + i);
98}
99
102{
103 return static_cast<plot2d_config&>(ref_sub_plot_config(i));
104}
105
106std::vector<vec2>& plot2d::ref_sub_plot_samples(unsigned i)
107{
108 return samples[i];
109}
110
112std::vector<unsigned>& plot2d::ref_sub_plot_strips(unsigned i)
113{
114 return strips[i];
115}
116
118{
119 aam_domain.init(ctx);
120 aam_domain_tick_labels.init(ctx);
121 if (!line_prog.build_program(ctx, "plot2d_line.glpr", true)) {
122 std::cerr << "could not build GLSL program from plot2d_line.glpr" << std::endl;
123 return false;
124 }
125 else
126 line_prog.allow_context_to_set_color(false);
127 if (!point_prog.build_program(ctx, "plot2d_point.glpr", true)) {
128 std::cerr << "could not build GLSL program from plot2d_point.glpr" << std::endl;
129 return false;
130 }
131 else
132 point_prog.allow_context_to_set_color(false);
133
135 options.define_macro("PLOT_MODE", "1");
136 if (!rectangle_prog.build_program(ctx, "plot2d_rect.glpr", options, true)) {
137 std::cerr << "could not build GLSL program from plot2d_rect.glpr" << std::endl;
138 return false;
139 }
140 else
141 rectangle_prog.allow_context_to_set_color(false);
142 return plot_base::init(ctx);
143}
144
146{
147 aam_domain.destruct(ctx);
148 aam_domain_tick_labels.destruct(ctx);
149 point_prog.destruct(ctx);
150 line_prog.destruct(ctx);
151 rectangle_prog.destruct(ctx);
152 plot_base::clear(ctx);
153}
154
155bool plot2d::draw_point_plot(cgv::render::context& ctx, int i, int layer_idx)
156{
157 // skip unvisible and empty sub plots
158 if (!ref_sub_plot2d_config(i).show_plot)
159 return false;
160 GLsizei count = (GLsizei)enable_attributes(ctx, i, samples);
161 bool result = false;
162 if (count > 0) {
163 const plot2d_config& spc = ref_sub_plot2d_config(i);
164 if (spc.show_points && point_prog.is_linked()) {
165 set_plot_uniforms(ctx, point_prog);
166 set_mapping_uniforms(ctx, point_prog);
167 point_prog.set_uniform(ctx, "sub_plot_delta", float(i) * sub_plot_delta);
168 point_prog.set_uniform(ctx, "depth_offset", -layer_idx * layer_depth);
169 point_prog.set_uniform(ctx, "reference_point_size", get_domain_config_ptr()->reference_size);
170 point_prog.set_uniform(ctx, "blend_width_in_pixel", get_domain_config_ptr()->blend_width_in_pixel);
171 point_prog.set_uniform(ctx, "halo_width_in_pixel", 0.0f);
172 point_prog.set_uniform(ctx, "percentual_halo_width", spc.point_halo_width.size / spc.point_size.size);
173 point_prog.set_uniform(ctx, "viewport_height", (float)ctx.get_height());
174 point_prog.set_uniform(ctx, "measure_point_size_in_pixel", false);
175 point_prog.set_uniform(ctx, "screen_aligned", false);
176 point_prog.set_uniform(ctx, "color_index", spc.point_color.color_idx);
177 point_prog.set_uniform(ctx, "secondary_color_index", spc.point_halo_color.color_idx);
178 point_prog.set_uniform(ctx, "opacity_index", spc.point_color.opacity_idx);
179 point_prog.set_uniform(ctx, "secondary_opacity_index", spc.point_halo_color.opacity_idx);
180 point_prog.set_uniform(ctx, "size_index", spc.point_size.size_idx);
181 point_prog.set_uniform(ctx, "secondary_size_index", spc.point_halo_width.size_idx);
182 point_prog.set_attribute(ctx, point_prog.get_color_index(), spc.point_color.color);
183 point_prog.set_attribute(ctx, "secondary_color", spc.point_halo_color.color);
184 point_prog.set_attribute(ctx, "size", spc.point_size.size);
185 point_prog.enable(ctx);
186 color_scale_adapter.enable(ctx, color_scale_texture_unit);
187 draw_sub_plot_samples(count, spc);
189 point_prog.disable(ctx);
190 result = true;
191 }
192 }
193 disable_attributes(ctx, i);
194 return result;
195}
196bool plot2d::draw_line_plot(cgv::render::context& ctx, int i, int layer_idx)
197{
198 // skip unvisible and empty sub plots
199 if (!ref_sub_plot2d_config(i).show_plot)
200 return false;
201 GLsizei count = (GLsizei)enable_attributes(ctx, i, samples);
202 bool result = false;
203 if (count > 0) {
204 const plot2d_config& spc = ref_sub_plot2d_config(i);
205 if (spc.show_lines && line_prog.is_linked()) {
206 set_plot_uniforms(ctx, line_prog);
207 set_mapping_uniforms(ctx, line_prog);
208 line_prog.set_uniform(ctx, "sub_plot_delta", float(i) * sub_plot_delta);
209 line_prog.set_uniform(ctx, "depth_offset", -layer_idx * layer_depth);
210 line_prog.set_uniform(ctx, "reference_line_width", get_domain_config_ptr()->reference_size);
211 line_prog.set_uniform(ctx, "blend_width_in_pixel", get_domain_config_ptr()->blend_width_in_pixel);
212 line_prog.set_uniform(ctx, "halo_width_in_pixel", 0.0f);
213 line_prog.set_uniform(ctx, "halo_color_strength", 1.0f);
214 line_prog.set_uniform(ctx, "halo_color", spc.line_halo_color.color);
215 line_prog.set_uniform(ctx, "percentual_halo_width", spc.line_halo_width.size / spc.line_width.size);
216 line_prog.set_uniform(ctx, "viewport_height", (float)ctx.get_height());
217 line_prog.set_uniform(ctx, "measure_line_width_in_pixel", false);
218 line_prog.set_uniform(ctx, "screen_aligned", false);
219 line_prog.set_uniform(ctx, "color_index", spc.line_color.color_idx);
220 line_prog.set_uniform(ctx, "secondary_size_index", spc.line_halo_width.size_idx);
221 line_prog.set_uniform(ctx, "secondary_color_index", spc.line_halo_color.color_idx);
222 line_prog.set_uniform(ctx, "opacity_index", spc.line_color.opacity_idx);
223 line_prog.set_uniform(ctx, "secondary_opacity_index", spc.line_halo_color.opacity_idx);
224 line_prog.set_uniform(ctx, "size_index", spc.line_width.size_idx);
225 line_prog.set_attribute(ctx, line_prog.get_color_index(), spc.line_color.color);
226 line_prog.set_attribute(ctx, "secondary_color", spc.line_halo_color.color);
227 line_prog.set_attribute(ctx, "size", spc.line_width.size);
228 color_scale_adapter.enable(ctx, color_scale_texture_unit);
229 line_prog.enable(ctx);
230 if (strips[i].empty())
231 draw_sub_plot_samples(count, spc, true);
232 else {
233 unsigned fst = 0;
234 for (unsigned j = 0; j < strips[i].size(); ++j) {
235 glDrawArrays(GL_LINE_STRIP, fst, strips[i][j]);
236 fst += strips[i][j];
237 }
238 }
239 line_prog.disable(ctx);
241 result = true;
242 }
243 }
244 disable_attributes(ctx, i);
245 return result;
246}
247bool plot2d::draw_stick_plot(cgv::render::context& ctx, int i, int layer_idx)
248{
249 // skip unvisible and empty sub plots
250 if (!ref_sub_plot2d_config(i).show_plot)
251 return false;
252 GLsizei count = (GLsizei)enable_attributes(ctx, i, samples);
253 bool result = false;
254 if (count > 0) {
255 const plot2d_config& spc = ref_sub_plot2d_config(i);
256 if (spc.show_sticks && rectangle_prog.is_linked()) {
257 // configure vertex shader
258 rectangle_prog.set_uniform(ctx, "sub_plot_delta", float(i) * sub_plot_delta);
259 rectangle_prog.set_uniform(ctx, "color_index", spc.stick_color.color_idx);
260 rectangle_prog.set_uniform(ctx, "secondary_color_index", -1);
261 rectangle_prog.set_uniform(ctx, "opacity_index", spc.stick_color.opacity_idx);
262 rectangle_prog.set_uniform(ctx, "secondary_opacity_index", -1);
263 rectangle_prog.set_uniform(ctx, "size_index", spc.stick_width.size_idx);
264 rectangle_prog.set_uniform(ctx, "secondary_size_index", -1);
265 rectangle_prog.set_uniform(ctx, "rectangle_base_window", spc.stick_base_window);
266 rectangle_prog.set_uniform(ctx, "rectangle_coordinate_index", spc.stick_coordinate_index);
267 rectangle_prog.set_uniform(ctx, "rectangle_border_width", 0.0f);
268 rectangle_prog.set_attribute(ctx, rectangle_prog.get_color_index(), spc.stick_color.color);
269 rectangle_prog.set_attribute(ctx, "size", spc.stick_width.size * get_domain_config_ptr()->reference_size);
270 rectangle_prog.set_attribute(ctx, "depth_offset", -layer_idx * layer_depth);
271 // configure geometry shader
272 rectangle_prog.set_uniform(ctx, "border_mode", spc.stick_coordinate_index == 0 ? 2 : 1);
273
274 color_scale_adapter.enable(ctx, color_scale_texture_unit);
275 rectangle_prog.enable(ctx);
276 draw_sub_plot_samples(count, spc);
277 rectangle_prog.disable(ctx);
279 result = true;
280 }
281 }
282 disable_attributes(ctx, i);
283 return result;
284}
285void plot2d::configure_bar_plot(cgv::render::context& ctx)
286{
287 // prepare rectangle program to draw bar and stick plots
288 set_plot_uniforms(ctx, rectangle_prog);
289 set_mapping_uniforms(ctx, rectangle_prog);
290 // configure geometry shader
291 rectangle_prog.set_uniform(ctx, "pixel_blend", 2.0f);
292 rectangle_prog.set_uniform(ctx, "viewport_height", (float)ctx.get_height());
293 // configure fragment shader
294 rectangle_prog.set_uniform(ctx, "use_texture", false);
295 // configure side shader
296 rectangle_prog.set_uniform(ctx, "culling_mode", 0);
297 rectangle_prog.set_uniform(ctx, "map_color_to_material", 7);
298 rectangle_prog.set_uniform(ctx, "illumination_mode", 0);
299}
300
301bool plot2d::draw_bar_plot(cgv::render::context& ctx, int i, int layer_idx)
302{
303 // skip unvisible and empty sub plots
304 if (!ref_sub_plot2d_config(i).show_plot)
305 return false;
306 bool result = false;
307 GLsizei count = (GLsizei)enable_attributes(ctx, i, samples);
308 if (count > 0) {
309 const plot2d_config& spc = ref_sub_plot2d_config(i);
310 if (spc.show_bars && rectangle_prog.is_linked()) {
311 // configure vertex shader
312 rectangle_prog.set_uniform(ctx, "sub_plot_delta", float(i) * sub_plot_delta);
313 rectangle_prog.set_uniform(ctx, "color_index", spc.bar_color.color_idx);
314 rectangle_prog.set_uniform(ctx, "secondary_color_index", spc.bar_outline_color.color_idx);
315 rectangle_prog.set_uniform(ctx, "opacity_index", spc.bar_color.opacity_idx);
316 rectangle_prog.set_uniform(ctx, "secondary_opacity_index", spc.bar_outline_color.opacity_idx);
317 rectangle_prog.set_uniform(ctx, "size_index", spc.bar_percentual_width.size_idx);
318 rectangle_prog.set_uniform(ctx, "secondary_size_index", spc.bar_outline_width.size_idx);
319 rectangle_prog.set_uniform(ctx, "rectangle_base_window", spc.bar_base_window);
320 rectangle_prog.set_uniform(ctx, "rectangle_coordinate_index", spc.bar_coordinate_index);
321 rectangle_prog.set_uniform(ctx, "rectangle_border_width", spc.bar_outline_width.size * get_domain_config_ptr()->reference_size);
322 rectangle_prog.set_attribute(ctx, rectangle_prog.get_color_index(), spc.bar_color.color);
323 rectangle_prog.set_attribute(ctx, "secondary_color", spc.bar_outline_color.color);
324 rectangle_prog.set_attribute(ctx, "size", (count > 1 ? extent[0] / (count - 1) : extent[0]) * spc.bar_percentual_width.size);
325 rectangle_prog.set_attribute(ctx, "depth_offset", -layer_idx * layer_depth);
326 // configure geometry shader
327 rectangle_prog.set_uniform(ctx, "border_mode", spc.bar_coordinate_index == 0 ? 2 : 1);
328
329 color_scale_adapter.enable(ctx, color_scale_texture_unit);
330 rectangle_prog.enable(ctx);
331 draw_sub_plot_samples(count, spc);
332 rectangle_prog.disable(ctx);
334 result = true;
335 }
336 }
337 disable_attributes(ctx, i);
338 return result;
339}
340
341int plot2d::draw_sub_plots_jointly(cgv::render::context& ctx, int layer_idx)
342{
343 // first draw all bar plots
344 unsigned i;
345 for (i = 0; i < get_nr_sub_plots(); ++i) {
346 draw_bar_plot(ctx, i, layer_idx);
347 ++layer_idx;
348 }
349 // next draw stick plots
350 for (i = 0; i < get_nr_sub_plots(); ++i) {
351 draw_stick_plot(ctx, i, layer_idx);
352 ++layer_idx;
353 }
354 // then we draw line plots
355 for (i = 0; i < get_nr_sub_plots(); ++i) {
356 draw_line_plot(ctx, i, layer_idx);
357 ++layer_idx;
358 }
359 // finally draw point plots
360 for (i = 0; i < get_nr_sub_plots(); ++i) {
361 draw_point_plot(ctx, i, layer_idx);
362 ++layer_idx;
363 }
364 return layer_idx;
365}
366
367void plot2d::extract_domain_rectangles(std::vector<box2>& R, std::vector<rgb>& C, std::vector<float>& D)
368{
369 R.resize(5);
370 C.resize(5);
371 D.resize(5);
372 vec2 extent = vec2(this->extent[0], this->extent[1]);
374 R[0] = box2(-0.5f * extent, 0.5f * extent);
375 R[0].add_point(0.5f * extent + float(get_nr_sub_plots() - 1) * vec2(sub_plot_delta[0], sub_plot_delta[1]));
377 D[0] = 0.0f;
378 for (unsigned ai = 0; ai < 2; ++ai) {
379 axis_config& ac = get_domain_config_ptr()->axis_configs[ai];
380 axis_config& ao = get_domain_config_ptr()->axis_configs[1 - ai];
381 float lw = rs * ac.line_width;
383 vec2 axis_extent(0.0f);
384 axis_extent[ai] = extent[ai];
385 axis_extent[1 - ai] = lw;
386 box2 axis_box(-0.5f * axis_extent, 0.5f * axis_extent);
387 axis_box.ref_min_pnt()[1 - ai] += 0.5f * (extent[1 - ai] - lw);
388 axis_box.ref_max_pnt()[1 - ai] += 0.5f * (extent[1 - ai] - lw);
389 R[2 * ai + 1] = axis_box;
390 C[2 * ai + 1] = col;
391 D[2 * ai + 1] = -layer_depth;
392 axis_box.ref_min_pnt()[1 - ai] -= extent[1 - ai] - lw;
393 axis_box.ref_max_pnt()[1 - ai] -= extent[1 - ai] - lw;
394 R[2 * ai + 2] = axis_box;
395 C[2 * ai + 2] = col;
396 D[2 * ai + 2] = -layer_depth;
397 // axis line
398 if (ao.get_attribute_min() < 0 && ao.get_attribute_max() > 0) {
399 float axis_plot = ao.plot_space_from_attribute_space(0.0f);
400 axis_box.ref_min_pnt()[1 - ai] = axis_plot - 0.5f * lw;
401 axis_box.ref_max_pnt()[1 - ai] = axis_plot + 0.5f * lw;
402 R.push_back(axis_box);
403 C.push_back(ac.color);
404 D.push_back(-2 * layer_depth);
405 }
406 }
407}
408
409/*
410bool plot2d::extract_tick_rectangles_and_tick_labels(
411 std::vector<box2>& R, std::vector<rgb>& C, std::vector<float>& D,
412 std::vector<label_info>& tick_labels, int ai, int ti, float he, float z_plot)
413{
414 axis_config& ac = get_domain_config_ptr()->axis_configs[ai];
415 float acw = 1.5f * ac.line_width * get_domain_config_ptr()->reference_size;
416 tick_config& tc = ti == 0 ? ac.primary_ticks : ac.secondary_ticks;
417 if (tc.type == TT_NONE)
418 return false;
419 float min_tick = ac.tick_space_from_attribute_space(ac.get_attribute_min());
420 float max_tick = ac.tick_space_from_attribute_space(ac.get_attribute_max());
421 int min_i = (int)ceil(min_tick / tc.step - std::numeric_limits<float>::epsilon());
422 int max_i = (int)((max_tick - fmod(max_tick, tc.step)) / tc.step);
423 // ignore secondary ticks on domain boundary
424 if (ti == 1 && min_i * tc.step - min_tick < std::numeric_limits<float>::epsilon())
425 ++min_i;
426 if (ti == 1 && max_i * tc.step - max_tick > -std::numeric_limits<float>::epsilon())
427 --max_i;
428 float lw = 0.5f * get_domain_config_ptr()->reference_size * tc.line_width;
429 float dl = 0.5f * get_domain_config_ptr()->reference_size * tc.length;
430 float d = -int(ti + 3) * layer_depth;
431 for (int i = min_i; i <= max_i; ++i) {
432 float c_tick = (float)(i * tc.step);
433 float c_attr = ac.attribute_space_from_tick_space(c_tick);
434 // ignore secondary ticks on axes
435 if (fabs(c_attr) < std::numeric_limits<float>::epsilon())
436 continue;
437 // ignore secondary ticks on primary ticks
438 if (ti == 1 && fabs(fmod(c_tick, ac.primary_ticks.step)) < 0.00001f)
439 continue;
440 std::string label_str;
441 if (tc.label)
442 label_str = cgv::utils::to_string(c_attr);
443 float c_plot = ac.plot_space_from_window_space(ac.window_space_from_tick_space(c_tick));
444 vec2 mn, mx;
445 mn[ai] = c_plot - lw;
446 mx[ai] = c_plot + lw;
447 switch (tc.type) {
448 case TT_DASH:
449 mn[1 - ai] = -he;
450 mx[1 - ai] = -he + dl;
451 R.push_back(box2(mn, mx));
452 C.push_back(ac.color);
453 D.push_back(d);
454 if (!label_str.empty()) {
455 mx[1 - ai] += acw;
456 tick_labels.push_back(label_info(mx.to_vec(), label_str, ai == 0 ? cgv::render::TA_BOTTOM : cgv::render::TA_LEFT));
457 if (ti == 1)
458 tick_labels.back().scale = 0.75f;
459 }
460 mn[1 - ai] = he - dl;
461 mx[1 - ai] = he;
462 R.push_back(box2(mn, mx));
463 C.push_back(ac.color);
464 D.push_back(d);
465 if (!label_str.empty()) {
466 mn[1 - ai] -= acw;
467 tick_labels.push_back(label_info(mn.to_vec(), label_str, ai == 0 ? cgv::render::TA_TOP : cgv::render::TA_RIGHT));
468 if (ti == 1)
469 tick_labels.back().scale = 0.75f;
470 }
471 if (z_plot != std::numeric_limits<float>::quiet_NaN()) {
472 mn[1 - ai] = z_plot - dl;
473 mx[1 - ai] = z_plot + dl;
474 R.push_back(box2(mn, mx));
475 C.push_back(ac.color);
476 D.push_back(d);
477 }
478 break;
479 case TT_LINE:
480 case TT_PLANE:
481 mn[1 - ai] = -he;
482 mx[1 - ai] = he;
483 R.push_back(box2(mn, mx));
484 C.push_back(ac.color);
485 D.push_back(d);
486 if (!label_str.empty()) {
487 mn[1 - ai] += acw;
488 mx[1 - ai] -= acw;
489 mn[ai] += 2.5f * lw;
490 mx[ai] += 2.5f * lw;
491 tick_labels.push_back(label_info(mx.to_vec(), label_str, cgv::render::TextAlignment(ai == 0 ? cgv::render::TA_TOP + cgv::render::TA_LEFT : cgv::render::TA_RIGHT + cgv::render::TA_BOTTOM)));
492 if (ti == 1)
493 tick_labels.back().scale = 0.75f;
494 tick_labels.push_back(label_info(mn.to_vec(), label_str, cgv::render::TextAlignment(ai == 0 ? cgv::render::TA_BOTTOM + cgv::render::TA_LEFT : cgv::render::TA_LEFT + cgv::render::TA_BOTTOM)));
495 if (ti == 1)
496 tick_labels.back().scale = 0.75f;
497 }
498 break;
499 }
500 }
501 return true;
502}
503*/
504
505void plot2d::extract_domain_tick_rectangles_and_tick_labels(
506 std::vector<box2>& R, std::vector<rgb>& C, std::vector<float>& D,
507 std::vector<label_info>& tick_labels, std::vector<tick_batch_info>& tick_batches)
508{
509 vecn E = get_extent();
510 set_extent(vecn(2, &extent[0]));
511 tick_labels.clear();
512 tick_batches.clear();
513 for (unsigned ti = 0; ti < 2; ++ti) {
514 for (unsigned ai = 0; ai < 2; ++ai) {
515 axis_config& ac = get_domain_config_ptr()->axis_configs[ai];
516 axis_config& ao = get_domain_config_ptr()->axis_configs[1 - ai];
517 float z_plot = (ao.get_attribute_min() < 0.0f && ao.get_attribute_max() > 0.0f) ?
518 ao.plot_space_from_attribute_space(0.0f) : std::numeric_limits<float>::quiet_NaN();
519 tick_batch_info tbi(ai, 1 - ai, ti == 0, 0, (unsigned)tick_labels.size());
520 if (extract_tick_rectangles_and_tick_labels(R, C, D, tick_labels, ai, ai, ti, 0.5f * ao.extent, z_plot, 1.0f, vec2(0.0f), -3 * layer_depth, ac.multi_axis_ticks)) {
521 if ((tbi.label_count = (unsigned)(tick_labels.size() - tbi.first_label)) > 0)
522 tick_batches.push_back(tbi);
523 }
524 }
525 }
526 set_extent(E);
527}
528
529void plot2d::draw_domain(cgv::render::context& ctx, int si, bool no_fill)
530{
531 std::vector<box2> R;
532 std::vector<rgb> C;
533 std::vector<float> D;
534 extract_domain_rectangles(R, C, D);
535 extract_domain_tick_rectangles_and_tick_labels(R, C, D, tick_labels, tick_batches);
536 draw_rectangles(ctx, aam_domain, R, C, D, (get_domain_config_ptr()->fill && !no_fill) ? 0 : 1);
537 draw_title(ctx, vec2::from_vec(get_domain_config_ptr()->title_pos), -3 * layer_depth, si);
538 draw_tick_labels(ctx, aam_domain_tick_labels, tick_labels, tick_batches, -4 * layer_depth);
539}
540
542{
544
545 ctx.push_blend_state();
546 ctx.enable_blending();
548 ctx.push_cull_state();
549 ctx.set_cull_state(cgv::render::CM_OFF);
551 ctx.set_depth_func(cgv::render::CF_LEQUAL);
552 ctx.push_buffer_mask();
553
554 // place plot with modelview matrix
556 mat4 R;
558 ctx.mul_modelview_matrix(cgv::math::translate4<float>(center_location) * R);
559
560 // configure bar prog only once
561 configure_bar_plot(ctx);
562 // draw all subplots jointly in one plane
563 if (sub_plot_delta[2] == 0.0f) {
564 if (get_domain_config_ptr()->show_domain)
565 draw_domain(ctx);
566 if (legend_components != LC_HIDDEN)
567 draw_legend(ctx, 5);
568 if (disable_depth_mask)
569 ctx.set_depth_mask(false);
570 else
571 ctx.set_depth_func(cgv::render::CF_LEQUAL);
572 draw_sub_plots_jointly(ctx, 8);
573 if (disable_depth_mask)
574 ctx.set_depth_mask(true);
575 else
576 ctx.set_depth_func(cgv::render::CF_LESS);
577 }
578 // draw subplots with offset in back to front order
579 else {
580 auto M = ctx.get_modelview_matrix();
581 double plot_pos_eye_z = M(2, 3);
582 double plot_z_eye_z = M(2, 2);
583 int i_begin = 0, i_end = get_nr_sub_plots(), i_delta = 1;
584 // check if we can not use default order
585 if (plot_pos_eye_z * plot_z_eye_z * sub_plot_delta[2] > 0) {
586 i_begin = i_end - 1;
587 i_end = -1;
588 i_delta = -1;
589 ctx.mul_modelview_matrix(cgv::math::translate4<float>(vec3(0, 0, (get_nr_sub_plots()-1) * sub_plot_delta[2])));
590 }
591 // traverse all subplots in back to front order
592 bool fst = true;
593 unsigned ai;
594 for (ai=0; ai<2+nr_attributes; ++ai)
595 if (multi_axis_modes[ai])
596 get_domain_config_ptr()->axis_configs[ai].backup_attribute_range();
597 for (int i = i_begin; i != i_end; i += i_delta) {
598 // adapt all axes in multi axis mode
599 for (ai = 0; ai < 2 + nr_attributes; ++ai) {
600 if (multi_axis_modes[ai]) {
601 auto& ac = get_domain_config_ptr()->axis_configs[ai];
602 float min_val, max_val;
603 ac.put_backup_attribute_range(min_val, max_val);
604 if (determine_axis_extent_from_subplot(ai, i, min_val, max_val)) {
605 if (fabs(max_val - min_val) < 10.0f * std::numeric_limits<float>::epsilon())
606 max_val = min_val + 1;
607 ac.set_attribute_range(min_val, max_val);
608 }
609
610 }
611 }
612 if (get_domain_config_ptr()->show_domain)
613 draw_domain(ctx, i, !fst);
614 if (legend_components != LC_HIDDEN)
615 draw_legend(ctx, 5, i == i_begin, multi_axis_modes);
616 if (disable_depth_mask)
617 ctx.set_depth_mask(false);
618 else
619 ctx.set_depth_func(cgv::render::CF_LEQUAL);
620 draw_bar_plot(ctx, i, 8);
621 draw_stick_plot(ctx, i, 9);
622 draw_line_plot(ctx, i, 10);
623 draw_point_plot(ctx, i, 11);
624 if (disable_depth_mask)
625 ctx.set_depth_mask(true);
626 else
627 ctx.set_depth_func(cgv::render::CF_LESS);
628 ctx.mul_modelview_matrix(cgv::math::translate4<float>(vec3(0, 0, i_delta* sub_plot_delta[2])));
629 fst = false;
630 }
631 for (ai = 0; ai < 2 + nr_attributes; ++ai)
632 if (multi_axis_modes[ai])
633 get_domain_config_ptr()->axis_configs[ai].restore_attribute_range();
634 }
635
637
638 ctx.pop_blend_state();
639 ctx.pop_cull_state();
641 ctx.pop_buffer_mask();
642}
643
646{
647 auto& p2dc = reinterpret_cast<plot2d_config&>(pbc);
649}
650
653{
654 auto& p2dc = reinterpret_cast<plot2d_config&>(pbc);
656}
657
660{
661 auto& p2dc = reinterpret_cast<plot2d_config&>(pbc);
663}
664
669
671{
672 if (p.begin_tree_node("Multi Modes", multi_axis_modes, false, "level=3")) {
673 p.align("\a");
674 for (unsigned ai = 0; ai < 2 + nr_attributes; ++ai)
675 p.add_member_control(bp, get_domain_config_ptr()->axis_configs[ai].name, multi_axis_modes[ai], "toggle");
676 p.align("\b");
678 }
679 p.add_member_control(bp, "Delta X", sub_plot_delta[0], "value_slider", "min=-1;max=1;step=0.001;ticks=true");
680 p.add_member_control(bp, "Delta Y", sub_plot_delta[1], "value_slider", "min=-1;max=1;step=0.001;ticks=true");
681 p.add_member_control(bp, "Delta Z", sub_plot_delta[2], "value_slider", "min=-1;max=1;step=0.02;ticks=true");
683 p.add_member_control(bp, "Disable Depth Mask", disable_depth_mask, "toggle");
684}
685
686 }
687}
base class for all classes that can be registered with support for dynamic properties (see also secti...
Definition base.h:75
derive from this class to provide a gui to the current viewer
Definition provider.h:64
void align(const std::string &_align)
send pure alignment information
Definition provider.cxx:36
bool begin_tree_node(const std::string &label, const T &value, bool initial_visibility=false, const std::string &options="", gui_group_ptr ggp=gui_group_ptr())
Begin a sub tree of a tree structured gui.
Definition provider.h:212
data::ref_ptr< control< T > > add_member_control(cgv::base::base *base_ptr, const std::string &label, T &value, const std::string &gui_type="", const std::string &options="", const std::string &align="\n")
add control with callback to cgv::base::on_set method on cgv::gui::control::value_change
Definition provider.h:137
void end_tree_node(const T &value)
template specialization that allows to specify value reference plus node_instance by using the result...
Definition provider.h:222
static fvec< float, N > from_vec(const vec< float > &)
conversion from vector
Definition fvec.h:752
void put_homogeneous_matrix(hmat_type &M) const
compute equivalent homogeneous 4x4 rotation matrix
Definition quaternion.h:154
void create_stick_config_gui(cgv::base::base *bp, cgv::gui::provider &p, plot_base_config &pbc)
create the gui for a stick subplot
Definition plot2d.cxx:652
void clear(cgv::render::context &ctx)
destruct shader programs
Definition plot2d.cxx:145
std::vector< std::vector< unsigned > > strips
allow to split series into connected strips that are represented by the number of contained samples
Definition plot2d.h:49
void create_point_config_gui(cgv::base::base *bp, cgv::gui::provider &p, plot_base_config &pbc)
create the gui for a point subplot
Definition plot2d.cxx:645
std::vector< vec2 > & ref_sub_plot_samples(unsigned i=0)
return the samples of the i-th sub plot
Definition plot2d.cxx:106
void create_gui(cgv::base::base *bp, cgv::gui::provider &p)
create a gui for the plot with gui for all configs
Definition plot2d.cxx:670
cgv::render::attribute_array_manager aam_domain
attribute managers for domain rectangles and domain tick labels
Definition plot2d.h:51
void delete_sub_plot(unsigned i)
delete the i-th sub plot
Definition plot2d.cxx:91
void create_bar_config_gui(cgv::base::base *bp, cgv::gui::provider &p, plot_base_config &pbc)
create the gui for a bar subplot
Definition plot2d.cxx:659
void draw(cgv::render::context &ctx)
draw plot
Definition plot2d.cxx:541
std::vector< unsigned > & ref_sub_plot_strips(unsigned i=0)
return the strip definition of the i-th sub plot
Definition plot2d.cxx:112
plot2d_config & ref_sub_plot2d_config(unsigned i=0)
return a reference to the plot1d configuration of the i-th plot
Definition plot2d.cxx:101
bool * multi_axis_modes
whether to manage separate axes for each sub plot
Definition plot2d.h:55
vec3 sub_plot_delta
offset in between sub plots in x, y and z direction
Definition plot2d.h:57
void create_config_gui(cgv::base::base *bp, cgv::gui::provider &p, unsigned i)
create the gui for a subplot configuration
Definition plot2d.cxx:665
unsigned add_sub_plot(const std::string &name)
add sub plot and return sub plot index
Definition plot2d.cxx:68
plot2d(const std::string &title, unsigned nr_attributes=0)
construct 2D plot with given number of additional attributes and default parameters
Definition plot2d.cxx:24
std::vector< std::vector< vec2 > > samples
store 2d samples for data series
Definition plot2d.h:47
bool init(cgv::render::context &ctx)
construct shader programs
Definition plot2d.cxx:117
base class for plot2d and plot3d, which can have several sub plots each
Definition plot_base.h:286
cgv::render::rectangle_render_style rrs
render style of rectangles
Definition plot_base.h:466
virtual void create_config_gui(cgv::base::base *bp, cgv::gui::provider &p, unsigned i)
create the gui for a subplot configuration
virtual void create_bar_config_gui(cgv::base::base *bp, cgv::gui::provider &p, plot_base_config &pbc)
create the gui for a bar subplot
const domain_config * get_domain_config_ptr() const
return const pointer to domain configuration
void clear(cgv::render::context &ctx)
destruct shader programs
unsigned get_nr_sub_plots() const
return current number of sub plots
LegendComponent legend_components
whether to show legend
Definition plot_base.h:370
std::vector< attribute_source_array > attribute_source_arrays
attribute sources
Definition plot_base.h:444
vecn get_extent() const
query the plot extend in 2D coordinates
bool determine_axis_extent_from_subplot(unsigned ai, unsigned i, float &sample_min, float &sample_max)
adjust the domain with respect to ai th axis to the i-th subplot
float layer_depth
depth offset of a single layer
Definition plot_base.h:327
quat orientation
orientiation quaternion mapping from domain to world coordinates
Definition plot_base.h:358
void set_mapping_uniforms(cgv::render::context &ctx, cgv::render::shader_program &prog)
set the uniforms for defining the mappings to visual variables
vec3 center_location
center location of domain in world coordinates
Definition plot_base.h:360
std::vector< plot_base_config * > configs
store one configuration per sub plot
Definition plot_base.h:352
std::vector< label_info > tick_labels
all tick labels
Definition plot_base.h:323
plot_base_config & ref_sub_plot_config(unsigned i)
return a reference to the plot base configuration of the i-th plot
unsigned nr_attributes
number of additional attributes
Definition plot_base.h:346
void prepare_extents()
prepare extents for drawing
virtual void create_gui(cgv::base::base *bp, cgv::gui::provider &p)
create a gui for the plot with gui for all configs
virtual void create_point_config_gui(cgv::base::base *bp, cgv::gui::provider &p, plot_base_config &pbc)
create the gui for a point subplot
std::vector< tick_batch_info > tick_batches
twice number of axis pairs with index of first tick label and number of tick labels for primary and s...
Definition plot_base.h:325
cgv::render::color_scale_adapter color_scale_adapter
adapter to enable using color scales in shader programs
Definition plot_base.h:425
void set_extent(const vecn &new_extent)
set the plot extend in 2D coordinates
virtual void create_stick_config_gui(cgv::base::base *bp, cgv::gui::provider &p, plot_base_config &pbc)
create the gui for a stick subplot
void set_plot_uniforms(cgv::render::context &ctx, cgv::render::shader_program &prog)
set the uniforms for plot configurations
size_t enable_attributes(cgv::render::context &ctx, int i, const std::vector< std::vector< vec2 > > &samples)
set vertex shader input attributes based on attribute source information
bool init(cgv::render::context &ctx)
build legend prog and create aab
vec3 extent
extents used for drawing current
Definition plot_base.h:452
bool disable(const context &ctx)
Disable the managed render resources after rendering.
bool enable(const context &ctx, int texture_unit)
Enable the managed render resources to prepare for rendering.
base class for all drawables, which is independent of the used rendering API.
Definition context.h:668
void set_blend_func_back_to_front()
set the default blend function for back to front blending (source = BF_SRC_ALPHA, destination = BF_ON...
Definition context.cxx:1877
virtual void mul_modelview_matrix(const dmat4 &MV)
multiply given matrix from right to current modelview matrix
Definition context.cxx:1933
void pop_buffer_mask()
pop the top of the current buffer mask from the stack
Definition context.cxx:1893
void push_depth_test_state()
push a copy of the current depth test state onto the stack saved attributes: depth test enablement,...
Definition context.cxx:1794
void push_blend_state()
push a copy of the current blend state onto the stack saved attributes: blend enablement,...
Definition context.cxx:1841
void pop_blend_state()
pop the top of the current culling state from the stack
Definition context.cxx:1845
void pop_depth_test_state()
pop the top of the current depth test state from the stack
Definition context.cxx:1798
virtual unsigned int get_height() const =0
return the height of the window
void push_cull_state()
push a copy of the current culling state onto the stack saved attributes: cull face enablement,...
Definition context.cxx:1824
virtual void set_cull_state(CullingMode culling_mode)
set the culling state
Definition context.cxx:1837
virtual void set_depth_func(CompareFunction func)
set the depth test function
Definition context.cxx:1811
virtual void enable_blending()
enable blending
Definition context.cxx:1881
virtual dmat4 get_modelview_matrix() const =0
return homogeneous 4x4 viewing matrix, which transforms from world to eye space
void pop_cull_state()
pop the top of the current culling state from the stack
Definition context.cxx:1828
void pop_modelview_matrix()
see push_V for an explanation
Definition context.cxx:1939
void push_modelview_matrix()
push the current viewing matrix onto a matrix stack for viewing matrices.
Definition context.cxx:1927
void push_buffer_mask()
push a copy of the current buffer mask onto the stack saved attributes: depth mask,...
Definition context.cxx:1889
virtual void set_depth_mask(bool flag)
set the depth buffer mask
Definition context.cxx:1910
Stores preprocessor options used for conditionally compiling shader programs.
Definition shader_code.h:73
void define_macro(const std::string &identifier)
Define a macro as identifier and no replacement text.
Definition shader_code.h:99
bool enable(context &ctx)
enable the shader program
bool disable(context &ctx)
disable shader program and restore fixed functionality
bool set_uniform(const context &ctx, const std::string &name, const T &value, bool generate_error=false)
Set the value of a uniform by name, where the type can be any of int, unsigned, float,...
void destruct(const context &ctx)
destruct shader program
bool is_linked() const
return whether program is linked
bool set_attribute(const context &ctx, const std::string &name, const T &value)
set constant default value of a vertex attribute by attribute name, if name does not specify an attri...
bool build_program(const context &ctx, const std::string &file_name, bool show_error=false)
successively calls create, attach_program and link.
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
T min_value(ForwardIt first, ForwardIt last, T fallback)
Find the minimum value in the range [first, last) or return fallback if the range is empty.
Definition algorithm.h:57
T max_value(ForwardIt first, ForwardIt last, T fallback)
Find the maximum value in the range [first, last) or return fallback if the range is empty.
Definition algorithm.h:89
this header is dependency free
Definition print.h:11
cgv::math::vec< float > vecn
declare type of single precision floating point vector with varying dimension
Definition vec.h:1187
cgv::media::color< float, cgv::media::RGB > rgb
declare rgb color type with 32 bit components
Definition color.h:896
cgv::math::fvec< float, 2 > vec2
declare type of 2d single precision floating point vectors
Definition fvec.h:681
cgv::media::axis_aligned_box< float, 2 > box2
declare type of 2d single precision floating point axis-aligned boxes
cgv::math::fvec< float, 3 > vec3
declare type of 3d single precision floating point vectors
Definition fvec.h:683
struct that manages attribute sources and corresponding gpu objects per subplot
Definition plot_base.h:256
store source of a single plot attribute (one coordinate axis or one float attribute)
Definition plot_base.h:232
float reference_size
store size of virtual pixel based measurement
Definition plot_base.h:56
bool fill
whether to fill the domain
Definition plot_base.h:42
std::string title
plot title
Definition plot_base.h:44
std::vector< axis_config > axis_configs
store a vector of axis configurations (2/3 for plot2/3d plus several attribute axes)
Definition plot_base.h:60
rgb color
color of the domain fill
Definition plot_base.h:52
extend common plot configuration with parameters specific to 2d plot
Definition plot2d.h:15
void configure_chart(ChartType chart_type)
configure the sub plot to a specific chart type
Definition plot2d.cxx:17
plot2d_config(const std::string &_name)
set default values
Definition plot2d.cxx:11
plot independent configuration parameters of one sub plot in a 2d or 3d plot
Definition plot_base.h:134
virtual void configure_chart(ChartType chart_type)
configure the sub plot to a specific chart type
Definition plot_base.cxx:68
std::string name
name of sub plot
Definition plot_base.h:136
bool show_lines
whether to connect data points with lines
Definition plot_base.h:168
bool show_points
whether to show data points
Definition plot_base.h:156
mapped_rgba point_color
point color
Definition plot_base.h:161
mapped_size point_halo_width
width of point halo in pixel
Definition plot_base.h:163
mapped_size point_size
point size in pixels
Definition plot_base.h:158
mapped_rgba point_halo_color
color of point halo
Definition plot_base.h:165