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>
29 disable_depth_mask =
false;
44bool plot2d::compute_sample_coordinate_interval(
int i,
int ai,
float& samples_min,
float& samples_max)
47 bool found_sample =
false;
48 float min_value, max_value;
49 for (
unsigned j = 0; j <
samples[i].size(); ++j) {
51 min_value = std::min(min_value,
samples[i][j](ai));
52 max_value = std::max(max_value,
samples[i][j](ai));
61 samples_min = min_value;
62 samples_max = max_value;
82 samples.push_back(std::vector<vec2>());
83 strips.push_back(std::vector<unsigned>());
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;
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;
132 point_prog.allow_context_to_set_color(
false);
133 if (!rectangle_prog.
build_program(ctx,
"plot2d_rect.glpr",
true, { {
"PLOT_MODE",
"1"} })) {
134 std::cerr <<
"could not build GLSL program from plot2d_rect.glpr" << std::endl;
138 rectangle_prog.allow_context_to_set_color(
false);
144 aam_domain.destruct(ctx);
145 aam_domain_tick_labels.destruct(ctx);
146 point_prog.destruct(ctx);
147 line_prog.destruct(ctx);
148 rectangle_prog.destruct(ctx);
149 plot_base::clear(ctx);
155 if (!ref_sub_plot2d_config(i).show_plot)
157 GLsizei count = (GLsizei)enable_attributes(ctx, i, samples);
162 set_plot_uniforms(ctx, point_prog);
163 set_mapping_uniforms(ctx, point_prog);
164 point_prog.set_uniform(ctx,
"sub_plot_delta",
float(i) * sub_plot_delta);
165 point_prog.set_uniform(ctx,
"depth_offset", -layer_idx * layer_depth);
166 point_prog.set_uniform(ctx,
"reference_point_size", get_domain_config_ptr()->reference_size);
167 point_prog.set_uniform(ctx,
"blend_width_in_pixel", get_domain_config_ptr()->blend_width_in_pixel);
168 point_prog.set_uniform(ctx,
"halo_width_in_pixel", 0.0f);
170 point_prog.set_uniform(ctx,
"viewport_height", (
float)ctx.
get_height());
171 point_prog.set_uniform(ctx,
"measure_point_size_in_pixel",
false);
172 point_prog.set_uniform(ctx,
"screen_aligned",
false);
173 point_prog.set_uniform(ctx,
"color_index", spc.
point_color.color_idx);
174 point_prog.set_uniform(ctx,
"secondary_color_index", spc.
point_halo_color.color_idx);
175 point_prog.set_uniform(ctx,
"opacity_index", spc.
point_color.opacity_idx);
176 point_prog.set_uniform(ctx,
"secondary_opacity_index", spc.
point_halo_color.opacity_idx);
177 point_prog.set_uniform(ctx,
"size_index", spc.
point_size.size_idx);
178 point_prog.set_uniform(ctx,
"secondary_size_index", spc.
point_halo_width.size_idx);
179 point_prog.set_attribute(ctx, point_prog.get_color_index(), spc.
point_color.color);
180 point_prog.set_attribute(ctx,
"secondary_color", spc.
point_halo_color.color);
181 point_prog.set_attribute(ctx,
"size", spc.
point_size.size);
182 point_prog.enable(ctx);
183 draw_sub_plot_samples(count, spc);
184 point_prog.disable(ctx);
188 disable_attributes(ctx, i);
194 if (!ref_sub_plot2d_config(i).show_plot)
196 GLsizei count = (GLsizei)enable_attributes(ctx, i, samples);
199 const plot2d_config& spc = ref_sub_plot2d_config(i);
200 if (spc.show_lines && line_prog.is_linked()) {
201 set_plot_uniforms(ctx, line_prog);
202 set_mapping_uniforms(ctx, line_prog);
203 line_prog.set_uniform(ctx,
"sub_plot_delta",
float(i) * sub_plot_delta);
204 line_prog.set_uniform(ctx,
"depth_offset", -layer_idx * layer_depth);
205 line_prog.set_uniform(ctx,
"reference_line_width", get_domain_config_ptr()->reference_size);
206 line_prog.set_uniform(ctx,
"blend_width_in_pixel", get_domain_config_ptr()->blend_width_in_pixel);
207 line_prog.set_uniform(ctx,
"halo_width_in_pixel", 0.0f);
208 line_prog.set_uniform(ctx,
"halo_color_strength", 1.0f);
209 line_prog.set_uniform(ctx,
"halo_color", spc.line_halo_color.color);
210 line_prog.set_uniform(ctx,
"percentual_halo_width", spc.line_halo_width.size / spc.line_width.size);
211 line_prog.set_uniform(ctx,
"viewport_height", (
float)ctx.
get_height());
212 line_prog.set_uniform(ctx,
"measure_line_width_in_pixel",
false);
213 line_prog.set_uniform(ctx,
"screen_aligned",
false);
214 line_prog.set_uniform(ctx,
"color_index", spc.line_color.color_idx);
215 line_prog.set_uniform(ctx,
"secondary_size_index", spc.line_halo_width.size_idx);
216 line_prog.set_uniform(ctx,
"secondary_color_index", spc.line_halo_color.color_idx);
217 line_prog.set_uniform(ctx,
"opacity_index", spc.line_color.opacity_idx);
218 line_prog.set_uniform(ctx,
"secondary_opacity_index", spc.line_halo_color.opacity_idx);
219 line_prog.set_uniform(ctx,
"size_index", spc.line_width.size_idx);
220 line_prog.set_attribute(ctx, line_prog.get_color_index(), spc.line_color.color);
221 line_prog.set_attribute(ctx,
"secondary_color", spc.line_halo_color.color);
222 line_prog.set_attribute(ctx,
"size", spc.line_width.size);
223 line_prog.enable(ctx);
224 if (strips[i].empty())
225 draw_sub_plot_samples(count, spc,
true);
228 for (
unsigned j = 0; j < strips[i].size(); ++j) {
229 glDrawArrays(GL_LINE_STRIP, fst, strips[i][j]);
233 line_prog.disable(ctx);
237 disable_attributes(ctx, i);
243 if (!ref_sub_plot2d_config(i).show_plot)
245 GLsizei count = (GLsizei)enable_attributes(ctx, i, samples);
248 const plot2d_config& spc = ref_sub_plot2d_config(i);
249 if (spc.show_sticks && rectangle_prog.is_linked()) {
251 rectangle_prog.set_uniform(ctx,
"sub_plot_delta",
float(i) * sub_plot_delta);
252 rectangle_prog.set_uniform(ctx,
"color_index", spc.stick_color.color_idx);
253 rectangle_prog.set_uniform(ctx,
"secondary_color_index", -1);
254 rectangle_prog.set_uniform(ctx,
"opacity_index", spc.stick_color.opacity_idx);
255 rectangle_prog.set_uniform(ctx,
"secondary_opacity_index", -1);
256 rectangle_prog.set_uniform(ctx,
"size_index", spc.stick_width.size_idx);
257 rectangle_prog.set_uniform(ctx,
"secondary_size_index", -1);
258 rectangle_prog.set_uniform(ctx,
"rectangle_base_window", spc.stick_base_window);
259 rectangle_prog.set_uniform(ctx,
"rectangle_coordinate_index", spc.stick_coordinate_index);
260 rectangle_prog.set_uniform(ctx,
"rectangle_border_width", 0.0f);
261 rectangle_prog.set_attribute(ctx, rectangle_prog.get_color_index(), spc.stick_color.color);
262 rectangle_prog.set_attribute(ctx,
"size", spc.stick_width.size * get_domain_config_ptr()->reference_size);
263 rectangle_prog.set_attribute(ctx,
"depth_offset", -layer_idx * layer_depth);
265 rectangle_prog.set_uniform(ctx,
"border_mode", spc.stick_coordinate_index == 0 ? 2 : 1);
267 rectangle_prog.enable(ctx);
268 draw_sub_plot_samples(count, spc);
269 rectangle_prog.disable(ctx);
273 disable_attributes(ctx, i);
279 set_plot_uniforms(ctx, rectangle_prog);
280 set_mapping_uniforms(ctx, rectangle_prog);
282 rectangle_prog.set_uniform(ctx,
"pixel_blend", 2.0f);
283 rectangle_prog.set_uniform(ctx,
"viewport_height", (
float)ctx.
get_height());
285 rectangle_prog.set_uniform(ctx,
"use_texture",
false);
287 rectangle_prog.set_uniform(ctx,
"culling_mode", 0);
288 rectangle_prog.set_uniform(ctx,
"map_color_to_material", 7);
289 rectangle_prog.set_uniform(ctx,
"illumination_mode", 0);
295 if (!ref_sub_plot2d_config(i).show_plot)
298 GLsizei count = (GLsizei)enable_attributes(ctx, i, samples);
300 const plot2d_config& spc = ref_sub_plot2d_config(i);
301 if (spc.show_bars && rectangle_prog.is_linked()) {
303 rectangle_prog.set_uniform(ctx,
"sub_plot_delta",
float(i) * sub_plot_delta);
304 rectangle_prog.set_uniform(ctx,
"color_index", spc.bar_color.color_idx);
305 rectangle_prog.set_uniform(ctx,
"secondary_color_index", spc.bar_outline_color.color_idx);
306 rectangle_prog.set_uniform(ctx,
"opacity_index", spc.bar_color.opacity_idx);
307 rectangle_prog.set_uniform(ctx,
"secondary_opacity_index", spc.bar_outline_color.opacity_idx);
308 rectangle_prog.set_uniform(ctx,
"size_index", spc.bar_percentual_width.size_idx);
309 rectangle_prog.set_uniform(ctx,
"secondary_size_index", spc.bar_outline_width.size_idx);
310 rectangle_prog.set_uniform(ctx,
"rectangle_base_window", spc.bar_base_window);
311 rectangle_prog.set_uniform(ctx,
"rectangle_coordinate_index", spc.bar_coordinate_index);
312 rectangle_prog.set_uniform(ctx,
"rectangle_border_width", spc.bar_outline_width.size * get_domain_config_ptr()->reference_size);
313 rectangle_prog.set_attribute(ctx, rectangle_prog.get_color_index(), spc.bar_color.color);
314 rectangle_prog.set_attribute(ctx,
"secondary_color", spc.bar_outline_color.color);
315 rectangle_prog.set_attribute(ctx,
"size", (count > 1 ? extent[0] / (count - 1) : extent[0]) * spc.bar_percentual_width.size);
316 rectangle_prog.set_attribute(ctx,
"depth_offset", -layer_idx * layer_depth);
318 rectangle_prog.set_uniform(ctx,
"border_mode", spc.bar_coordinate_index == 0 ? 2 : 1);
320 rectangle_prog.enable(ctx);
321 draw_sub_plot_samples(count, spc);
322 rectangle_prog.disable(ctx);
326 disable_attributes(ctx, i);
334 for (i = 0; i < get_nr_sub_plots(); ++i) {
335 draw_bar_plot(ctx, i, layer_idx);
339 for (i = 0; i < get_nr_sub_plots(); ++i) {
340 draw_stick_plot(ctx, i, layer_idx);
344 for (i = 0; i < get_nr_sub_plots(); ++i) {
345 draw_line_plot(ctx, i, layer_idx);
349 for (i = 0; i < get_nr_sub_plots(); ++i) {
350 draw_point_plot(ctx, i, layer_idx);
356void plot2d::extract_domain_rectangles(std::vector<box2>& R, std::vector<rgb>& C, std::vector<float>& D)
361 vec2 extent =
vec2(this->extent[0], this->extent[1]);
362 float rs = get_domain_config_ptr()->reference_size;
363 R[0] =
box2(-0.5f * extent, 0.5f * extent);
364 R[0].add_point(0.5f * extent +
float(get_nr_sub_plots() - 1) *
vec2(sub_plot_delta[0], sub_plot_delta[1]));
365 C[0] = get_domain_config_ptr()->color;
367 for (
unsigned ai = 0; ai < 2; ++ai) {
368 axis_config& ac = get_domain_config_ptr()->axis_configs[ai];
369 axis_config& ao = get_domain_config_ptr()->axis_configs[1 - ai];
370 float lw = rs * ac.line_width;
371 rgb col = get_domain_config_ptr()->fill ? ac.
color : get_domain_config_ptr()->color;
372 vec2 axis_extent(0.0f);
373 axis_extent[ai] = extent[ai];
374 axis_extent[1 - ai] = lw;
375 box2 axis_box(-0.5f * axis_extent, 0.5f * axis_extent);
376 axis_box.ref_min_pnt()[1 - ai] += 0.5f * (extent[1 - ai] - lw);
377 axis_box.ref_max_pnt()[1 - ai] += 0.5f * (extent[1 - ai] - lw);
378 R[2 * ai + 1] = axis_box;
380 D[2 * ai + 1] = -layer_depth;
381 axis_box.ref_min_pnt()[1 - ai] -= extent[1 - ai] - lw;
382 axis_box.ref_max_pnt()[1 - ai] -= extent[1 - ai] - lw;
383 R[2 * ai + 2] = axis_box;
385 D[2 * ai + 2] = -layer_depth;
387 if (ao.get_attribute_min() < 0 && ao.get_attribute_max() > 0) {
388 float axis_plot = ao.plot_space_from_attribute_space(0.0f);
389 axis_box.ref_min_pnt()[1 - ai] = axis_plot - 0.5f * lw;
390 axis_box.ref_max_pnt()[1 - ai] = axis_plot + 0.5f * lw;
391 R.push_back(axis_box);
392 C.push_back(ac.color);
393 D.push_back(-2 * layer_depth);
494void plot2d::extract_domain_tick_rectangles_and_tick_labels(
495 std::vector<box2>& R, std::vector<rgb>& C, std::vector<float>& D,
496 std::vector<label_info>& tick_labels, std::vector<tick_batch_info>& tick_batches)
498 vecn E = get_extent();
499 set_extent(
vecn(2, &extent[0]));
501 tick_batches.clear();
502 for (
unsigned ti = 0; ti < 2; ++ti) {
503 for (
unsigned ai = 0; ai < 2; ++ai) {
504 axis_config& ac = get_domain_config_ptr()->axis_configs[ai];
505 axis_config& ao = get_domain_config_ptr()->axis_configs[1 - ai];
506 float z_plot = (ao.get_attribute_min() < 0.0f && ao.get_attribute_max() > 0.0f) ?
507 ao.plot_space_from_attribute_space(0.0f) : std::numeric_limits<float>::quiet_NaN();
508 tick_batch_info tbi(ai, 1 - ai, ti == 0, 0, (
unsigned)tick_labels.size());
509 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)) {
510 if ((tbi.label_count = (
unsigned)(tick_labels.size() - tbi.first_label)) > 0)
511 tick_batches.push_back(tbi);
522 std::vector<float> D;
523 extract_domain_rectangles(R, C, D);
524 extract_domain_tick_rectangles_and_tick_labels(R, C, D, tick_labels, tick_batches);
525 draw_rectangles(ctx, aam_domain, R, C, D, (get_domain_config_ptr()->fill && !no_fill) ? 0 : 1);
526 draw_title(ctx,
vec2::from_vec(get_domain_config_ptr()->title_pos), -3 * layer_depth, si);
527 draw_tick_labels(ctx, aam_domain_tick_labels, tick_labels, tick_batches, -4 * layer_depth);
535 GLboolean line_smooth = glIsEnabled(GL_LINE_SMOOTH);
536 GLboolean blend = glIsEnabled(GL_BLEND);
537 GLboolean cull_face = glIsEnabled(GL_CULL_FACE);
538 GLenum blend_src, blend_dst, depth;
539 glGetIntegerv(GL_BLEND_DST,
reinterpret_cast<GLint*
>(&blend_dst));
540 glGetIntegerv(GL_BLEND_SRC,
reinterpret_cast<GLint*
>(&blend_src));
541 glGetIntegerv(GL_DEPTH_FUNC,
reinterpret_cast<GLint*
>(&depth));
544 glEnable(GL_LINE_SMOOTH);
545 glDisable(GL_CULL_FACE);
547 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
548 glDepthFunc(GL_LEQUAL);
553 orientation.put_homogeneous_matrix(R);
557 configure_bar_plot(ctx);
559 if (sub_plot_delta[2] == 0.0f) {
560 if (get_domain_config_ptr()->show_domain)
562 if (legend_components != LC_HIDDEN)
564 if (disable_depth_mask)
565 glDepthMask(GL_FALSE);
567 glDepthFunc(GL_LEQUAL);
568 draw_sub_plots_jointly(ctx, 8);
569 if (disable_depth_mask)
570 glDepthMask(GL_TRUE);
572 glDepthFunc(GL_LESS);
577 double plot_pos_eye_z = M(2, 3);
578 double plot_z_eye_z = M(2, 2);
579 int i_begin = 0, i_end = get_nr_sub_plots(), i_delta = 1;
581 if (plot_pos_eye_z * plot_z_eye_z * sub_plot_delta[2] > 0) {
590 for (ai=0; ai<2+nr_attributes; ++ai)
591 if (multi_axis_modes[ai])
592 get_domain_config_ptr()->axis_configs[ai].backup_attribute_range();
593 for (
int i = i_begin; i != i_end; i += i_delta) {
595 for (ai = 0; ai < 2 + nr_attributes; ++ai) {
596 if (multi_axis_modes[ai]) {
597 auto& ac = get_domain_config_ptr()->axis_configs[ai];
598 float min_val, max_val;
599 ac.put_backup_attribute_range(min_val, max_val);
600 if (determine_axis_extent_from_subplot(ai, i, min_val, max_val)) {
601 if (fabs(max_val - min_val) < 10.0f * std::numeric_limits<float>::epsilon())
602 max_val = min_val + 1;
603 ac.set_attribute_range(min_val, max_val);
608 if (get_domain_config_ptr()->show_domain)
609 draw_domain(ctx, i, !fst);
610 if (legend_components != LC_HIDDEN)
611 draw_legend(ctx, 5, i == i_begin, multi_axis_modes);
612 if (disable_depth_mask)
613 glDepthMask(GL_FALSE);
615 glDepthFunc(GL_LEQUAL);
616 draw_bar_plot(ctx, i, 8);
617 draw_stick_plot(ctx, i, 9);
618 draw_line_plot(ctx, i, 10);
619 draw_point_plot(ctx, i, 11);
620 if (disable_depth_mask)
621 glDepthMask(GL_TRUE);
623 glDepthFunc(GL_LESS);
627 for (ai = 0; ai < 2 + nr_attributes; ++ai)
628 if (multi_axis_modes[ai])
629 get_domain_config_ptr()->axis_configs[ai].restore_attribute_range();
636 glDisable(GL_LINE_SMOOTH);
640 glEnable(GL_CULL_FACE);
642 glBlendFunc(blend_src, blend_dst);
649 plot_base::create_point_config_gui(bp, p, pbc);
656 plot_base::create_stick_config_gui(bp, p, pbc);
663 plot_base::create_bar_config_gui(bp, p, pbc);
668 plot_base::create_config_gui(bp, p, i);
673 if (p.
begin_tree_node(
"Multi Modes", multi_axis_modes,
false,
"level=3")) {
675 for (
unsigned ai = 0; ai < 2 + nr_attributes; ++ai)
676 p.
add_member_control(bp, get_domain_config_ptr()->axis_configs[ai].name, multi_axis_modes[ai],
"toggle");
680 p.
add_member_control(bp,
"Delta X", sub_plot_delta[0],
"value_slider",
"min=-1;max=1;step=0.001;ticks=true");
681 p.
add_member_control(bp,
"Delta Y", sub_plot_delta[1],
"value_slider",
"min=-1;max=1;step=0.001;ticks=true");
682 p.
add_member_control(bp,
"Delta Z", sub_plot_delta[2],
"value_slider",
"min=-1;max=1;step=0.02;ticks=true");
683 plot_base::create_gui(bp, p);
base class for all classes that can be registered with support for dynamic properties (see also secti...
derive from this class to provide a gui to the current viewer
void align(const std::string &_align)
send pure alignment information
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.
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
void end_tree_node(const T &value)
template specialization that allows to specify value reference plus node_instance by using the result...
static fvec< float, N > from_vec(const vec< float > &)
conversion from vector
std::vector< std::vector< unsigned > > strips
allow to split series into connected strips that are represented by the number of contained samples
std::vector< vec2 > & ref_sub_plot_samples(unsigned i=0)
return the samples of the i-th sub plot
cgv::render::attribute_array_manager aam_domain
attribute managers for domain rectangles and domain tick labels
void delete_sub_plot(unsigned i)
delete the i-th sub plot
std::vector< unsigned > & ref_sub_plot_strips(unsigned i=0)
return the strip definition of the i-th sub plot
plot2d_config & ref_sub_plot2d_config(unsigned i=0)
return a reference to the plot1d configuration of the i-th plot
bool * multi_axis_modes
whether to manage separate axes for each sub plot
vec3 sub_plot_delta
offset in between sub plots in x, y and z direction
unsigned add_sub_plot(const std::string &name)
add sub plot and return sub plot index
plot2d(const std::string &title, unsigned nr_attributes=0)
construct 2D plot with given number of additional attributes and default parameters
std::vector< std::vector< vec2 > > samples
store 2d samples for data series
bool init(cgv::render::context &ctx)
construct shader programs
base class for plot2d and plot3d, which can have several sub plots each
const domain_config * get_domain_config_ptr() const
return const pointer to domain configuration
unsigned get_nr_sub_plots() const
return current number of sub plots
std::vector< attribute_source_array > attribute_source_arrays
attribute sources
std::vector< plot_base_config * > configs
store one configuration per sub plot
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
bool init(cgv::render::context &ctx)
build legend prog and create aab
base class for all drawables, which is independent of the used rendering API.
virtual void mul_modelview_matrix(const dmat4 &MV)
multiply given matrix from right to current modelview matrix
virtual unsigned int get_height() const =0
return the height of the window
virtual dmat4 get_modelview_matrix() const =0
return homogeneous 4x4 viewing matrix, which transforms from world to eye space
void pop_modelview_matrix()
see push_V for an explanation
void push_modelview_matrix()
push the current viewing matrix onto a matrix stack for viewing matrices.
bool build_program(const context &ctx, const std::string &file_name, bool show_error=false, const shader_define_map &defines=shader_define_map())
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
cgv::math::vec< float > vecn
declare type of single precision floating point vector with varying dimension
cgv::media::color< float, cgv::media::RGB > rgb
declare rgb color type with 32 bit components
cgv::math::fvec< float, 2 > vec2
declare type of 2d single precision floating point vectors
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
struct that manages attribute sources and corresponding gpu objects per subplot
store source of a single plot attribute (one coordinate axis or one float attribute)
std::string title
plot title
std::vector< axis_config > axis_configs
store a vector of axis configurations (2/3 for plot2/3d plus several attribute axes)
extend common plot configuration with parameters specific to 2d plot
void configure_chart(ChartType chart_type)
configure the sub plot to a specific chart type
plot2d_config(const std::string &_name)
set default values
plot independent configuration parameters of one sub plot in a 2d or 3d plot
virtual void configure_chart(ChartType chart_type)
configure the sub plot to a specific chart type
std::string name
name of sub plot
bool show_lines
whether to connect data points with lines
bool show_points
whether to show data points
mapped_rgba point_color
point color
mapped_size point_halo_width
width of point halo in pixel
mapped_size point_size
point size in pixels
mapped_rgba point_halo_color
color of point halo