Files
2025-12-05 08:54:02 +01:00

8329 lines
245 KiB
Plaintext

// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef tools_sg_plotter
#define tools_sg_plotter
#include "../lina/vec2f"
#include "render_action"
#include "plottables"
#include "style"
#include "rep"
#include "colormap"
#include "noderef"
#include "atb_vertices"
#include "cube" //for lego
#include "matrix"
#include "normal"
#include "holder"
#include "tex_rect" //for plottable_img.
#include "axis"
#include "infos_box"
#include "legend"
#include "text"
#include "torche"
#include "ellipse"
#include "../data_axis"
#include "../hatcher"
#include "../clist_contour"
#include "../tess_contour"
#include "../lina/geom3"
#include "../spline"
#include "../rtausmef"
#include <utility>
namespace tools {
namespace sg {
class plotter : public node {
TOOLS_NODE(plotter,tools::sg::plotter,node)
private:
static const std::string& s_infos_what_def() {
static const std::string s_v("name entries mean rms fit_quality fit_ndf fit_parameters fit_errors");
return s_v;
}
static float default_infos_margin() {return 0.005f;}
static float default_title_box_width() {return 0.3f;}
static float default_title_box_height() {return 0.05f;}
static float default_title_box_x_margin() {return 0.01f;}
static float default_title_box_y_margin() {return 0.005f;}
public:
sf<float> width; //PAW XSIZ
sf<float> height; //PAW YSIZ
sf<float> left_margin; //PAW XMGL
sf<float> right_margin; //PAW XMGR
sf<float> bottom_margin; //PAW YMGL
sf<float> top_margin; //PAW YMGU
sf<float> depth;
sf<float> down_margin;
sf<float> up_margin;
sf<bool> title_up;
sf<float> title_to_axis;
sf<float> title_height;
sf<bool> title_automated;
sf_enum<hjust> title_hjust;
sf_string title; //output if title_automated.
sf<bool> colormap_visible;
enum colormap_axis_labeling_type {
cells = 0,
min_max
};
sf_enum<colormap_axis_labeling_type> colormap_axis_labeling;
sf<bool> colormap_attached;
sf<bool> colormap_axis_visible;
// Wanted axes parameters.
// They are not necessary realized on the sg::axis nodes.
sf<bool> x_axis_enforced;
sf<bool> x_axis_automated;
sf<float> x_axis_min;
sf<float> x_axis_max;
sf<bool> x_axis_is_log;
sf<bool> y_axis_enforced;
sf<bool> y_axis_automated;
sf<float> y_axis_min;
sf<float> y_axis_max;
sf<bool> y_axis_is_log;
sf<bool> z_axis_enforced;
sf<bool> z_axis_automated;
sf<float> z_axis_min;
sf<float> z_axis_max;
sf<bool> z_axis_is_log;
sf<float> value_top_margin;
sf<float> value_bottom_margin;
sf<bool> value_bins_with_entries;
sf<float> infos_width; //in percent of width.
sf<float> infos_x_margin; //in percent of width. From right.
sf<float> infos_y_margin; //in percent of height. From top.
sf_string infos_what;
sf<float> title_box_width; //in percent of width.
sf<float> title_box_height; //in percent of height.
sf<float> title_box_x_margin; //in percent of width. From left.
sf<float> title_box_y_margin; //in percent of height. From top.
sf<bool> func2D_borders_visible;
// used with shape xyz
sf<float> theta; //in degrees.
sf<float> phi; //in degrees.
sf<float> tau; //in degrees.
////////////////////////////////////////////////////////////////
/// legend related :////////////////////////////////////////////
////////////////////////////////////////////////////////////////
sf<bool> legends_automated;
//sf<bool> legends_attached_to_infos;
//if legends_attached_to_infos is false :
// legends_origin is used to place the legends. It is then
// the lower left corner of the box containing all legends.
mf_vec<vec2f,float> legends_origin; //common origin of legend boxes.
enum unit_type {
unit_percent,
unit_axis
};
mf_enum<unit_type> legends_origin_unit;
mf_vec<vec2f,float> legends_size; //overall legend boxes size.
mf_string legends_string;
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
sf<bool> shape_automated;
enum shape_type {
xy = 0,
xyz
};
sf_enum<shape_type> shape;
// used with xy shape :
sf<float> xy_depth; //all is in z [0,xy_depth]
sf<unsigned int> curve_number_of_points;
sf<bool> data_light_on_automated;
// for gopaw :
sf<bool> primitives_enforced;
sf<bool> inner_frame_enforced;
// to be implemented :
sf<bool> top_axis_visible;
sf<bool> right_axis_visible;
sf<bool> superpose_bins;
// For contours :
sf<unsigned int> number_of_levels;
mf<float> levels;
public:
virtual const desc_fields& node_desc_fields() const {
TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::plotter)
static const desc_fields s_v(parent::node_desc_fields(),63, //WARNING : take care of count.
TOOLS_ARG_FIELD_DESC(width),
TOOLS_ARG_FIELD_DESC(height),
TOOLS_ARG_FIELD_DESC(left_margin),
TOOLS_ARG_FIELD_DESC(right_margin),
TOOLS_ARG_FIELD_DESC(bottom_margin),
TOOLS_ARG_FIELD_DESC(top_margin),
TOOLS_ARG_FIELD_DESC(depth),
TOOLS_ARG_FIELD_DESC(down_margin),
TOOLS_ARG_FIELD_DESC(up_margin),
TOOLS_ARG_FIELD_DESC(colormap_visible), //10
TOOLS_ARG_FIELD_DESC_ENUMS_BEG(colormap_axis_labeling,2)
TOOLS_ARG_ENUM(cells),
TOOLS_ARG_ENUM(min_max)
TOOLS_ARG_FIELD_DESC_ENUMS_END,
TOOLS_ARG_FIELD_DESC(colormap_attached),
TOOLS_ARG_FIELD_DESC(colormap_axis_visible),
TOOLS_ARG_FIELD_DESC(title_up),
TOOLS_ARG_FIELD_DESC(title_to_axis),
TOOLS_ARG_FIELD_DESC(title_height),
TOOLS_ARG_FIELD_DESC(title_automated),
TOOLS_ARG_FIELD_DESC_ENUMS_BEG(title_hjust,3)
"left",left,
"center",center,
"right",right
TOOLS_ARG_FIELD_DESC_ENUMS_END,
TOOLS_ARG_FIELD_DESC(title),
TOOLS_ARG_FIELD_DESC(x_axis_enforced), //20
TOOLS_ARG_FIELD_DESC(x_axis_automated),
TOOLS_ARG_FIELD_DESC(x_axis_min),
TOOLS_ARG_FIELD_DESC(x_axis_max),
TOOLS_ARG_FIELD_DESC(x_axis_is_log),
TOOLS_ARG_FIELD_DESC(y_axis_enforced),
TOOLS_ARG_FIELD_DESC(y_axis_automated),
TOOLS_ARG_FIELD_DESC(y_axis_min),
TOOLS_ARG_FIELD_DESC(y_axis_max),
TOOLS_ARG_FIELD_DESC(y_axis_is_log),
TOOLS_ARG_FIELD_DESC(z_axis_enforced), //30
TOOLS_ARG_FIELD_DESC(z_axis_automated),
TOOLS_ARG_FIELD_DESC(z_axis_min),
TOOLS_ARG_FIELD_DESC(z_axis_max),
TOOLS_ARG_FIELD_DESC(z_axis_is_log),
TOOLS_ARG_FIELD_DESC(value_top_margin),
TOOLS_ARG_FIELD_DESC(value_bottom_margin),
TOOLS_ARG_FIELD_DESC(value_bins_with_entries),
TOOLS_ARG_FIELD_DESC(infos_width),
TOOLS_ARG_FIELD_DESC(infos_x_margin),
TOOLS_ARG_FIELD_DESC(infos_y_margin), //40
TOOLS_ARG_FIELD_DESC(infos_what),
TOOLS_ARG_FIELD_DESC(func2D_borders_visible),
TOOLS_ARG_FIELD_DESC(theta),
TOOLS_ARG_FIELD_DESC(phi),
TOOLS_ARG_FIELD_DESC(tau),
TOOLS_ARG_FIELD_DESC(legends_automated),
TOOLS_ARG_FIELD_DESC_ENUMS_BEG(legends_origin,2)
"unit_percent",unit_percent,
"unit_axis",unit_axis
TOOLS_ARG_FIELD_DESC_ENUMS_END,
TOOLS_ARG_FIELD_DESC(legends_origin_unit),
TOOLS_ARG_FIELD_DESC(legends_size),
TOOLS_ARG_FIELD_DESC(legends_string), //50
TOOLS_ARG_FIELD_DESC(shape_automated),
TOOLS_ARG_FIELD_DESC_ENUMS_BEG(shape,2)
"xy",xy,
"xyz",xyz
TOOLS_ARG_FIELD_DESC_ENUMS_END,
TOOLS_ARG_FIELD_DESC(xy_depth),
TOOLS_ARG_FIELD_DESC(curve_number_of_points),
TOOLS_ARG_FIELD_DESC(number_of_levels),
TOOLS_ARG_FIELD_DESC(levels),
TOOLS_ARG_FIELD_DESC(data_light_on_automated),
TOOLS_ARG_FIELD_DESC(primitives_enforced),
TOOLS_ARG_FIELD_DESC(inner_frame_enforced),
TOOLS_ARG_FIELD_DESC(title_box_width), //60
TOOLS_ARG_FIELD_DESC(title_box_height),
TOOLS_ARG_FIELD_DESC(title_box_x_margin),
TOOLS_ARG_FIELD_DESC(title_box_y_margin) //63
);
return s_v;
}
virtual bool touched() {
if(parent::touched()) return true;
if(background_style().touched()) return true;
if(title_style().touched()) return true;
if(infos_style().touched()) return true;
if(title_box_style().touched()) return true;
if(inner_frame_style().touched()) return true;
if(grid_style().touched()) return true;
if(wall_style().touched()) return true;
{tools_vforit(style,m_bins_style,it) {if((*it).touched()) return true;}}
{tools_vforit(style,m_errors_style,it) {if((*it).touched()) return true;}}
{tools_vforit(style,m_func_style,it) {if((*it).touched()) return true;}}
{tools_vforit(style,m_points_style,it) {if((*it).touched()) return true;}}
{tools_vforit(style,m_left_hatch_style,it) {if((*it).touched()) return true;}}
{tools_vforit(style,m_right_hatch_style,it) {if((*it).touched()) return true;}}
{tools_vforit(style,m_legend_style,it) {if((*it).touched()) return true;}}
return false;
}
virtual void reset_touched() {
parent::reset_touched();
background_style().reset_touched();
title_style().reset_touched();
infos_style().reset_touched();
title_box_style().reset_touched();
inner_frame_style().reset_touched();
grid_style().reset_touched();
wall_style().reset_touched();
{tools_vforit(style,m_bins_style,it) (*it).reset_touched();}
{tools_vforit(style,m_errors_style,it) (*it).reset_touched();}
{tools_vforit(style,m_func_style,it) (*it).reset_touched();}
{tools_vforit(style,m_points_style,it) (*it).reset_touched();}
{tools_vforit(style,m_left_hatch_style,it) (*it).reset_touched();}
{tools_vforit(style,m_right_hatch_style,it) (*it).reset_touched();}
{tools_vforit(style,m_legend_style,it) (*it).reset_touched();}
}
private:
void add_fields(){
// if adding a field, look for reset_style(), set_from_style() and set_from_string()
add_field(&width);
add_field(&height);
add_field(&left_margin);
add_field(&right_margin);
add_field(&bottom_margin);
add_field(&top_margin);
add_field(&depth);
add_field(&down_margin);
add_field(&up_margin);
add_field(&title_up);
add_field(&title_to_axis);
add_field(&title_height);
add_field(&title_automated);
add_field(&title_hjust);
add_field(&title);
add_field(&x_axis_enforced);
add_field(&x_axis_automated);
add_field(&x_axis_min);
add_field(&x_axis_max);
add_field(&x_axis_is_log);
add_field(&y_axis_enforced);
add_field(&y_axis_automated);
add_field(&y_axis_min);
add_field(&y_axis_max);
add_field(&y_axis_is_log);
add_field(&z_axis_enforced);
add_field(&z_axis_automated);
add_field(&z_axis_min);
add_field(&z_axis_max);
add_field(&z_axis_is_log);
add_field(&value_top_margin);
add_field(&value_bottom_margin);
add_field(&value_bins_with_entries);
add_field(&infos_width);
add_field(&infos_x_margin);
add_field(&infos_y_margin);
add_field(&infos_what);
add_field(&title_box_width);
add_field(&title_box_height);
add_field(&title_box_x_margin);
add_field(&title_box_y_margin);
add_field(&func2D_borders_visible);
add_field(&theta);
add_field(&phi);
add_field(&tau);
add_field(&legends_automated);
//add_field(&legends_attached_to_infos);
add_field(&legends_origin);
add_field(&legends_origin_unit);
add_field(&legends_size);
add_field(&legends_string);
add_field(&shape_automated);
add_field(&shape);
add_field(&xy_depth);
add_field(&curve_number_of_points);
add_field(&number_of_levels);
add_field(&levels);
add_field(&data_light_on_automated);
add_field(&primitives_enforced);
add_field(&inner_frame_enforced);
}
public: //style
void copy_style(const plotter& a_from) { //used in sg::plots.
////////////////////////////////////////////
////////////////////////////////////////////
////////////////////////////////////////////
shape_automated = a_from.shape_automated;
shape = a_from.shape;
xy_depth = a_from.xy_depth;
curve_number_of_points = a_from.curve_number_of_points;
value_top_margin = a_from.value_top_margin;
value_bottom_margin = a_from.value_bottom_margin;
value_bins_with_entries = a_from.value_bins_with_entries;
infos_what = a_from.infos_what;
infos_width = a_from.infos_width;
//infos height is automatic.
infos_x_margin = a_from.infos_x_margin;
infos_y_margin = a_from.infos_y_margin;
title_box_width = a_from.title_box_width;
title_box_height = a_from.title_box_height;
title_box_x_margin = a_from.title_box_x_margin;
title_box_y_margin = a_from.title_box_y_margin;
legends_automated = a_from.legends_automated;
title_automated = a_from.title_automated;
title = a_from.title;
title_up = a_from.title_up;
title_hjust = a_from.title_hjust;
colormap_visible = a_from.colormap_visible;
colormap_axis_labeling = a_from.colormap_axis_labeling;
colormap_attached = a_from.colormap_attached;
colormap_axis_visible = a_from.colormap_axis_visible;
number_of_levels = a_from.number_of_levels;
levels = a_from.levels;
data_light_on_automated = a_from.data_light_on_automated;
primitives_enforced = a_from.primitives_enforced;
inner_frame_enforced = a_from.inner_frame_enforced;
////////////////////////////////////////////
////////////////////////////////////////////
////////////////////////////////////////////
x_axis_enforced = a_from.x_axis_enforced;
x_axis_automated = a_from.x_axis_automated;
x_axis_min = a_from.x_axis_min;
x_axis_max = a_from.x_axis_max;
x_axis_is_log = a_from.x_axis_is_log;
y_axis_enforced = a_from.y_axis_enforced;
y_axis_automated = a_from.y_axis_automated;
y_axis_min = a_from.y_axis_min;
y_axis_max = a_from.y_axis_max;
y_axis_is_log = a_from.y_axis_is_log;
z_axis_enforced = a_from.z_axis_enforced;
z_axis_automated = a_from.z_axis_automated;
z_axis_min = a_from.z_axis_min;
z_axis_max = a_from.z_axis_max;
z_axis_is_log = a_from.z_axis_is_log;
////////////////////////////////////////////
////////////////////////////////////////////
////////////////////////////////////////////
m_background_style = a_from.m_background_style;
m_title_style = a_from.m_title_style;
m_infos_style = a_from.m_infos_style;
m_title_box_style = a_from.m_title_box_style;
m_inner_frame_style = a_from.m_inner_frame_style;
m_grid_style = a_from.m_grid_style;
m_wall_style = a_from.m_wall_style;
m_bins_style = a_from.m_bins_style;
m_errors_style = a_from.m_errors_style;
m_func_style = a_from.m_func_style;
m_points_style = a_from.m_points_style;
m_left_hatch_style = a_from.m_left_hatch_style;
m_right_hatch_style = a_from.m_right_hatch_style;
m_legend_style = a_from.m_legend_style;
}
void reset_style(bool a_geom = false) {
//reset fields that are considered as part of the style.
//::printf("debug : tools::sg::plotter::reset_style :\n");
shape_automated = true;
shape = xy;
xy_depth = 0.01f;
curve_number_of_points = 100;
////////////////////////////////////////////
value_top_margin = 0.1f; //percent. // CERN-PAW seems to have 0.1F and CERN-ROOT 0.05F.
value_bottom_margin = 0.0f; //percent.
value_bins_with_entries = true; //gopaw uses false.
infos_what = s_infos_what_def();
infos_width = 0.3f;
//infos height is automatic.
infos_x_margin = default_infos_margin(); //percent of width
infos_y_margin = default_infos_margin(); //percent of height
title_box_width = default_title_box_width();
title_box_height = default_title_box_height();
title_box_x_margin = default_title_box_x_margin(); //percent of width
title_box_y_margin = default_title_box_y_margin(); //percent of height
legends_automated = true;
////////////////////////////////////////////
if(a_geom) {
float xfac = 1.0F/20.0F; //0.05
float yfac = 1.0F/20.0F; //0.05
// Take PAW defaults :
float XSIZ = 20 * xfac; //1 //page width
float YSIZ = 20 * yfac; //1 //page height
float XMGL = 2 * xfac; //0.1 //left x margin (to data frame).
float XMGR = 2 * xfac; //0.1 //right y margin (to data frame).
float YMGL = 2 * yfac; //0.1 //low y margin (to data frame).
float YMGU = 2 * yfac; //0.1 //up y margin (to data frame).
// Axes :
float VSIZ = 0.28F * yfac; //0.014 //tick label character size.
float XVAL = 0.4F * xfac; //0.02 //x distance of y tick label to data frame.
float YVAL = 0.4F * yfac; //0.02 //y distance of x tick label to data frame.
float XTIC = 0.3F * yfac; //0.015 //y length of X axis ticks.
float YTIC = 0.3F * xfac; //0.015 //x length of Y axis ticks.
float XLAB = 1.4F * xfac; //0.07 //x distance of y title to data frame.
float YLAB = 0.8F * yfac; //0.04 //y distance of x title to data frame.
float ASIZ = 0.28F * yfac; //0.014 // axis title (label) character size.
float YHTI = 1.2F * yfac; //0.06 //y distance of title to x axis.
float TSIZ = 0.28F * yfac; //0.014 //title character size
float zfac = 1.0F/20.0F; //0.05
float ZSIZ = 20 * zfac; //1 //page depth
float ZMGD = 2 * zfac; //0.1 //low y margin (to data frame).
float ZMGU = 2 * zfac; //0.1 //up y margin (to data frame).
width = XSIZ;
height = YSIZ;
depth = ZSIZ;
left_margin = XMGL;
right_margin = XMGR;
bottom_margin = YMGL;
top_margin = YMGU;
down_margin = ZMGD;
up_margin = ZMGU;
title_to_axis = YHTI;
title_height = TSIZ;
if(shape.value()==xy) {
m_x_axis.tick_length.value(XTIC);
m_x_axis.label_to_axis.value(YVAL);
m_x_axis.label_height.value(VSIZ);
m_x_axis.title_to_axis.value(YLAB);
m_x_axis.title_height.value(ASIZ);
m_y_axis.tick_length.value(YTIC);
m_y_axis.label_to_axis.value(XVAL);
m_y_axis.label_height.value(VSIZ);
m_y_axis.title_to_axis.value(XLAB);
m_y_axis.title_height.value(ASIZ);
m_cmap_axis.tick_length.value(YTIC);
m_cmap_axis.label_to_axis.value(XVAL);
m_cmap_axis.label_height.value(VSIZ);
m_cmap_axis.title_to_axis.value(XLAB);
m_cmap_axis.title_height.value(ASIZ);
} else { //xyz
m_x_axis.tick_length.value(XTIC);
m_x_axis.label_to_axis.value(YVAL);
m_x_axis.label_height.value(VSIZ);
m_x_axis.title_to_axis.value(YLAB);
m_x_axis.title_height.value(ASIZ);
m_y_axis.tick_length.value(XTIC);
m_y_axis.label_to_axis.value(YVAL);
m_y_axis.label_height.value(VSIZ);
m_y_axis.title_to_axis.value(YLAB);
m_y_axis.title_height.value(ASIZ);
m_z_axis.tick_length.value(YTIC);
m_z_axis.label_to_axis.value(XVAL);
m_z_axis.label_height.value(VSIZ);
m_z_axis.title_to_axis.value(XLAB);
m_z_axis.title_height.value(ASIZ);
m_cmap_axis.tick_length.value(XTIC);
m_cmap_axis.label_to_axis.value(YVAL);
m_cmap_axis.label_height.value(VSIZ);
m_cmap_axis.title_to_axis.value(YLAB);
m_cmap_axis.title_height.value(ASIZ);
}
}
title_automated = true;
title.value().clear();
title_up = true;
title_hjust = center;
////////////////////////////////////////////
colormap_visible = true;
colormap_axis_labeling = cells;
colormap_attached = true;
colormap_axis_visible = true;
////////////////////////////////////////////
x_axis_enforced = false;
x_axis_automated = true;
x_axis_min = 0;
x_axis_max = 1;
x_axis_is_log = false;
y_axis_enforced = false;
y_axis_automated = true;
y_axis_min = 0;
y_axis_max = 1;
y_axis_is_log = false;
z_axis_enforced = false;
z_axis_automated = true;
z_axis_min = 0;
z_axis_max = 1;
z_axis_is_log = false;
m_x_axis.reset_style();
m_y_axis.reset_style();
m_z_axis.reset_style();
////////////////////////////////////////////
////////////////////////////////////////////
////////////////////////////////////////////
number_of_levels = 10;
levels.clear();
data_light_on_automated = true;
primitives_enforced = false;
inner_frame_enforced = false;
////////////////////////////////////////////
// setup styles :
////////////////////////////////////////////
m_title_style = text_style();
m_infos_style = text_style();
m_title_box_style = text_style();
m_background_style = style();
m_wall_style = style();
m_inner_frame_style = style();
m_grid_style = style();
m_title_style.color = colorf_black();
m_title_style.font = font_hershey();
m_title_style.font_modeling = font_filled;
m_title_style.encoding = encoding_PAW();
m_background_style.back_color = colorf_white();
m_background_style.line_width = 0; //no border
m_background_style.color = colorf_black(); //border
m_inner_frame_style.color = colorf_black();
m_inner_frame_style.line_pattern = line_solid;
m_grid_style.color = colorf_black();
m_grid_style.line_pattern = line_dashed;
m_infos_style.font = font_hershey();
m_infos_style.font_modeling = font_filled;
m_infos_style.encoding = encoding_PAW();
m_title_box_style.visible = false;
m_title_box_style.font = font_hershey();
m_title_box_style.font_modeling = font_filled;
m_title_box_style.encoding = encoding_PAW();
{tools_vforit(style,m_bins_style,it) {
(*it) = style();
(*it).modeling = modeling_top_lines();
(*it).marker_size = 5; //for bins1D of profile.
}}
{tools_vforit(style,m_errors_style,it) {(*it) = style();(*it).visible = false;}}
{tools_vforit(style,m_func_style,it) (*it) = style();}
{tools_vforit(style,m_points_style,it) {
(*it) = style();
(*it).modeling = modeling_markers(); //for gopaw.
}}
{tools_vforit(style,m_left_hatch_style,it) {(*it) = style();(*it).visible = false;}}
{tools_vforit(style,m_right_hatch_style,it) {(*it) = style();(*it).visible = false;}}
{tools_vforit(style,m_legend_style,it) {(*it) = style();(*it).visible = false;}}
}
void gopaw_reset_style() {
{tools_vforit(style,m_bins_style,it) {
(*it) = style();
(*it).modeling = modeling_top_lines();
(*it).marker_size = 5; //for bins1D of profile.
}}
{tools_vforit(style,m_errors_style,it) {(*it) = style();(*it).visible = false;}}
{tools_vforit(style,m_func_style,it) (*it) = style();}
{tools_vforit(style,m_points_style,it) {
(*it) = style();
(*it).modeling = modeling_markers(); //for gopaw.
}}
{tools_vforit(style,m_left_hatch_style,it) {(*it) = style();(*it).visible = false;}}
{tools_vforit(style,m_right_hatch_style,it) {(*it) = style();(*it).visible = false;}}
{tools_vforit(style,m_legend_style,it) {(*it) = style();(*it).visible = false;}}
}
typedef std::pair<std::string,std::string> style_item_t;
typedef std::vector<style_item_t> style_t;
bool set_from_style(std::ostream& a_out,const style_t& a_style) {
tools_vforcit(style_item_t,a_style,it) {
const std::string& key = (*it).first;
const std::string& sv = (*it).second;
if(key=="tag") {
} else if(key=="width") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
width = v;
} else if(key=="height") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
height = v;
} else if(key=="depth") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
depth = v;
} else if(key=="left_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
left_margin = v;
} else if(key=="right_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
right_margin = v;
} else if(key=="bottom_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
bottom_margin = v;
} else if(key=="top_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
top_margin = v;
} else if(key=="down_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
down_margin = v;
} else if(key=="up_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
up_margin = v;
} else if(key=="title") {
title = sv;
} else if(key=="title_up") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
title_up = v;
} else if(key=="title_to_axis") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
title_to_axis = v;
} else if(key=="title_height") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
title_height = v;
} else if(key=="title_automated") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
title_automated = v;
} else if(key=="title_hjust") {
hjust v;
if(!shjust(sv,v))
{style_failed(a_out,key,sv);return false;}
title_hjust = v;
} else if(key=="x_axis_enforced") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
x_axis_enforced = v;
} else if(key=="x_axis_automated") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
x_axis_automated = v;
} else if(key=="x_axis_min") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
x_axis_min = v;
} else if(key=="x_axis_max") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
x_axis_max = v;
} else if(key=="x_axis_is_log") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
x_axis_is_log = v;
} else if(key=="y_axis_enforced") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
y_axis_enforced = v;
} else if(key=="y_axis_automated") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
y_axis_automated = v;
} else if(key=="y_axis_min") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
y_axis_min = v;
} else if(key=="y_axis_max") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
y_axis_max = v;
} else if(key=="y_axis_is_log") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
y_axis_is_log = v;
} else if(key=="z_axis_enforced") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
z_axis_enforced = v;
} else if(key=="z_axis_automated") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
z_axis_automated = v;
} else if(key=="z_axis_min") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
z_axis_min = v;
} else if(key=="z_axis_max") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
z_axis_max = v;
} else if(key=="z_axis_is_log") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
z_axis_is_log = v;
} else if(key=="value_top_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
value_top_margin = v;
} else if(key=="value_bottom_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
value_bottom_margin = v;
} else if(key=="value_bins_with_entries") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
value_bins_with_entries = v;
} else if(key=="infos_width") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
infos_width = v;
} else if(key=="infos_x_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
infos_x_margin = v;
} else if(key=="infos_y_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
infos_y_margin = v;
} else if(key=="title_box_width") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
title_box_width = v;
} else if(key=="title_box_height") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
title_box_height = v;
} else if(key=="title_box_x_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
title_box_x_margin = v;
} else if(key=="title_box_y_margin") {
float v;
if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
title_box_y_margin = v;
} else if(key=="infos_what") {
infos_what = sv;
} else if(key=="legends_automated") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
legends_automated = v;
} else if(key=="legends_origin") {
vec2f v;
if(!sto(sv,v)) {style_failed(a_out,key,sv);return false;}
legends_origin.setValue(v);
} else if(key=="legends_size") {
vec2f v;
if(!sto(sv,v)) {style_failed(a_out,key,sv);return false;}
legends_size.setValue(v);
} else if(key=="legends_origin_unit") {
unit_type v;
if(!sto(sv,v)) {style_failed(a_out,key,sv);return false;}
legends_origin_unit.setValue(v);
} else if(key=="shape_automated") {
bool v;
if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
shape_automated = v;
} else if(key=="shape") {
if(sv=="xy") {
shape = xy;
} else if(sv=="xyz") {
shape = xyz;
} else {
style_failed(a_out,key,sv);return false;
}
} else {
a_out << "tools::sg::plotter::set_from_style : unknown key " << key << "." << std::endl;
}
}
return true;
}
protected:
bool s2axis(const std::string& a_s,sg::axis*& a_axis) {
if(a_s=="x_axis") {a_axis = &(x_axis());return true;}
else if(a_s=="y_axis") {a_axis = &(y_axis());return true;}
else if(a_s=="z_axis") {a_axis = &(z_axis());return true;}
else if(a_s=="colormap_axis") {a_axis = &(colormap_axis());return true;}
else {
a_axis = 0;
return false;
}
}
public:
bool set_from_string(std::ostream& a_out,cmaps_t& a_cmaps,const std::string& a_field,const std::string& a_value) {
// see also plotter_style file.
std::string::size_type pos = a_field.find('.');
bool status = true;
if(pos==std::string::npos) {
style_t _style;
_style.push_back(style_item_t(a_field,a_value));
if(!set_from_style(a_out,_style)) status = false;
} else {
std::vector<std::string> _words;
words(a_field,".",false,_words);
if(_words.size()==2) {
const std::string& word0 = _words[0];
const std::string& word1 = _words[1];
std::string _s = word1+" "+std::string(a_value);
sg::axis* _axis = 0;
if(word0=="background_style") {if(!background_style().from_string(a_out,a_cmaps,_s)) status = false;}
else if(word0=="title_style") {if(!title_style().from_string(a_out,a_cmaps,_s)) status = false;}
else if(word0=="infos_style") {if(!infos_style().from_string(a_out,a_cmaps,_s)) status = false;}
else if(word0=="title_box_style") {if(!title_box_style().from_string(a_out,a_cmaps,_s)) status = false;}
else if(word0=="inner_frame_style") {if(!inner_frame_style().from_string(a_out,a_cmaps,_s)) status = false;}
else if(word0=="grid_style") {if(!grid_style().from_string(a_out,a_cmaps,_s)) status = false;}
else if(word0=="wall_style") {if(!wall_style().from_string(a_out,a_cmaps,_s)) status = false;}
else if(!s2axis(word0,_axis)) {
a_out << "tools::sg::plotter::set_from_string : unexpected axis field " << word0 << "." << std::endl;
status = false;
} else {
style_t _style;
_style.push_back(style_item_t(word1,a_value));
if(!_axis->set_from_style(a_out,_style)) status = false;
}
} else if(_words.size()==3) {
const std::string& word0 = _words[0];
const std::string& word1 = _words[1];
const std::string& word2 = _words[2];
sg::axis* _axis = 0;
std::string _s = word2+" "+std::string(a_value);
unsigned int index;
bool to_status = to<unsigned int>(word1,index);
if(word0=="bins_style") {
if(!to_status) {
a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
status = false;
} else {
if(!bins_style(index).from_string(a_out,a_cmaps,_s)) status = false;
}
} else if(word0=="errors_style") {
if(!to_status) {
a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
status = false;
} else {
if(!errors_style(index).from_string(a_out,a_cmaps,_s)) status = false;
}
} else if(word0=="func_style") {
if(!to_status) {
a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
status = false;
} else {
if(!func_style(index).from_string(a_out,a_cmaps,_s)) status = false;
}
} else if(word0=="points_style") {
if(!to_status) {
a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
status = false;
} else {
if(!points_style(index).from_string(a_out,a_cmaps,_s)) status = false;
}
} else if(word0=="left_hatch_style") {
if(!to_status) {
a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
status = false;
} else {
if(!left_hatch_style(index).from_string(a_out,a_cmaps,_s)) status = false;
}
} else if(word0=="right_hatch_style") {
if(!to_status) {
a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
status = false;
} else {
if(!right_hatch_style(index).from_string(a_out,a_cmaps,_s)) status = false;
}
} else if(word0=="legend_style") {
if(!to_status) {
a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
status = false;
} else {
if(!legend_style(index).from_string(a_out,a_cmaps,_s)) status = false;
}
} else if(!s2axis(word0,_axis)) {
a_out << "tools::sg::plotter::set_from_string : unexpected axis field " << word0 << "." << std::endl;
status = false;
} else {
if(word1=="line_style") {if(!_axis->line_style().from_string(a_out,a_cmaps,_s)) status = false;}
else if(word1=="ticks_style") {if(!_axis->ticks_style().from_string(a_out,a_cmaps,_s)) status = false;}
else if(word1=="labels_style") {if(!_axis->labels_style().from_string(a_out,a_cmaps,_s)) status = false;}
else if(word1=="mag_style") {if(!_axis->mag_style().from_string(a_out,a_cmaps,_s)) status = false;}
else if(word1=="title_style") {if(!_axis->title_style().from_string(a_out,a_cmaps,_s)) status = false;}
else {
a_out << "tools::sg::plotter::set_from_string : unexpected style field " << word1 << "." << std::endl;
status = false;
}
}
} else {
a_out << "tools::sg::plotter::set_from_string : unexpected number of fields " << _words.size() << "." << std::endl;
status = false;
}
}
return status;
}
void set_encoding(const std::string& a_value) {
title_style().encoding = a_value;
infos_style().encoding = a_value;
title_box_style().encoding = a_value;
m_x_axis.set_encoding(a_value);
m_y_axis.set_encoding(a_value);
m_z_axis.set_encoding(a_value);
m_cmap_axis.set_encoding(a_value);
}
void set_encoding_none() {set_encoding(encoding_none());}
void print_available_customization(std::ostream& a_out) const {
a_out << "plotter fields :" << std::endl;
{const std::vector<field_desc>& fds = node_desc_fields();
tools_vforcit(field_desc,fds,itd) {
a_out << " " << (*itd).name() << ", class " << (*itd).cls() << std::endl;
}}
a_out << std::endl;
a_out << "plotter data available styles :" << std::endl;
a_out << " bins_style.<uint>, class style" << std::endl;
a_out << " errors_style.<uint>, class style" << std::endl;
a_out << " func_style.<uint>, class style" << std::endl;
a_out << " points_style.<uint>, class style" << std::endl;
a_out << " left_hatch_style.<uint>, class style" << std::endl;
a_out << " right_hatch_style.<uint>, class style" << std::endl;
a_out << " legend_style.<uint>, class style" << std::endl;
a_out << std::endl;
a_out << "plotter available styles :" << std::endl;
a_out << " title_style, class text_style" << std::endl;
a_out << " infos_style, class text_style" << std::endl;
a_out << " title_box_style, class text_style" << std::endl;
a_out << " background_style, class style" << std::endl;
a_out << " inner_frame_style, class style" << std::endl;
a_out << " grid_style, class style" << std::endl;
a_out << " wall_style, class style" << std::endl;
a_out << std::endl;
a_out << "plotter available axes :" << std::endl;
a_out << " x_axis" << std::endl;
a_out << " y_axis" << std::endl;
a_out << " z_axis" << std::endl;
a_out << " colormap_axis" << std::endl;
a_out << std::endl;
a_out << "plotter axis available styles :" << std::endl;
a_out << " title_style, class text_style" << std::endl;
a_out << " labels_style, class text_style" << std::endl;
a_out << " mag_style, class text_style" << std::endl;
a_out << " line_style, class line_style" << std::endl;
a_out << " ticks_style, class line_style" << std::endl;
a_out << std::endl;
a_out << "plotter style class fields :" << std::endl;
{style _style;
const std::vector<field_desc>& fds = _style.node_desc_fields();
tools_vforcit(field_desc,fds,itd) {
a_out << " " << (*itd).name() << ", class " << (*itd).cls() << std::endl;
}}
a_out << std::endl;
a_out << "plotter text_style class fields :" << std::endl;
{text_style _style;
const std::vector<field_desc>& fds = _style.node_desc_fields();
tools_vforcit(field_desc,fds,itd) {
a_out << " " << (*itd).name() << ", class " << (*itd).cls() << std::endl;
}}
a_out << std::endl;
a_out << "plotter line_style class fields :" << std::endl;
{line_style _style;
const std::vector<field_desc>& fds = _style.node_desc_fields();
tools_vforcit(field_desc,fds,itd) {
a_out << " " << (*itd).name() << ", class " << (*itd).cls() << std::endl;
}}
a_out << std::endl;
}
protected:
void style_failed(std::ostream& a_out,const std::string& a_key,const std::string& a_value) {
a_out << "tools::sg::plotter::set_from_style :"
<< " failed for key " << sout(a_key)
<< " and value " << sout(a_value) << "."
<< std::endl;
}
public:
virtual void render(render_action& a_action) {
if(touched()) {
update_sg(a_action.out());
reset_touched();
}
m_group.render(a_action);
}
virtual void pick(pick_action& a_action) {
if(touched()) {
update_sg(a_action.out());
reset_touched();
}
nodekit_pick(a_action,m_group,this);
}
virtual void search(search_action& a_action) {
if(touched()) {
update_sg(a_action.out());
reset_touched();
}
node::search(a_action);
if(a_action.done()) return;
m_group.search(a_action);
}
virtual void bbox(bbox_action& a_action) {
if(touched()) {
update_sg(a_action.out());
reset_touched();
}
m_group.bbox(a_action);
}
virtual bool write(write_action& a_action) {
if(touched()) {
update_sg(a_action.out());
reset_touched();
}
return m_group.write(a_action);
}
public:
plotter(const base_freetype& a_ttf)
:parent()
,width(0)
,height(0)
,left_margin(0)
,right_margin(0)
,bottom_margin(0)
,top_margin(0)
,depth(0)
,down_margin(0)
,up_margin(0)
,title_up(true)
,title_to_axis(0) //set below.
,title_height(0) //set below.
,title_automated(true)
,title_hjust(center)
,title("")
,colormap_visible(true)
,colormap_axis_labeling(cells)
,colormap_attached(true)
,colormap_axis_visible(true)
,x_axis_enforced(false)
,x_axis_automated(true)
,x_axis_min(0)
,x_axis_max(1)
,x_axis_is_log(false)
,y_axis_enforced(false)
,y_axis_automated(true)
,y_axis_min(0)
,y_axis_max(1)
,y_axis_is_log(false)
,z_axis_enforced(false)
,z_axis_automated(true)
,z_axis_min(0)
,z_axis_max(1)
,z_axis_is_log(false)
,value_top_margin(0.1f) //percent. // CERN-PAW seems to have 0.1F and CERN-ROOT 0.05F.
,value_bottom_margin(0.0f) //percent.
,value_bins_with_entries(true)
,infos_width(0.3f) //percent of width
,infos_x_margin(default_infos_margin()) //percent of width
,infos_y_margin(default_infos_margin()) //percent of height
,infos_what(s_infos_what_def())
,title_box_width(default_title_box_width()) //percent of width
,title_box_height(default_title_box_height()) //percent of height
,title_box_x_margin(default_title_box_x_margin()) //percent of width
,title_box_y_margin(default_title_box_y_margin()) //percent of height
,func2D_borders_visible(true)
,theta(30)
,phi(30)
,tau(-90)
,legends_automated(true)
,shape_automated(true)
,shape(xy)
,xy_depth(0.01f)
,curve_number_of_points(100)
,data_light_on_automated(true)
,primitives_enforced(false)
,inner_frame_enforced(false)
,number_of_levels(10)
,levels()
,m_ttf(a_ttf)
,m_cmap_axis(a_ttf)
,m_x_axis(a_ttf)
,m_y_axis(a_ttf)
,m_z_axis(a_ttf)
,m_shape(xy)
{
m_cmaps[style_default_colormap::s_default()] = style_default_colormap(); //costly
add_fields();
reset_style(true);
init_sg(); // skeleton of scene graph.
}
virtual ~plotter(){
clear_plottables();
clear_primitives();
clear_cmaps();
}
public:
plotter(const plotter& a_from)
:parent(a_from)
,width(a_from.width)
,height(a_from.height)
,left_margin(a_from.left_margin)
,right_margin(a_from.right_margin)
,bottom_margin(a_from.bottom_margin)
,top_margin(a_from.top_margin)
,depth(a_from.depth)
,down_margin(a_from.down_margin)
,up_margin(a_from.up_margin)
,title_up(a_from.title_up)
,title_to_axis(a_from.title_to_axis)
,title_height(a_from.title_height)
,title_automated(a_from.title_automated)
,title_hjust(a_from.title_hjust)
,title(a_from.title)
,colormap_visible(a_from.colormap_visible)
,colormap_axis_labeling(a_from.colormap_axis_labeling)
,colormap_attached(a_from.colormap_attached)
,colormap_axis_visible(a_from.colormap_axis_visible)
,x_axis_enforced(a_from.x_axis_enforced)
,x_axis_automated(a_from.x_axis_automated)
,x_axis_min(a_from.x_axis_min)
,x_axis_max(a_from.x_axis_max)
,x_axis_is_log(a_from.x_axis_is_log)
,y_axis_enforced(a_from.y_axis_enforced)
,y_axis_automated(a_from.y_axis_automated)
,y_axis_min(a_from.y_axis_min)
,y_axis_max(a_from.y_axis_max)
,y_axis_is_log(a_from.y_axis_is_log)
,z_axis_enforced(a_from.z_axis_enforced)
,z_axis_automated(a_from.z_axis_automated)
,z_axis_min(a_from.z_axis_min)
,z_axis_max(a_from.z_axis_max)
,z_axis_is_log(a_from.z_axis_is_log)
,value_top_margin(a_from.value_top_margin)
,value_bottom_margin(a_from.value_bottom_margin)
,value_bins_with_entries(a_from.value_bins_with_entries)
,infos_width(a_from.infos_width)
,infos_x_margin(a_from.infos_x_margin)
,infos_y_margin(a_from.infos_y_margin)
,infos_what(a_from.infos_what)
,title_box_width(a_from.title_box_width)
,title_box_height(a_from.title_box_height)
,title_box_x_margin(a_from.title_box_x_margin)
,title_box_y_margin(a_from.title_box_y_margin)
,func2D_borders_visible(a_from.func2D_borders_visible)
,theta(a_from.theta)
,phi(a_from.phi)
,tau(a_from.tau)
,legends_automated(a_from.legends_automated)
,legends_origin(a_from.legends_origin)
,legends_origin_unit(a_from.legends_origin_unit)
,legends_size(a_from.legends_size)
,legends_string(a_from.legends_string)
,shape_automated(a_from.shape_automated)
,shape(a_from.shape)
,xy_depth(a_from.xy_depth)
,curve_number_of_points(a_from.curve_number_of_points)
,data_light_on_automated(a_from.data_light_on_automated)
,primitives_enforced(a_from.primitives_enforced)
,inner_frame_enforced(a_from.inner_frame_enforced)
,number_of_levels(a_from.number_of_levels)
,levels(a_from.levels)
,m_ttf(a_from.m_ttf)
,m_background_sep()
,m_cmap_axis(m_ttf)
,m_x_axis(m_ttf)
,m_y_axis(m_ttf)
,m_z_axis(m_ttf)
,m_etc_sep(a_from.m_etc_sep)
,m_shape(a_from.m_shape)
,m_bins_style(a_from.m_bins_style)
,m_errors_style(a_from.m_errors_style)
,m_func_style(a_from.m_func_style)
,m_points_style(a_from.m_points_style)
,m_left_hatch_style(a_from.m_left_hatch_style)
,m_right_hatch_style(a_from.m_right_hatch_style)
,m_legend_style(a_from.m_legend_style)
,m_title_style(a_from.m_title_style)
,m_infos_style(a_from.m_infos_style)
,m_title_box_style(a_from.m_title_box_style)
,m_background_style(a_from.m_background_style)
,m_wall_style(a_from.m_wall_style)
,m_inner_frame_style(a_from.m_inner_frame_style)
,m_grid_style(a_from.m_grid_style)
,m_cmaps(a_from.m_cmaps)
{
add_fields();
// to copy axes styles :
m_x_axis = a_from.m_x_axis;
m_y_axis = a_from.m_y_axis;
m_z_axis = a_from.m_z_axis;
m_cmap_axis = a_from.m_cmap_axis;
init_sg(); // skeleton of scene graph.
{tools_vforcit(plottable*,a_from.m_plottables,it) {m_plottables.push_back((*it)->copy());}}
{tools_vforcit(plotprim*,a_from.m_primitives,it) {m_primitives.push_back((*it)->copy());}}
}
plotter& operator=(const plotter& a_from){
parent::operator=(a_from);
if(&a_from==this) return *this;
width = a_from.width;
height = a_from.height;
left_margin = a_from.left_margin;
right_margin = a_from.right_margin;
bottom_margin = a_from.bottom_margin;
top_margin = a_from.top_margin;
depth = a_from.depth;
down_margin = a_from.down_margin;
up_margin = a_from.up_margin;
title_up = a_from.title_up;
title_to_axis = a_from.title_to_axis;
title_height = a_from.title_height;
title_automated = a_from.title_automated;
title_hjust = a_from.title_hjust;
title = a_from.title;
colormap_visible = a_from.colormap_visible;
colormap_axis_labeling = a_from.colormap_axis_labeling;
colormap_attached = a_from.colormap_attached;
colormap_axis_visible = a_from.colormap_axis_visible;
x_axis_enforced = a_from.x_axis_enforced;
x_axis_automated = a_from.x_axis_automated;
x_axis_min = a_from.x_axis_min;
x_axis_max = a_from.x_axis_max;
x_axis_is_log = a_from.x_axis_is_log;
y_axis_enforced = a_from.y_axis_enforced;
y_axis_automated = a_from.y_axis_automated;
y_axis_min = a_from.y_axis_min;
y_axis_max = a_from.y_axis_max;
y_axis_is_log = a_from.y_axis_is_log;
z_axis_enforced = a_from.z_axis_enforced;
z_axis_automated = a_from.z_axis_automated;
z_axis_min = a_from.z_axis_min;
z_axis_max = a_from.z_axis_max;
z_axis_is_log = a_from.z_axis_is_log;
value_top_margin = a_from.value_top_margin;
value_bottom_margin = a_from.value_bottom_margin;
value_bins_with_entries = a_from.value_bins_with_entries;
infos_width = a_from.infos_width;
infos_x_margin = a_from.infos_x_margin;
infos_y_margin = a_from.infos_y_margin;
infos_what = a_from.infos_what;
title_box_width = a_from.title_box_width;
title_box_height = a_from.title_box_height;
title_box_x_margin = a_from.title_box_x_margin;
title_box_y_margin = a_from.title_box_y_margin;
func2D_borders_visible = a_from.func2D_borders_visible;
theta = a_from.theta;
phi = a_from.phi;
tau = a_from.tau;
legends_automated = a_from.legends_automated;
legends_origin = a_from.legends_origin;
legends_origin_unit = a_from.legends_origin_unit;
legends_size = a_from.legends_size;
legends_string = a_from.legends_string;
shape_automated = a_from.shape_automated;
shape = a_from.shape;
xy_depth = a_from.xy_depth;
curve_number_of_points = a_from.curve_number_of_points;
number_of_levels = a_from.number_of_levels;
levels = a_from.levels;
data_light_on_automated = a_from.data_light_on_automated;
primitives_enforced = a_from.primitives_enforced;
inner_frame_enforced = a_from.inner_frame_enforced;
m_etc_sep = a_from.m_etc_sep;
m_bins_style = a_from.m_bins_style;
m_errors_style = a_from.m_errors_style;
m_func_style = a_from.m_func_style;
m_points_style = a_from.m_points_style;
m_left_hatch_style = a_from.m_left_hatch_style;
m_right_hatch_style = a_from.m_right_hatch_style;
m_legend_style = a_from.m_legend_style;
m_title_style = a_from.m_title_style;
m_infos_style = a_from.m_infos_style;
m_title_box_style = a_from.m_title_box_style;
m_background_style = a_from.m_background_style;
m_wall_style = a_from.m_wall_style;
m_inner_frame_style = a_from.m_inner_frame_style;
m_grid_style = a_from.m_grid_style;
// to copy axes styles :
m_x_axis = a_from.m_x_axis;
m_y_axis = a_from.m_y_axis;
m_z_axis = a_from.m_z_axis;
m_cmap_axis = a_from.m_cmap_axis;
m_cmaps = a_from.m_cmaps;
clear_plottables();
clear_primitives();
clear_todels();
{tools_vforcit(plottable*,a_from.m_plottables,it) {m_plottables.push_back((*it)->copy());}}
{tools_vforcit(plotprim*,a_from.m_primitives,it) {m_primitives.push_back((*it)->copy());}}
return *this;
}
public:
size_t number_of_plottables() const {
size_t number = 0;
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(!object->is_valid()) continue;
// take into account all valid plottables, even the one without a representation.
number++;
}
return number;
}
#define TOOLS_SG_PLOTTER_NUMBER_OF(a__what) \
size_t number_of_plotted_##a__what##s() const {\
size_t number = 0;\
tools_vforcit(plottable*,m_plottables,it) {\
plottable* object = *it;\
if(!object) continue;\
if(!object->is_valid()) continue;\
if(safe_cast<plottable,a__what>(*object)) number++;\
}\
return number;\
}
TOOLS_SG_PLOTTER_NUMBER_OF(bins1D)
TOOLS_SG_PLOTTER_NUMBER_OF(bins2D)
TOOLS_SG_PLOTTER_NUMBER_OF(points2D)
TOOLS_SG_PLOTTER_NUMBER_OF(points3D)
TOOLS_SG_PLOTTER_NUMBER_OF(func1D)
TOOLS_SG_PLOTTER_NUMBER_OF(func2D)
#undef TOOLS_SG_PLOTTER_NUMBER_OF
void plotted_object_names(std::vector<std::string>& a_names) const {
a_names.clear();
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(!object->is_valid()) continue;
// take into account all valid plottables, even the one without a representation.
a_names.push_back(object->name());
}
}
public: //public
const torche& data_light() const {return m_data_light;}
torche& data_light() {return m_data_light;}
matrix& tsf() {return m_tsf;}
const separator& etc_sep() const {return m_etc_sep;}
separator& etc_sep() {return m_etc_sep;}
const std::vector<plottable*>& plottables() const {return m_plottables;}
void add_plottable(plottable* a_p) {
//WARNING : it takes ownership of a_p object.
m_plottables.push_back(a_p);
touch();
}
void prep_plottable(plottable* a_p) {
//WARNING : it takes ownership of a_p object.
m_plottables.insert(m_plottables.begin(),a_p);
touch();
}
void transfer_plottables(std::vector<plottable*>& a_to) {
a_to = m_plottables;
m_plottables.clear(); //do not delete plottables !
touch();
}
template <class T>
bool remove_plottables() {
bool found = false;
std::vector<plottable*>::iterator it;
for(it=m_plottables.begin();it!=m_plottables.end();) {
plottable* object = *it;
if(object && safe_cast<plottable,T>(*object)) {
it = m_plottables.erase(it);
delete object;
found = true;
} else {
it++;
}
}
if(found) touch();
return found;
}
void add_primitive(plotprim* a_prim) {m_primitives.push_back(a_prim);touch();}
void transfer_primitives(std::vector<plotprim*>& a_to) {
a_to = m_primitives;
m_primitives.clear(); //do not delete primitives !
touch();
}
template <class T>
void add_todel(T* a_obj) {
m_todel_group.add(new sg::holder<T>(a_obj));
}
template <class T>
void remove_todels(){
remove_holders<T>(m_todel_group.children());
}
void transfer_todels(std::vector<node*>& a_to) { //used in sg::plots.
m_todel_group.transfer(a_to);
}
void add_node_todel(node* a_node) { //used in sg::plots.
m_todel_group.add(a_node);
}
void clear() {
clear_plottables();
clear_primitives();
clear_todels();
legends_string.clear();
legends_origin_unit.clear();
legends_origin.clear();
legends_size.clear();
primitives_enforced = false;
inner_frame_enforced = false;
}
const sg::axis& x_axis() const {return m_x_axis;}
sg::axis& x_axis() {return m_x_axis;}
const sg::axis& y_axis() const {return m_y_axis;}
sg::axis& y_axis() {return m_y_axis;}
const sg::axis& z_axis() const {return m_z_axis;}
sg::axis& z_axis() {return m_z_axis;}
const sg::axis& colormap_axis() const {return m_cmap_axis;}
sg::axis& colormap_axis() {return m_cmap_axis;}
text_style& title_style() {return m_title_style;}
style& background_style() {return m_background_style;}
style& wall_style() {return m_wall_style;}
style& inner_frame_style() {return m_inner_frame_style;}
style& grid_style() {return m_grid_style;}
text_style& infos_style() {return m_infos_style;}
text_style& title_box_style() {return m_title_box_style;}
style& bins_style(size_t a_index) {
size_t sz = m_bins_style.size();
if(a_index>=sz) {
//012345 sz=6
// 9 a_index wanted
// 6789 loop
for(size_t index=sz;index<=a_index;index++) {
m_bins_style.push_back(style());
m_bins_style.back().modeling = modeling_top_lines();
m_bins_style.back().marker_size = 5; //for bins1D of profile.
}
}
return m_bins_style[a_index];
}
style& errors_style(size_t a_index) {
size_t sz = m_errors_style.size();
if(a_index>=sz) {
for(size_t index=sz;index<=a_index;index++) {
m_errors_style.push_back(style());
m_errors_style.back().visible = false;
}
}
return m_errors_style[a_index];
}
style& func_style(size_t a_index) {
size_t sz = m_func_style.size();
if(a_index>=sz) {
for(size_t index=sz;index<=a_index;index++) {
m_func_style.push_back(style());
}
}
return m_func_style[a_index];
}
style& points_style(size_t a_index) {
size_t sz = m_points_style.size();
if(a_index>=sz) {
//012345 sz=6
// 9 a_index wanted
// 6789 loop
for(size_t index=sz;index<=a_index;index++) {
m_points_style.push_back(style());
m_points_style.back().modeling = modeling_markers(); //for gopaw.
}
}
return m_points_style[a_index];
}
style& left_hatch_style(size_t a_index) {
size_t sz = m_left_hatch_style.size();
if(a_index>=sz) {
for(size_t index=sz;index<=a_index;index++) {
m_left_hatch_style.push_back(style());
m_left_hatch_style.back().visible = false;
}
}
return m_left_hatch_style[a_index];
}
style& right_hatch_style(size_t a_index) {
size_t sz = m_right_hatch_style.size();
if(a_index>=sz) {
for(size_t index=sz;index<=a_index;index++) {
m_right_hatch_style.push_back(style());
m_right_hatch_style.back().visible = false;
}
}
return m_right_hatch_style[a_index];
}
style& legend_style(size_t a_index) {
size_t sz = m_legend_style.size();
if(a_index>=sz) {
for(size_t index=sz;index<=a_index;index++) {
m_legend_style.push_back(style());
}
}
return m_legend_style[a_index];
}
void bins_modelings(size_t a_index,std::vector<std::string>& a_opts) {
a_opts.clear();
update_shape();
if(m_shape==xy) {
size_t ibins = 0;
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(bins1D* b1 = safe_cast<plottable,bins1D>(*object)) {
//update_bins1D_xy
if(a_index==ibins) {
if(b1->is_profile()) {
a_opts.push_back(modeling_points());
a_opts.push_back(modeling_markers());
return;
} else {
a_opts.push_back(modeling_boxes());
a_opts.push_back(modeling_wire_boxes());
a_opts.push_back(modeling_bar_chart());
a_opts.push_back(modeling_top_lines());
a_opts.push_back(modeling_points());
a_opts.push_back(modeling_markers());
return;
}
}
ibins++;
} if(safe_cast<plottable,bins2D>(*object)) {
//update_bins2D_xy
if(a_index==ibins) {
a_opts.push_back(modeling_curve());
a_opts.push_back(modeling_filled_curve());
a_opts.push_back(modeling_boxes());
a_opts.push_back(modeling_wire_boxes());
a_opts.push_back(modeling_solid());
a_opts.push_back(modeling_points());
return;
}
ibins++;
}
}
}
}
bool xx_2_yy(const vec3f& a_pos,vec3f& a_out) const {
// a_pos is in data frame NDC coordinates.
{float XSIZ = width;
float XMGL = left_margin;
float XMGR = right_margin;
float wData = XSIZ-XMGL-XMGR;
a_out[0] = wData*a_pos[0];}
{float YSIZ = height;
float YMGL = bottom_margin;
float YMGU = top_margin;
float hData = YSIZ-YMGL-YMGU;
a_out[1] = hData*a_pos[1];}
{float ZSIZ = depth;
float ZMGD = down_margin;
float ZMGU = up_margin;
float dData = ZSIZ-ZMGD-ZMGU;
a_out[2] = dData*a_pos[2];}
return true;
}
bool data_frame_2_vp(const vec3f& a_pos,vec3f& a_vp) const {
// a_pos is in data frame NDC coordinates.
// a_vp is in viewport/screen coordinates (in [0,1]).
{float XSIZ = width;
float XMGL = left_margin;
float XMGR = right_margin;
float wData = XSIZ-XMGL-XMGR;
if(XSIZ==0.0F) {
//SoDebugError::postInfo("tools::sg;:plotter::data_frame_2_vp","XSIZ is 0");
return false;
}
a_vp[0] = (wData*a_pos[0] + XMGL)/XSIZ;}
{float YSIZ = height;
float YMGL = bottom_margin;
float YMGU = top_margin;
float hData = YSIZ-YMGL-YMGU;
if(YSIZ==0.0F) {
return false;
}
a_vp[1] = (hData*a_pos[1] + YMGL)/YSIZ;}
{float ZSIZ = depth;
float ZMGD = down_margin;
float ZMGU = up_margin;
float dData = ZSIZ-ZMGD-ZMGU;
if(ZSIZ==0.0F) {
return false;
}
a_vp[2] = (dData*a_pos[2] + ZMGD)/ZSIZ;}
return true;
}
bool vp_2_data_frame(const vec3f& a_vp,vec3f& a_pos) const {
// a_vp is in viewport/screen coordinates (in [0,1]).
// a_pos is in data frame NDC coordinates.
{float XSIZ = width;
float XMGL = left_margin;
float XMGR = right_margin;
float wData = XSIZ-XMGL-XMGR;
if(wData==0.0F) {
return false;
}
a_pos[0] = (a_vp[0]*XSIZ - XMGL)/wData;}
{float YSIZ = height;
float YMGL = bottom_margin;
float YMGU = top_margin;
float hData = YSIZ-YMGL-YMGU;
if(hData==0.0F) {
return false;
}
a_pos[1] = (a_vp[1]*YSIZ - YMGL)/hData;}
{float ZSIZ = depth;
float ZMGD = down_margin;
float ZMGU = up_margin;
float dData = ZSIZ-ZMGD-ZMGU;
if(dData==0.0F) {
return false;
}
a_pos[2] = (a_vp[2]*ZSIZ - ZMGD)/dData;}
return true;
}
bool data_frame_2_axis(const vec3f& aDF,vec3f& a_pos) const {
// aDF is in data area coordinates. In [0,1][0,1][0,1].
// a_pos is in axes coordinates.
// Assume that axes min,max,is_log are up to date.
{float mn = m_x_axis.minimum_value;
float mx = m_x_axis.maximum_value;
bool lg = m_x_axis.is_log;
if(lg) {
mn = fpow(10,mn);
mx = fpow(10,mx);
}
a_pos[0] = verify_log_inv(aDF[0],mn,mx-mn,lg);}
{float mn = m_y_axis.minimum_value;
float mx = m_y_axis.maximum_value;
bool lg = m_y_axis.is_log;
if(lg) {
mn = fpow(10,mn);
mx = fpow(10,mx);
}
a_pos[1] = verify_log_inv(aDF[1],mn,mx-mn,lg);}
{float mn = m_z_axis.minimum_value;
float mx = m_z_axis.maximum_value;
bool lg = m_z_axis.is_log;
if(lg) {
mn = fpow(10,mn);
mx = fpow(10,mx);
}
a_pos[2] = verify_log_inv(aDF[2],mn,mx-mn,lg);}
return true;
}
bool axis_2_data_frame(const vec3f& a_pos,vec3f& aDF) const {
// a_pos is in axes coordinates.
// aDF in data area coordinate. In [0,1][0,1][0,1].
// Assume that axes min,max,logScale are up to date.
{float mn = m_x_axis.minimum_value;
float mx = m_x_axis.maximum_value;
if(mx==mn) {
return false;
}
bool lg = m_x_axis.is_log;
if(lg) {
if(mn<=0) {
return false;
}
if(mx<=0) {
return false;
}
mn = flog10(mn);
mx = flog10(mx);
}
aDF[0] = verify_log(a_pos[0],mn,mx-mn,lg);}
{float mn = m_y_axis.minimum_value;
float mx = m_y_axis.maximum_value;
if(mx==mn) {
return false;
}
bool lg = m_y_axis.is_log;
if(lg) {
if(mn<=0) {
return false;
}
if(mx<=0) {
return false;
}
mn = flog10(mn);
mx = flog10(mx);
}
aDF[1] = verify_log(a_pos[1],mn,mx-mn,lg);}
{float mn = m_z_axis.minimum_value;
float mx = m_z_axis.maximum_value;
if(mx==mn) {
return false;
}
bool lg = m_z_axis.is_log;
if(lg) {
if(mn<=0) {
return false;
}
if(mx<=0) {
return false;
}
mn = flog10(mn);
mx = flog10(mx);
}
aDF[2] = verify_log(a_pos[2],mn,mx-mn,lg);}
return true;
}
bool axis_2_vp(const vec3f& a_pos,vec3f& a_vp) const {
// a_pos is in axes coordinates.
// a_vp is in viewport/screen coordinates (in [0,1]).
vec3f d; // In data area coordinate. In [0,1][0,1][0,1].
if(!axis_2_data_frame(a_pos,d)) return false;
return data_frame_2_vp(d,a_vp);
}
bool vp_2_axis(const vec3f& a_vp,vec3f& a_pos) const {
// a_vp is in viewport/screen coordinates (in [0,1]).
// a_pos is in axes coordinates.
vec3f d; // In data area coordinate. In [0,1][0,1][0,1].
if(!vp_2_data_frame(a_vp,d)) return false;
return data_frame_2_axis(d,a_pos);
}
public:
void set_axes_modeling(const std::string& a_v){
m_x_axis.modeling = a_v;
m_y_axis.modeling = a_v;
m_z_axis.modeling = a_v;
m_cmap_axis.modeling = a_v;
}
void set_axes_color(const colorf& a_color){
m_x_axis.line_style().color = a_color;
m_x_axis.ticks_style().color = a_color;
m_x_axis.labels_style().color = a_color;
m_x_axis.title_style().color = a_color;
m_x_axis.mag_style().color = a_color;
m_y_axis.line_style().color = a_color;
m_y_axis.ticks_style().color = a_color;
m_y_axis.labels_style().color = a_color;
m_y_axis.title_style().color = a_color;
m_y_axis.mag_style().color = a_color;
m_z_axis.line_style().color = a_color;
m_z_axis.ticks_style().color = a_color;
m_z_axis.labels_style().color = a_color;
m_z_axis.title_style().color = a_color;
m_z_axis.mag_style().color = a_color;
m_cmap_axis.line_style().color = a_color;
m_cmap_axis.ticks_style().color = a_color;
m_cmap_axis.labels_style().color = a_color;
m_cmap_axis.title_style().color = a_color;
m_cmap_axis.mag_style().color = a_color;
}
void set_axes_text_scale(float a_v){
m_x_axis.labels_style().scale = a_v;
m_x_axis.title_style().scale = a_v;
m_x_axis.mag_style().scale = a_v;
m_y_axis.labels_style().scale = a_v;
m_y_axis.title_style().scale = a_v;
m_y_axis.mag_style().scale = a_v;
m_z_axis.labels_style().scale = a_v;
m_z_axis.title_style().scale = a_v;
m_z_axis.mag_style().scale = a_v;
m_cmap_axis.labels_style().scale = a_v;
m_cmap_axis.title_style().scale = a_v;
m_cmap_axis.mag_style().scale = a_v;
}
void set_axes_line_pattern(unsigned short a_v){
m_x_axis.line_style().pattern = a_v;
m_y_axis.line_style().pattern = a_v;
m_z_axis.line_style().pattern = a_v;
m_cmap_axis.line_style().pattern = a_v;
}
void set_axes_line_width(int a_v){
m_x_axis.line_style().width = float(a_v);
m_y_axis.line_style().width = float(a_v);
m_z_axis.line_style().width = float(a_v);
m_cmap_axis.line_style().width = float(a_v);
m_x_axis.ticks_style().width = float(a_v);
m_y_axis.ticks_style().width = float(a_v);
m_z_axis.ticks_style().width = float(a_v);
m_cmap_axis.ticks_style().width = float(a_v);
}
void set_axes_tick_length(float a_v){
m_x_axis.tick_length = a_v;
m_y_axis.tick_length = a_v;
m_z_axis.tick_length = a_v;
m_cmap_axis.tick_length = a_v;
}
void set_axes_title_height(float a_v){
m_x_axis.title_height = a_v;
m_y_axis.title_height = a_v;
m_z_axis.title_height = a_v;
m_cmap_axis.title_height = a_v;
}
void set_axes_label_height(float a_v){
m_x_axis.label_height = a_v;
m_y_axis.label_height = a_v;
m_z_axis.label_height = a_v;
m_cmap_axis.label_height = a_v;
}
void set_axes_font_modeling(font_modeling a_v){
m_x_axis.labels_style().font_modeling = a_v;
m_x_axis.title_style().font_modeling = a_v;
m_x_axis.mag_style().font_modeling = a_v;
m_y_axis.labels_style().font_modeling = a_v;
m_y_axis.title_style().font_modeling = a_v;
m_y_axis.mag_style().font_modeling = a_v;
m_z_axis.labels_style().font_modeling = a_v;
m_z_axis.title_style().font_modeling = a_v;
m_z_axis.mag_style().font_modeling = a_v;
m_cmap_axis.labels_style().font_modeling = a_v;
m_cmap_axis.title_style().font_modeling = a_v;
m_cmap_axis.mag_style().font_modeling = a_v;
}
void set_font_modeling(font_modeling a_v){
set_axes_font_modeling(a_v);
title_style().font_modeling = a_v;
infos_style().font_modeling = a_v;
title_box_style().font_modeling = a_v;
}
protected:
void init_sg(){
m_group.add(new noderef(m_background_sep));
m_group.add(new noderef(m_cmap_sep));
m_group.add(new noderef(m_infos_title_sep));
m_group.add(new noderef(m_infos_sep));
m_group.add(new noderef(m_legend_sep));
m_group.add(new noderef(m_title_box_sep));
m_group.add(new noderef(m_tsf));
m_group.add(new noderef(m_layout));
m_group.add(new noderef(m_title_sep));
m_group.add(new noderef(m_x_axis_sep));
m_group.add(new noderef(m_y_axis_sep));
m_group.add(new noderef(m_z_axis_sep));
m_group.add(new noderef(m_grid_sep));
m_group.add(new noderef(m_data_sep));
m_group.add(new noderef(m_primitives_sep));
m_cmap_sep.add(new noderef(m_cmap_matrix));
m_cmap_sep.add(new noderef(m_cmap_cells_sep));
m_cmap_sep.add(new noderef(m_cmap_axis_matrix));
m_cmap_sep.add(new noderef(m_cmap_axis));
m_x_axis_sep.add(new noderef(m_x_axis_matrix));
m_x_axis_sep.add(new noderef(m_x_axis));
m_y_axis_sep.add(new noderef(m_y_axis_matrix));
m_y_axis_sep.add(new noderef(m_y_axis));
m_z_axis_sep.add(new noderef(m_z_axis_matrix));
m_z_axis_sep.add(new noderef(m_z_axis));
m_data_sep.add(new noderef(m_data_light));
m_data_sep.add(new noderef(m_data_matrix));
m_data_sep.add(new noderef(m_bins_sep));
m_data_sep.add(new noderef(m_errors_sep));
m_data_sep.add(new noderef(m_func_sep));
m_data_sep.add(new noderef(m_points_sep));
m_data_sep.add(new noderef(m_inner_frame_sep));
m_data_sep.add(new noderef(m_etc_sep));
}
void update_layout(){
float XSIZ = width;
float XMGL = left_margin;
float XMGR = right_margin;
float wData = XSIZ-XMGL-XMGR;
float YSIZ = height;
float YMGL = bottom_margin;
float YMGU = top_margin;
float hData = YSIZ-YMGL-YMGU;
float ZSIZ = depth;
float ZMGD = down_margin;
float ZMGU = up_margin;
float dData = ZSIZ-ZMGD-ZMGU;
{mat4f& mtx = m_layout.mtx.value();
mtx.set_identity();
if(m_shape==xy) {
// in rep primitives (0,0) is the lower left corner
// of the data area square;
mtx.mul_translate(-XSIZ/2+XMGL,-YSIZ/2+YMGL,0);
if(data_light_on_automated.value()) m_data_light.on = false;
vec3f dir(0,0,-1);
m_data_light.direction = dir;
} else { //xyz
// global transformation (to have a "lego" layout) :
// translate so that the center of the scene
// is the center of the data area cube;
// then rotate to have lego 3D layout.
mtx.mul_rotate(1,0,0,theta*fdeg2rad());
mtx.mul_rotate(0,1,0,phi*fdeg2rad());
mtx.mul_rotate(1,0,0,tau*fdeg2rad());
// To place as CERN-PAW default.
// In CERN-PAW, it is the projection
// which fits in the (XSIZ,XMGL,XMGR)/(YSIZ,YMGL,YMGU)
// page setup.
rotf r1(vec3f(1,0,0),theta * fdeg2rad());
rotf r2(vec3f(0,1,0),phi * fdeg2rad());
rotf r3(vec3f(1,0,0),tau * fdeg2rad());
rotf r = r1*r2*r3;
mat4f _m;
r.value(_m);
float xmn = -0.5F*wData;
float ymn = -0.5F*hData;
float zmn = -0.5F*dData;
float xmx = 0.5F*wData;
float ymx = 0.5F*hData;
float zmx = 0.5F*dData;
box3f _box;
float x,y,z;
// zmn face :
{x = xmn;y = ymn;z = zmn;
_m.mul_3f(x,y,z);
_box.extend_by(x,y,z);}
{x = xmx;y = ymn;z = zmn;
_m.mul_3f(x,y,z);
_box.extend_by(x,y,z);}
{x = xmx;y = ymx;z = zmn;
_m.mul_3f(x,y,z);
_box.extend_by(x,y,z);}
{x = xmn;y = ymx;z = zmn;
_m.mul_3f(x,y,z);
_box.extend_by(x,y,z);}
// zmx face :
{x = xmn;y = ymn;z = zmx;
_m.mul_3f(x,y,z);
_box.extend_by(x,y,z);}
{x = xmx;y = ymn;z = zmx;
_m.mul_3f(x,y,z);
_box.extend_by(x,y,z);}
{x = xmx;y = ymx;z = zmx;
_m.mul_3f(x,y,z);
_box.extend_by(x,y,z);}
{x = xmn;y = ymx;z = zmx;
_m.mul_3f(x,y,z);
_box.extend_by(x,y,z);}
float xfac = _box.mx()[0]-_box.mn()[0];
float yfac = _box.mx()[1]-_box.mn()[1];
float zfac = _box.mx()[2]-_box.mn()[2];
//cube setup (driven by hData) :
mtx.mul_scale(hData/xfac,hData/yfac,hData/zfac);
mtx.mul_translate(-wData/2,-hData/2,-dData/2); //Applied first.
if(data_light_on_automated.value()) m_data_light.on = true;
{vec3f dir(1,-1,-10);
float dx,dy,dz;dir.value(dx,dy,dz);
mat4f inv;
if(mtx.invert(inv)) {
inv.mul_dir_3f(dx,dy,dz);
m_data_light.direction = vec3f(dx,dy,dz);
}}
}}
{mat4f& mtx = m_data_matrix.mtx.value();
mtx.set_identity();
if(m_shape==xy) {
mtx.mul_scale(wData,hData,1); //z size decided with xy_depth
} else if(m_shape==xyz) {
mtx.mul_scale(wData,hData,dData);
}}
}
public:
void update_sg(std::ostream& a_out) {
update_shape();
update_axes_data(a_out);
update_background();
update_layout();
// roundtrip over plottables to check if they are valids. Done first.
unsigned int nplottables = 0;
unsigned int nbins = 0;
unsigned int npoints = 0;
unsigned int nfunc = 0;
{tools_vforit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(!object->is_valid()) {
*it = 0;
delete object;
} else {
if(safe_cast<plottable,bins1D>(*object)) {
nplottables++;
nbins++;
} else if(safe_cast<plottable,bins2D>(*object)) {
nplottables++;
nbins++;
} else if(safe_cast<plottable,points2D>(*object)) {
nplottables++;
npoints++;
} else if(safe_cast<plottable,points3D>(*object)) {
nplottables++;
npoints++;
} else if(safe_cast<plottable,func1D>(*object)) {
nplottables++;
nfunc++;
} else if(safe_cast<plottable,func2D>(*object)) {
nplottables++;
nfunc++;
}
}
}}
clear_cmaps();
m_bins_cmaps.resize(nbins,0);
m_points_cmaps.resize(npoints,0);
m_func_cmaps.resize(nfunc,0);
// even if !nplottables we continue.
m_infos_title_sep.clear();
m_infos_sep.clear();
m_legend_strings.clear();
bool superpose = false;
float xmin = m_x_axis_data.min_value();
float xmax = m_x_axis_data.max_value();
bool xlog = m_x_axis_data.is_log();
if(xlog) {
if((xmin<=0) || (xmax<=0) ) {
m_x_axis_data.adjust();
xmin = m_x_axis_data.min_value();
xmax = m_x_axis_data.max_value();
// now should have reasonable values.
}
if((xmin<=0) || (xmax<=0) ) {
xlog = false;
} else {
xmin = flog10(xmin);
xmax = flog10(xmax);
}
}
float ymin = m_y_axis_data.min_value();
float ymax = m_y_axis_data.max_value();
bool ylog = m_y_axis_data.is_log();
if(ylog) {
if((ymin<=0) || (ymax<=0) ) {
m_y_axis_data.adjust();
ymin = m_y_axis_data.min_value();
ymax = m_y_axis_data.max_value();
// now should have reasonable values.
}
if((ymin<=0) || (ymax<=0) ) {
ylog = false;
}else{
ymin = flog10(ymin);
ymax = flog10(ymax);
}
}
float zmin = m_z_axis_data.min_value();
float zmax = m_z_axis_data.max_value();
bool zlog = m_z_axis_data.is_log();
if(zlog) {
if((zmin<=0) || (zmax<=0) ) {
m_z_axis_data.adjust();
zmin = m_z_axis_data.min_value();
zmax = m_z_axis_data.max_value();
// now should have reasonable values.
}
if((zmin<=0) || (zmax<=0) ) {
zlog = false;
}else{
zmin = flog10(zmin);
zmax = flog10(zmax);
}
}
if(m_shape==xy) {
if(xmin>=xmax) {
DUMP_UPDATE_WHAT(a_out,"bad min/max x axes");
}
if(ymin>=ymax) {
DUMP_UPDATE_WHAT(a_out,"bad min/max y axes");
}
} else if(m_shape==xyz) {
if(xmin>=xmax) {
DUMP_UPDATE_WHAT(a_out,"bad min/max x axes");
}
if(ymin>=ymax) {
DUMP_UPDATE_WHAT(a_out,"bad min/max y axes");
}
if(zmin>=zmax) {
DUMP_UPDATE_WHAT(a_out,"bad min/max z axes");
}
}
{float XSIZ = width;
float XMGL = left_margin;
float XMGR = right_margin;
float wData = XSIZ-XMGL-XMGR;
float YSIZ = height;
float YMGL = bottom_margin;
float YMGU = top_margin;
float hData = YSIZ-YMGL-YMGU;
if(m_shape==xy) {
if(wData<=0) {
DUMP_UPDATE_WHAT(a_out,"null w data area");
}
if(hData<=0) {
DUMP_UPDATE_WHAT(a_out,"null h data area");
}
} else if(m_shape==xyz) {
float ZSIZ = depth;
float ZMGD = down_margin;
float ZMGU = up_margin;
float dData = ZSIZ-ZMGD-ZMGU;
if(wData<=0) {
DUMP_UPDATE_WHAT(a_out,"null w data area");
}
if(hData<=0) {
DUMP_UPDATE_WHAT(a_out,"null h data area");
}
if(dData<=0) {
DUMP_UPDATE_WHAT(a_out,"null d data area");
}
}}
float dx = xmax - xmin;
float dy = ymax - ymin;
float dz = zmax - zmin;
rep_box boxX(xmin,dx,xlog);
rep_box boxY(ymin,dy,ylog);
rep_box boxZ(zmin,dz,zlog);
////////////////////////////////////
/// data : /////////////////////////
////////////////////////////////////
if(m_shape==xy) {
// first data plane is at zz = _zoffset().
float zz = 0;
////////////////////////////////////
/// binss //////////////////////////
////////////////////////////////////
{m_bins_sep.clear();
m_errors_sep.clear();
unsigned int ibins = 0; //used to get each bins style and colormap.
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(bins1D* b1 = safe_cast<plottable,bins1D>(*object)) {
zz += _zoffset(); // ibins = 0 back (PAW convention).
style* data_style = merge_bins_style(ibins,*object);
style* _left_hatch_style = merge_left_hatch_style(ibins,*object);
style* _right_hatch_style = merge_right_hatch_style(ibins,*object);
style* error_style = merge_errors_style(ibins,*object);
update_bins1D_xy(a_out,*b1,
*data_style,*_left_hatch_style,*_right_hatch_style,*error_style,ibins,
superpose,boxX,boxY,zz);
if(legends_automated.value()) {
m_legend_strings.push_back(object->legend());
style& _style = legend_style(m_legend_strings.size()-1);
_style.color = data_style->color;
_style.marker_style = data_style->marker_style;
_style.marker_size = data_style->marker_size;
}
delete data_style;
delete _left_hatch_style;
delete _right_hatch_style;
delete error_style;
ibins++;
} if(bins2D* b2 = safe_cast<plottable,bins2D>(*object)) {
zz += _zoffset(); // ibins = 0 back (PAW convention).
style* data_style = merge_bins_style(ibins,*object);
update_bins2D_xy(a_out,*b2,*data_style,ibins,boxX,boxY,boxZ,zz);
if(legends_automated.value()) {
m_legend_strings.push_back(object->legend());
style& _style = legend_style(m_legend_strings.size()-1);
_style.color = data_style->color;
_style.marker_style = data_style->marker_style;
_style.marker_size = data_style->marker_size;
}
delete data_style;
ibins++;
}
}}
////////////////////////////////////
/// funcs //////////////////////////
////////////////////////////////////
{m_func_sep.clear();
//zz = 0; // Functions in front.
unsigned int ifunc = 0; //used to get each func style and colormap.
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(func1D* f1 = safe_cast<plottable,func1D>(*object)) {
zz += _zoffset();
style* data_style = merge_func_style(ifunc,*object);
update_func1D_xy(a_out,*f1,*data_style,boxX,boxY,zz);
if(legends_automated.value()) {
m_legend_strings.push_back(object->legend());
style& _style = legend_style(m_legend_strings.size()-1);
_style.color = data_style->color;
_style.marker_style = data_style->marker_style;
_style.marker_size = data_style->marker_size;
}
delete data_style;
ifunc++;
} else if(func2D* f2 = safe_cast<plottable,func2D>(*object)) {
zz += _zoffset();
style* data_style = merge_func_style(ifunc,*object);
update_func2D_xy(a_out,*f2,ifunc,*data_style,boxX,boxY,boxZ,zz);
if(legends_automated.value()) {
m_legend_strings.push_back(object->legend());
style& _style = legend_style(m_legend_strings.size()-1);
_style.color = data_style->color;
_style.marker_style = data_style->marker_style;
_style.marker_size = data_style->marker_size;
}
delete data_style;
ifunc++;
}
}}
////////////////////////////////////
/// pointss ////////////////////////
////////////////////////////////////
{m_points_sep.clear();
unsigned int ipoints = 0; //used to get each points style and colormap.
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(points2D* p2 = safe_cast<plottable,points2D>(*object)) {
zz += _zoffset(); // ibins = 0 back (PAW convention).
style* data_style = merge_points_style(ipoints,*object);
update_points2D_xy(a_out,*p2,*data_style,boxX,boxY,zz);
if(legends_automated.value()) {
m_legend_strings.push_back(object->legend());
style& _style = legend_style(m_legend_strings.size()-1);
_style.color = data_style->color;
_style.modeling = data_style->modeling;
_style.marker_style = data_style->marker_style;
_style.marker_size = data_style->marker_size;
_style.point_size = data_style->point_size;
}
delete data_style;
ipoints++;
}
}}
}
if(m_shape==xyz) {
////////////////////////////////////
/// binss //////////////////////////
////////////////////////////////////
{m_bins_sep.clear();
m_errors_sep.clear();
unsigned int ibins = 0; //used to get each bins style and colormap.
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(safe_cast<plottable,bins1D>(*object)) {
ibins++;
} else if(bins2D* b2 = safe_cast<plottable,bins2D>(*object)) {
style* data_style = merge_bins_style(ibins,*object);
update_bins2D_xyz(a_out,*b2,ibins,*data_style,boxX,boxY,boxZ);
delete data_style;
ibins++;
}
}}
////////////////////////////////////
/// funcs //////////////////////////
////////////////////////////////////
{m_func_sep.clear();
unsigned int ifunc = 0; //used to get each func style and colormap.
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(safe_cast<plottable,func1D>(*object)) {
ifunc++;
} else if(func2D* f2 = safe_cast<plottable,func2D>(*object)) {
style* data_style = merge_func_style(ifunc,*object);
update_func2D_xyz(a_out,*f2,ifunc,*data_style,boxX,boxY,boxZ);
delete data_style;
ifunc++;
}
}}
////////////////////////////////////
/// pointss ////////////////////////
////////////////////////////////////
{m_points_sep.clear();
unsigned int ipoints = 0; //used to get each points style and colormap.
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(points3D* p3 = safe_cast<plottable,points3D>(*object)) {
style* data_style = merge_points_style(ipoints,*object);
update_points3D_xyz(a_out,*p3,*data_style,boxX,boxY,boxZ);
if(legends_automated.value()) {
m_legend_strings.push_back(object->legend());
style& _style = legend_style(m_legend_strings.size()-1);
_style.color = data_style->color;
_style.modeling = data_style->modeling;
_style.marker_style = data_style->marker_style;
_style.marker_size = data_style->marker_size;
_style.point_size = data_style->point_size;
}
delete data_style;
ipoints++;
}
}}
}
////////////////////////////////////
/// axes : /////////////////////////
////////////////////////////////////
// done before update_legends() which needs
// the x_axis min/max if legends_origin_unit
// is unit_axis.
// axes :
if(m_shape==xy){
if(x_axis_enforced.value()) {
update_x_axis_2D();
m_x_axis.minimum_value = x_axis_min.value();
m_x_axis.maximum_value = x_axis_max.value();
m_x_axis.is_log = x_axis_is_log.value();
m_x_axis.update_sg(a_out); // So that the grid be correct.
m_x_axis.reset_touched();
} else {
if(!nplottables) {
m_x_axis.width = 0;
} else {
update_x_axis_2D();
update_axis(a_out,m_x_axis,m_x_axis_data);
}
}
if(y_axis_enforced.value()) {
update_y_axis_2D();
m_y_axis.minimum_value = y_axis_min.value();
m_y_axis.maximum_value = y_axis_max.value();
m_y_axis.is_log = y_axis_is_log.value();
m_y_axis.update_sg(a_out); // So that the grid be correct.
m_y_axis.reset_touched();
} else {
if(!nplottables) {
m_y_axis.width = 0;
} else {
update_y_axis_2D();
update_axis(a_out,m_y_axis,m_y_axis_data);
}
}
if(z_axis_enforced.value()) {
update_z_axis_2D();
m_z_axis.minimum_value = z_axis_min.value();
m_z_axis.maximum_value = z_axis_max.value();
m_z_axis.is_log = z_axis_is_log.value();
m_z_axis.update_sg(a_out); // So that the grid be correct.
m_z_axis.reset_touched();
} else {
if(!nplottables) {
m_z_axis.width = 0;
} else {
update_z_axis_2D();
}
}
}
if(m_shape==xyz){
if(x_axis_enforced.value()) {
update_x_axis_3D();
m_x_axis.minimum_value = x_axis_min.value();
m_x_axis.maximum_value = x_axis_max.value();
m_x_axis.is_log = x_axis_is_log.value();
m_x_axis.update_sg(a_out); // So that the grid be correct.
m_x_axis.reset_touched();
} else {
if(!nplottables) {
m_x_axis.width = 0;
} else {
update_x_axis_3D();
update_axis(a_out,m_x_axis,m_x_axis_data);
}
}
if(y_axis_enforced.value()) {
update_y_axis_3D();
m_y_axis.minimum_value = y_axis_min.value();
m_y_axis.maximum_value = y_axis_max.value();
m_y_axis.is_log = y_axis_is_log.value();
m_y_axis.update_sg(a_out); // So that the grid be correct.
m_y_axis.reset_touched();
} else {
if(!nplottables) {
m_y_axis.width = 0;
} else {
update_y_axis_3D();
update_axis(a_out,m_y_axis,m_y_axis_data);
}
}
if(z_axis_enforced.value()) {
update_z_axis_3D();
m_z_axis.minimum_value = z_axis_min.value();
m_z_axis.maximum_value = z_axis_max.value();
m_z_axis.is_log = z_axis_is_log.value();
m_z_axis.update_sg(a_out); // So that the grid be correct.
m_z_axis.reset_touched();
} else {
if(!nplottables) {
m_z_axis.width = 0;
} else {
update_z_axis_3D();
update_axis(a_out,m_z_axis,m_z_axis_data);
}
}
}
if(nplottables) {
// infos box is done before update_legends()
// because legends may be placed relative to it.
update_infos(a_out);
}
m_legend_sep.clear();
if(!legends_automated) {
m_legend_strings = legends_string.values();
}
update_legends(a_out);
if(title_automated) {
std::string _s;
get_title(_s);
title.value(_s);
title.reset_touched(); //output field.
}
m_title_sep.clear();
if(nplottables) update_title();
m_title_box_sep.clear();
if(nplottables) update_title_box();
m_inner_frame_sep.clear();
if(inner_frame_enforced.value() || nplottables) {
if(m_shape==xy) {
update_inner_frame_XY();
} else {
update_inner_frame_XYZ();
}
}
m_grid_sep.clear();
if(nplottables) {
if(m_shape==xy) {
update_grid_XY();
} else {
update_grid_XYZ();
}
}
m_cmap_axis.width = 0;
m_cmap_cells_sep.clear();
if(m_bins_cmaps.size() && m_bins_cmaps[0] && m_bins_cmaps[0]->valn()) { //major_bins
update_cmap(a_out,*(m_bins_cmaps[0]));
} else if(m_points_cmaps.size() && m_points_cmaps[0] && m_points_cmaps[0]->valn()) { //major_points
update_cmap(a_out,*(m_points_cmaps[0]));
} else if(m_func_cmaps.size() && m_func_cmaps[0] && m_func_cmaps[0]->valn()) { //major_func
update_cmap(a_out,*(m_func_cmaps[0]));
}
update_primitives(a_out);
}
void get_value_axis_min_max(float a_Sw_mn,float a_Sw_mx,bool a_is_log,float& a_min,float& a_max,bool a_min_visible) {
if(a_Sw_mn>a_Sw_mx) {
a_min = 0;
a_max = 0;
return;
}
// a_Sw_mx >= a_Sw_mn.
if(a_is_log && (a_Sw_mn<=0) ) { //let data_axis.adjust() do something.
a_min = a_Sw_mn;
a_max = a_Sw_mx;
return;
}
float mn;
if(a_is_log) {
if(value_bottom_margin.value()!=0) {
float log_Sw_mn = flog10(a_Sw_mn);
float log_Sw_mx = flog10(a_Sw_mx);
float log_mn = log_Sw_mn - (log_Sw_mx-log_Sw_mn)*value_bottom_margin;
mn = fpow(10,log_mn);
} else {
mn = a_Sw_mn;
if(a_min_visible) { // arrang so that the bin with a_Sw_mn be visible.
float log_Sw_mn = flog10(a_Sw_mn);
mn = fpow(10,log_Sw_mn)*(1.0f-0.4f);
}
}
} else {
if(value_bottom_margin.value()!=0) {
mn = a_Sw_mn - (a_Sw_mx-a_Sw_mn)*value_bottom_margin;
} else {
if(a_min_visible) {
// Arrange so that the bin with a_Sw_mn (if not 0) be visible. (If 0, it will be anyway on the x axis) :
if(a_Sw_mn>0) {
mn = 0; //PAW logic.
} else if(a_Sw_mn==0) {
mn = 0; //PAW logic. min bin will be anyway on x axis.
} else {
mn = a_Sw_mn; // min bin will be anyway on x axis.
}
} else {
mn = a_Sw_mn; //min bin will be on x axis.
}
}
}
a_min = mn;
float mx;
if(a_is_log) {
if(value_top_margin.value()!=0) {
float log_Sw_mn = flog10(a_Sw_mn);
float log_Sw_mx = flog10(a_Sw_mx);
float log_mx = log_Sw_mx + (log_Sw_mx-log_Sw_mn)*value_top_margin;
mx = fpow(10,log_mx);
} else {
mx = a_Sw_mx; //max bin will be on top of frame (then not visible if same color).
}
} else {
mx = a_Sw_mx + (a_Sw_mx-mn)*value_top_margin;
//mx = a_Sw_mx + (a_Sw_mx-a_Sw_mn)*value_top_margin; //not compatible with gopaw.
}
a_max = mx;
}
void update_axes_data(std::ostream& a_out){
m_x_axis_data.set_min_value(0);
m_x_axis_data.set_max_value(0);
m_x_axis_data.set_is_log(x_axis_is_log);
m_y_axis_data.set_min_value(0);
m_y_axis_data.set_max_value(0);
m_y_axis_data.set_is_log(y_axis_is_log);
m_z_axis_data.set_min_value(0);
m_z_axis_data.set_max_value(0);
m_z_axis_data.set_is_log(z_axis_is_log);
if(!x_axis_automated) { //def = true
m_x_axis_data.set_min_value(x_axis_min);
m_x_axis_data.set_max_value(x_axis_max);
}
if(!y_axis_automated) {
m_y_axis_data.set_min_value(y_axis_min);
m_y_axis_data.set_max_value(y_axis_max);
}
if(!z_axis_automated) {
m_z_axis_data.set_min_value(z_axis_min);
m_z_axis_data.set_max_value(z_axis_max);
}
bins1D* b1;
bins2D* b2;
func1D* f1;
func2D* f2;
points2D* p2;
points3D* p3;
if(first_bins(b1,b2)) {
if(b1) {
if(x_axis_automated) {
m_x_axis_data.set_min_value(b1->axis_min());
m_x_axis_data.set_max_value(b1->axis_max());
}
if(y_axis_automated) {
float Sw_mn,Sw_mx;
b1->bins_Sw_range(Sw_mn,Sw_mx,value_bins_with_entries.value());
float mn,mx;
get_value_axis_min_max(Sw_mn,Sw_mx,m_y_axis_data.is_log(),mn,mx,true);
m_y_axis_data.set_min_value(mn);
m_y_axis_data.set_max_value(mx);
m_y_axis_data.adjust();
}
} if(b2) {
if(x_axis_automated) {
m_x_axis_data.set_min_value(b2->x_axis_min());
m_x_axis_data.set_max_value(b2->x_axis_max());
}
if(y_axis_automated) {
m_y_axis_data.set_min_value(b2->y_axis_min());
m_y_axis_data.set_max_value(b2->y_axis_max());
}
if(z_axis_automated) {
float Sw_mn,Sw_mx;
b2->bins_Sw_range(Sw_mn,Sw_mx,value_bins_with_entries.value());
float mn,mx;
get_value_axis_min_max(Sw_mn,Sw_mx,m_z_axis_data.is_log(),mn,mx,false);
m_z_axis_data.set_min_value(mn);
m_z_axis_data.set_max_value(mx);
m_z_axis_data.adjust();
}
} /*else if(f_binsList[0]->getDimension()==3) {
//FIXME : should do something.
} else {
// Unusual case.
}*/
} else if(first_points(p2,p3)) {
if(p2) {
if(x_axis_automated) {
m_x_axis_data.set_min_value(p2->x_axis_min());
m_x_axis_data.set_max_value(p2->x_axis_max());
}
if(y_axis_automated) {
float ymn = p2->y_axis_min();
float ymx = p2->y_axis_max();
m_y_axis_data.set_min_value(ymn);
m_y_axis_data.set_max_value(ymx);
}
} else if(p3) {
if(x_axis_automated) {
m_x_axis_data.set_min_value(p3->x_axis_min());
m_x_axis_data.set_max_value(p3->x_axis_max());
}
if(y_axis_automated) {
m_y_axis_data.set_min_value(p3->y_axis_min());
m_y_axis_data.set_max_value(p3->y_axis_max());
}
if(z_axis_automated) {
m_z_axis_data.set_min_value(p3->z_axis_min());
m_z_axis_data.set_max_value(p3->z_axis_max());
}
}
} else if(first_func(f1,f2)) {
if(f1) {
if(x_axis_automated) {
float xmn = f1->x_min();
float xmx = f1->x_max();
if(xmx<=xmn) {
xmn = -1;
xmx = 1;
}
m_x_axis_data.set_min_value(xmn);
m_x_axis_data.set_max_value(xmx);
}
if(y_axis_automated) {
float xmn = m_x_axis_data.min_value();
float xmx = m_x_axis_data.max_value();
unsigned int nstp = f1->x_steps();
nstp = nstp <=0 ? curve_number_of_points.value(): nstp;
float df = (xmx - xmn)/nstp;
bool problem = false;
float vmin;
if(!f1->value(xmn,vmin)) problem = true;
float vmax = vmin;
for(unsigned int ibin=0;ibin<=nstp;ibin++) {
float xx = xmn + ibin * df;
float val;
if(!f1->value(xx,val)) problem = true;
vmax = max_of<float>(vmax,val);
vmin = min_of<float>(vmin,val);
}
if(problem) {
a_out << "tools::sg::plotter :"
<< " problem when getting some function value."
<< std::endl;
}
m_y_axis_data.set_min_value(vmin);
m_y_axis_data.set_max_value(vmax);
m_y_axis_data.adjust();
}
} else if(f2) {
if(x_axis_automated) {
float xmn = f2->x_min();
float xmx = f2->x_max();
if(xmx<=xmn) {
xmn = -1;
xmx = 1;
}
m_x_axis_data.set_min_value(xmn);
m_x_axis_data.set_max_value(xmx);
}
if(y_axis_automated) {
float ymn = f2->y_min();
float ymx = f2->y_max();
if(ymx<=ymn) {
ymn = -1;
ymx = 1;
}
m_y_axis_data.set_min_value(ymn);
m_y_axis_data.set_max_value(ymx);
}
if(z_axis_automated) {
float xmn = m_x_axis_data.min_value();
float xmx = m_x_axis_data.max_value();
int nx = f2->x_steps();
nx = nx <=0 ? curve_number_of_points.value() : nx;
float ymn = m_y_axis_data.min_value();
float ymx = m_y_axis_data.max_value();
int ny = f2->y_steps();
ny = ny <=0 ? curve_number_of_points.value() : ny;
float dfx = (xmx - xmn)/nx;
float dfy = (ymx - ymn)/ny;
bool problem = false;
float vmin;
if(!f2->value(xmn,ymn,vmin)) problem = true;
float vmax = vmin;
for(int jbin=ny-1;jbin>=0;jbin--) {
for(int ibin=nx-1;ibin>=0;ibin--) {
float xx = xmn + ibin * dfx;
float yy = ymn + jbin * dfy;
float val;
if(!f2->value(xx,yy,val)) problem = true;
vmin = min_of<float>(vmin,val);
vmax = max_of<float>(vmax,val);
}
}
if(problem) {
a_out << "tools::sg::plotter :"
<< " problem when getting some function value."
<< std::endl;
}
m_z_axis_data.set_min_value(vmin);
m_z_axis_data.set_max_value(vmax);
m_z_axis_data.adjust();
}
}
}
}
void update_shape(){
m_shape = get_shape();
}
void update_axis(std::ostream& a_out,sg::axis& a_axis,data_axis& a_data){
a_axis.minimum_value = a_data.min_value();
a_axis.maximum_value = a_data.max_value();
a_axis.is_log = a_data.is_log();
a_axis.update_sg(a_out); // So that the grid be correct.
a_axis.reset_touched();
}
void update_x_axis_2D(){
float XSIZ = width;
float XMGL = left_margin;
float XMGR = right_margin;
float wData = XSIZ-XMGL-XMGR;
//m_x_axis.verbose.setValue(verbose);
m_x_axis.tick_up = true;
m_x_axis.width = wData;
{text_style& style = m_x_axis.labels_style();
if(!style.enforced.value()) { //gopaw may enforce style.
style.x_orientation = vec3f(1,0,0);
style.y_orientation = vec3f(0,1,0);
style.hjust = center;
style.vjust = top;
}}
{text_style& style = m_x_axis.title_style();
style.x_orientation = vec3f(1,0,0);
style.y_orientation = vec3f(0,1,0);
style.hjust = m_x_axis.title_hjust;
style.vjust = top;}
{text_style& style = m_x_axis.mag_style();
style.hjust = left;
style.vjust = bottom;}
m_x_axis_matrix.set_translate(0,0,_zaxis());
}
void update_y_axis_2D(){
float YSIZ = height;
float YMGL = bottom_margin;
float YMGU = top_margin;
float hData = YSIZ-YMGL-YMGU;
m_y_axis.tick_up.value(true);
m_y_axis.width.value(hData);
{text_style& style = m_y_axis.labels_style();
if(!style.enforced.value()) {
style.x_orientation = vec3f(0,1,0);
style.y_orientation = vec3f(1,0,0);
style.hjust = right;
style.vjust = middle;
}}
{text_style& style = m_y_axis.title_style();
style.x_orientation = vec3f(1,0,0);
style.y_orientation = vec3f(0,-1,0);
style.hjust = m_y_axis.title_hjust;
style.vjust = bottom;}
{text_style& style = m_y_axis.mag_style();
style.x_orientation = vec3f(0,1,0);
style.y_orientation = vec3f(1,0,0);
style.hjust = right;
style.vjust = bottom;}
{mat4f& mtx = m_y_axis_matrix.mtx.value();
mtx.set_translate(0,0,_zaxis());
mtx.mul_rotate(0,1,0,fpi());
mtx.mul_rotate(0,0,1,fhalf_pi());}
}
void update_z_axis_2D(){
m_z_axis.width = 0;
m_z_axis_matrix.set_identity();
}
void update_x_axis_3D(){
float XSIZ = width;
float XMGL = left_margin;
float XMGR = right_margin;
float wData = XSIZ-XMGL-XMGR;
m_x_axis.tick_up = false;
m_x_axis.width = wData;
{text_style& style = m_x_axis.labels_style();
if(!style.enforced.value()) {
style.x_orientation = vec3f(1,0,0);
style.y_orientation = vec3f(0,1,0);
style.hjust = center;
style.vjust = top;
}}
{text_style& style = m_x_axis.title_style();
style.x_orientation = vec3f(1,0,0);
style.y_orientation = vec3f(0,1,0);
style.hjust = right;
style.vjust = top;}
m_x_axis_matrix.set_rotate(1,0,0,fhalf_pi());
}
void update_y_axis_3D(){
float YSIZ = height;
float YMGL = bottom_margin;
float YMGU = top_margin;
float hData = YSIZ-YMGL-YMGU;
m_y_axis.tick_up = false;
m_y_axis.width = hData;
{text_style& style = m_y_axis.labels_style();
if(!style.enforced.value()) {
style.x_orientation = vec3f(-1,0,0);
style.y_orientation = vec3f( 0,1,0);
style.hjust = center;
style.vjust = top;
}}
{text_style& style = m_y_axis.title_style();
style.x_orientation = vec3f(-1,0,0);
style.y_orientation = vec3f( 0,1,0);
style.hjust = left;
style.vjust = top;}
{mat4f& mtx = m_y_axis_matrix.mtx.value();
mtx.set_rotate(0,1,0,fhalf_pi());
mtx.mul_rotate(0,0,1,fhalf_pi());}
}
void update_z_axis_3D(){
float ZSIZ = depth;
float ZMGD = down_margin;
float ZMGU = up_margin;
float dData = ZSIZ-ZMGD-ZMGU;
m_z_axis.tick_up = false;
m_z_axis.width = dData;
{text_style& style = m_z_axis.labels_style();
if(!style.enforced.value()) {
style.x_orientation = vec3f(0,1,0);
style.y_orientation = vec3f(1,0,0);
style.hjust = right;
style.vjust = middle;
}}
{text_style& style = m_z_axis.title_style();
style.x_orientation = vec3f(0,1,0);
style.y_orientation = vec3f(1,0,0);
style.hjust = right;
style.vjust = bottom;}
{mat4f& mtx = m_z_axis_matrix.mtx.value();
mtx.set_translate(0,m_y_axis.width.value(),0);
mtx.mul_rotate(0,0,1,-fhalf_pi());
mtx.mul_rotate(0,1,0,-fhalf_pi());}
}
void update_cmap(std::ostream& a_out,const base_colormap& a_cmap){
if(!colormap_visible.value()) return;
size_t valn = a_cmap.valn();
if(!valn) return;
size_t coln = a_cmap.colorn();
if(!coln) return;
float XSIZ = width;
float XMGL = left_margin;
float XMGR = right_margin;
float wData = XSIZ-XMGL-XMGR;
float YSIZ = height;
float YMGL = bottom_margin;
float YMGU = top_margin;
float hData = YSIZ-YMGL-YMGU;
float hcmap = hData;
{mat4f& mtx = m_cmap_matrix.mtx.value();
if(m_shape==xy) {
mtx = m_layout.mtx.value();
mtx.mul_translate(0,0,_zgrid());
} else {
float ZSIZ = depth;
float ZMGD = down_margin;
float ZMGU = up_margin;
float dData = ZSIZ-ZMGD-ZMGU;
hcmap = dData;
if(colormap_attached.value()) {
mtx = m_layout.mtx.value();
mtx.mul_rotate(1,0,0,90.0F*fdeg2rad());
} else { //OpenPAW
float zz = -depth*0.5f;
mtx.set_translate(-XSIZ/2+XMGL,-YSIZ/2+YMGL,zz); //applied first
}
}}
float w = XMGR*0.3F;
float xx = wData+XMGR*0.1F;
float zz = 0;
float yy = 0;
float h = hcmap/float(coln);
// colored cells :
{m_cmap_cells_sep.clear();
m_cmap_cells_sep.add(new normal);
for(unsigned int index=0;index<coln;index++) {
rgba* mat = new rgba();
mat->color = a_cmap.color(index);
m_cmap_cells_sep.add(mat);
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
m_cmap_cells_sep.add(vtxs);
vtxs->add(xx ,yy ,zz);
vtxs->add(xx + w ,yy ,zz);
vtxs->add(xx + w ,yy + h ,zz);
vtxs->add(xx ,yy + h ,zz);
yy += h;
}}
// surrounding box :
{rgba* mat = new rgba();
mat->color = colorf_black();
m_cmap_cells_sep.add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = line_solid;
ds->line_width = 1;
m_cmap_cells_sep.add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::line_strip();
m_cmap_cells_sep.add(vtxs);
vtxs->add(xx ,0 ,zz);
vtxs->add(xx + w ,0 ,zz);
vtxs->add(xx + w ,hcmap ,zz);
vtxs->add(xx ,hcmap ,zz);
vtxs->add(xx ,0 ,zz);}
if(!colormap_axis_visible.value()) {
m_cmap_axis.width = 0;
} else {
// right axis :
mat4f& mtx = m_cmap_axis_matrix.mtx.value();
mtx.set_identity();
zz += _zoffset()*0.01f;
if(safe_cast<base_colormap,by_value_colormap>(a_cmap)) {
if(colormap_axis_labeling.value()==cells) {
if((valn+1)==coln) { // <col> <num> <col> ... <num> <col>
mtx.set_translate(xx+w,h,zz);
} else {
mtx.set_translate(xx+w,0,zz);
}
} else {
mtx.set_translate(xx+w,0,zz);
}
} else { //grey_scale,grey_scale_inverse,violet_to_red
mtx.set_translate(xx+w,0,zz);
}
mtx.mul_rotate(0,0,1,fhalf_pi());
m_cmap_axis.title = "";
m_cmap_axis.tick_up = true;
if(safe_cast<base_colormap,by_value_colormap>(a_cmap)) {
if(colormap_axis_labeling.value()==cells) {
if((valn+1)==coln) { // <col> <num> <col> ... <num> <col>
m_cmap_axis.width = hcmap-2*h;
m_cmap_axis.modeling = tick_modeling_none();
m_cmap_axis.tick_number = uint32(valn);
m_cmap_axis.labels.clear();
m_cmap_axis.coords.clear();
for(unsigned int index=0;index<valn;index++) {
//FIXME : for the labels, have a "mag" logic similar to SoAxis.
char tmp[32];
snpf(tmp,sizeof(tmp),"%g",a_cmap.value(index));
m_cmap_axis.labels.add(tmp);
m_cmap_axis.coords.add(h*index);
}
} else if((coln+1)==valn) { // <num> <col> <num> ... <col> <num>
m_cmap_axis.width = hcmap;
m_cmap_axis.modeling = tick_modeling_none();
m_cmap_axis.tick_number = uint32(valn);
m_cmap_axis.labels.clear();
m_cmap_axis.coords.clear();
for(unsigned int index=0;index<valn;index++) {
//FIXME : for the labels, have a "mag" logic similar to SoAxis.
char tmp[32];
snpf(tmp,sizeof(tmp),"%g",a_cmap.value(index));
m_cmap_axis.labels.add(tmp);
m_cmap_axis.coords.add(h*index);
}
} else {
a_out << "tools::sg::plotter::update_cmap :"
<< " inconsistent by value colormap."
<< std::endl;
}
} else {
m_cmap_axis.modeling = tick_modeling_hippo();
m_cmap_axis.width = hcmap;
m_cmap_axis.minimum_value = a_cmap.value(0);
m_cmap_axis.maximum_value = a_cmap.value(uint32(valn)-1);
}
} else { //grey_scale,grey_scale_inverse,violet_to_red
m_cmap_axis.modeling = tick_modeling_hippo();
m_cmap_axis.width = hcmap;
m_cmap_axis.minimum_value = a_cmap.value(0);
m_cmap_axis.maximum_value = a_cmap.value(uint32(valn)-1);
}
{text_style& style = m_cmap_axis.labels_style();
style.x_orientation = vec3f(0,-1,0);
style.y_orientation = vec3f(1,0,0);
style.hjust = left;
style.vjust = middle;}
{text_style& style = m_cmap_axis.mag_style();
style.hjust = center;
style.vjust = bottom;}
}//end axis
}
void update_primitives(std::ostream& a_out) {
m_primitives_sep.clear();
tools_vforcit(plotprim*,m_primitives,it) {
if(plottable_text* ptext = safe_cast<plotprim,plottable_text>(*(*it))) {
update_primitive_text(*ptext);
} else if(plottable_box* pbox = safe_cast<plotprim,plottable_box>(*(*it))) {
update_primitive_box(a_out,*pbox);
} else if(plottable_ellipse* pellipse = safe_cast<plotprim,plottable_ellipse>(*(*it))) {
update_primitive_ellipse(a_out,*pellipse);
} else if(plottable_img* pimg = safe_cast<plotprim,plottable_img>(*(*it))) {
update_primitive_img(a_out,*pimg);
}
}
}
protected: //vis bins
void update_bins1D_xy(std::ostream& a_out,
const bins1D& a_bins,
const style& a_data_style,
const style& a_left_hatch_style,
const style& a_right_hatch_style,
const style& a_errors_style,
int a_index,
bool /*aSuperpose*/,
const rep_box& a_box_x,
const rep_box& a_box_y,
float a_zz){
float bmin = 0;
float bmax = 0;
size_t xnbin = a_bins.bins();
std::vector<rep_bin1D> bins(xnbin);
{bool first = true;
for(size_t ibin=0;ibin<xnbin;ibin++) {
float val = a_bins.bin_Sw(int(ibin));
float xx = float(a_bins.bin_lower_edge(int(ibin)));
float xe = float(a_bins.bin_upper_edge(int(ibin)));
bins[ibin] = rep_bin1D(xx,xe,0,val);
if(first) {
first = false;
bmin = val;
bmax = val;
} else {
bmin = min_of<float>(bmin,val);
bmax = max_of<float>(bmax,val);
}
}}
bool errors_visible = a_errors_style.visible;
if(a_data_style.visible) {
painting_policy painting = a_data_style.painting;
if(painting==painting_by_value) {
m_bins_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_data_style.color_mapping);
} else if( (painting==painting_grey_scale) ||
(painting==painting_grey_scale_inverse) ||
(painting==painting_violet_to_red) ){
{float dbins = bmax-bmin;
if(dbins!=0.0F) {
for(size_t index=0;index<xnbin;index++) bins[index].m_ratio = (a_bins.bin_Sw(int(index))-bmin)/dbins;
}}
if(painting==painting_grey_scale) {
m_bins_cmaps[a_index] = new grey_scale_colormap(bmin,bmax,50);
} else if(painting==painting_grey_scale_inverse) {
m_bins_cmaps[a_index] = new grey_scale_inverse_colormap(bmin,bmax,50);
} else if(painting==painting_violet_to_red) {
m_bins_cmaps[a_index] = new violet_to_red_colormap(bmin,bmax,50);
}
} else {
m_bins_cmaps[a_index] = new const_colormap(a_data_style.color);
}
if(a_bins.is_profile()) {
style data_style = a_data_style;
data_style.modeling = modeling_markers();
rep_bins1D_xy_points(a_out,data_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz);
std::vector<float> bars(xnbin);
for(size_t ibin=0;ibin<xnbin;ibin++) bars[ibin] = a_bins.bin_error(int(ibin));
rep_errors_plus_xy(a_out,a_data_style,bins,a_box_x,a_box_y,bars,a_zz+_zerrors());
errors_visible = false;
} else {
const std::string& modeling = a_data_style.modeling;
bool _bar_chart = false;
if((modeling==modeling_points())||(modeling==modeling_markers())){
rep_bins1D_xy_points(a_out,a_data_style,
*(m_bins_cmaps[a_index]),
bins,a_box_x,a_box_y,a_zz);
//}
} else if(modeling==modeling_boxes()) {
rep_bins1D_xy_boxes(a_data_style,
*(m_bins_cmaps[a_index]),
bins,a_box_x,a_box_y,a_zz //,std::string(sid_bin)
);
} else if(modeling==modeling_wire_boxes()) {
rep_bins1D_xy_wire_boxes(a_data_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz,false);
} else if(modeling==modeling_bar_chart()) {
_bar_chart = true;
rep_bins1D_xy_wire_boxes(a_data_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz,true);
} else if(modeling==modeling_lines()){
rep_bins1D_xy_lines_one(a_data_style,bins,a_box_x,a_box_y,a_zz/*,std::string(sid)*/);
} else if(modeling==modeling_curve()){
rep_bins1D_xy_curve_one(a_out,a_data_style,bins,a_box_x,a_box_y,a_zz/*,std::string(sid)*/);
} else if(modeling==modeling_top_lines_boxes()) { //gopaw. pawex24, k_plus.
style _style;_style.color = colorf_white();
rep_bins1D_xy_boxes(_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz);
rep_bins1D_xy_top_lines(a_data_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz+_zhatch());
} else { //default modeling==modeling_top_lines()
rep_bins1D_xy_top_lines(a_data_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz/*,std::string(sid_bin)*/);
}
hatching_policy hatching = a_data_style.hatching.value();
if(hatching!=hatching_none) {
// WARNING : must come AFTER rep_bins1_xy.
if((hatching==hatching_right)||((hatching==hatching_left_and_right))) {
rep_hatch1D_xy(a_right_hatch_style,bins,a_box_x,a_box_y,a_zz+_zhatch(),_bar_chart);
}
if((hatching==hatching_left)||((hatching==hatching_left_and_right))) {
rep_hatch1D_xy(a_left_hatch_style,bins,a_box_x,a_box_y,a_zz+_zhatch(),_bar_chart);
}
}
} //end !is_profile.
} //end data_style visible
// Errors :
if(errors_visible) {
std::vector<float> bars(xnbin);
for(size_t ibin=0;ibin<xnbin;ibin++) bars[ibin] = a_bins.bin_error(int(ibin));
const std::string& modeling = a_errors_style.modeling;
if(modeling==modeling_plus()) {
rep_errors_plus_xy(a_out,a_errors_style,bins,a_box_x,a_box_y,bars,a_zz+_zerrors());
} else { //modeling_I()
rep_errors_I_xy(a_out,a_errors_style,bins,a_box_x,a_box_y,bars,a_zz+_zerrors());
}
}
}
static bool bins2D_to_func(const bins2D& a_bins,float a_X,float a_Y,float& a_value){
unsigned int xn = a_bins.x_bins();
float xmn = a_bins.x_axis_min();
float xmx = a_bins.x_axis_max();
unsigned int yn = a_bins.y_bins();
float ymn = a_bins.y_axis_min();
float ymx = a_bins.y_axis_max();
float dx = (xmx-xmn)/xn;
float dy = (ymx-ymn)/yn;
int ibin = (int)((a_X-xmn)/dx);
int jbin = (int)((a_Y-ymn)/dy);
if((ibin<0)||(ibin>=int(xn))) {a_value=0;return false;}
if((jbin<0)||(jbin>=int(yn))) {a_value=0;return false;}
float xx_0 = a_bins.bin_lower_edge_x(ibin);
float xx_1 = a_bins.bin_lower_edge_x(ibin+1);
float yy_0 = a_bins.bin_lower_edge_y(jbin);
float yy_1 = a_bins.bin_lower_edge_y(jbin+1);
float val1 = a_bins.bin_Sw(ibin,jbin);
float val2 = a_bins.bin_Sw(ibin+1,jbin);
float val4 = a_bins.bin_Sw(ibin,jbin+1);
// Interpolate :
vec3f p1(xx_0,yy_0,val1);
vec3f p2(xx_1,yy_0,val2);
vec3f p4(xx_0,yy_1,val4);
//FIXME : case of (x,y) in (p2,p3,p4)
plane<vec3f> _plane(p1,p2,p4);
vec3f pt;
line<vec3f> _line(vec3f(a_X,a_Y,0),vec3f(a_X,a_Y,10));
_plane.intersect(_line,pt);
a_value = pt[2];
return true;
}
typedef struct {
const func2D* m_func2D;
const bins2D* m_bins2D;
double m_limits[4];
double m_limits_in[4];
bool m_problem;
} SbFunc;
static double bins2D_to_contour(double a_X,double a_Y,void* aData) {
SbFunc* func =(SbFunc*)aData;
if( (a_X<func->m_limits_in[0])||
(a_X>func->m_limits_in[1])||
(a_Y<func->m_limits_in[2])||
(a_Y>func->m_limits_in[3])
) return -FLT_MAX;
float value;
if(!bins2D_to_func(*(func->m_bins2D),(float)a_X,(float)a_Y,value)) func->m_problem = true;
return value;
}
static double log_bins2D_to_contour(double a_X,double a_Y,void* aData) {
SbFunc* func =(SbFunc*)aData;
if( (a_X<func->m_limits_in[0])||
(a_X>func->m_limits_in[1])||
(a_Y<func->m_limits_in[2])||
(a_Y>func->m_limits_in[3])
) return -FLT_MAX;
float value;
if(!bins2D_to_func(*(func->m_bins2D),(float)a_X,(float)a_Y,value)) func->m_problem = true;
return take_log(value);
}
void update_bins2D_xy(std::ostream& a_out,
const bins2D& a_bins,
const style& a_data_style,
int a_index,
const rep_box& a_box_x,
const rep_box& a_box_y,
const rep_box& a_box_z,
float a_zz){
if(!a_data_style.visible) return;
unsigned int xnbin = a_bins.x_bins();
unsigned int ynbin = a_bins.y_bins();
const std::string& modeling = a_data_style.modeling;
if( (modeling==modeling_curve()) || (modeling==modeling_filled_curve()) ){
a_out << "tools::sg::update_bins2D_xy : modeling_curve :" << std::endl;
painting_policy painting = a_data_style.painting;
float zmin = a_box_z.m_pos;
float dz = a_box_z.m_width;
bool zlog = a_box_z.m_log;
float xmn = m_x_axis_data.min_value();
float xmx = m_x_axis_data.max_value();
float ymn = m_y_axis_data.min_value();
float ymx = m_y_axis_data.max_value();
clist_contour list_contour;
int nFir = 128;
list_contour.set_first_grid(nFir,nFir); //Default : 32,32
int nSec = 512; //slower than 256
list_contour.set_secondary_grid(nSec,nSec); //Default : 256,256.
double limits[4];
// User limits :
limits[0] = xmn;
limits[1] = xmx;
limits[2] = ymn;
limits[3] = ymx;
SbFunc sbFunc;
sbFunc.m_func2D = 0;
sbFunc.m_problem = false;
sbFunc.m_bins2D = &a_bins;
sbFunc.m_limits_in[0] = limits[0];
sbFunc.m_limits_in[1] = limits[1];
sbFunc.m_limits_in[2] = limits[2];
sbFunc.m_limits_in[3] = limits[3];
// Extend the grid to have some borders in order to close contours :
int n = nSec - 2 * 10;
double dx = (limits[1]-limits[0]) /n;
double dy = (limits[3]-limits[2]) /n;
limits[0] = limits[0] - 10 * dx;
limits[1] = limits[1] + 10 * dx;
limits[2] = limits[2] - 10 * dy;
limits[3] = limits[3] + 10 * dy;
sbFunc.m_limits[0] = limits[0];
sbFunc.m_limits[1] = limits[1];
sbFunc.m_limits[2] = limits[2];
sbFunc.m_limits[3] = limits[3];
list_contour.set_limits(limits);
if(levels.size()) {
size_t zn = levels.size();
std::vector<double> zs(zn);
for(size_t zi=0;zi<zn;zi++) zs[zi] = levels[zi];
list_contour.set_planes(zs);
} else {
unsigned int zn = number_of_levels.value();
if(zn<=0) zn = 1;
std::vector<double> zs(zn+1);
float zmax = zmin + dz;
double zd = (zmax-zmin)/zn;
for(unsigned int zi=0;zi<=zn;zi++) zs[zi] = zmin + zi * zd;
list_contour.set_planes(zs);
}
if(zlog)
list_contour.set_field_fcn(log_bins2D_to_contour,(void*)&sbFunc);
else
list_contour.set_field_fcn(bins2D_to_contour,(void*)&sbFunc);
list_contour.ccontour::generate();
if(!list_contour.compact_strips ()) {
a_out << "tools::sg::plotter::updateBins2D_XY : clist_contour::compact_strips () : failure." << std::endl;
} else {
if( (painting==painting_by_level) || (painting==painting_by_value) ){
m_bins_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_data_style.color_mapping);
if(zlog) m_bins_cmaps[a_index]->set_PAW_coloring();
} else {
m_bins_cmaps[a_index] = new const_colormap(a_data_style.color);
}
if(modeling==modeling_filled_curve()) {
rep_contour_xy_filled(a_out,a_data_style,
painting,*(m_bins_cmaps[a_index]),
list_contour,a_box_x,a_box_y,a_box_z,a_zz /*,std::string(sid.c_str())*/);
} else {
rep_contour_xy(a_out,a_data_style,
painting,*(m_bins_cmaps[a_index]),
list_contour,a_box_x,a_box_y,a_box_z,a_zz /*,std::string(sid.c_str())*/);
}
}
if(sbFunc.m_problem) {
a_out << "tools::sg::plotter::updateFunction_XY(SbPlottableFunction2D) : "
<< "problem when getting some function value." << std::endl;
}
} else {
bool hbe = a_bins.has_entries_per_bin();
float bmin = 0;
float bmax = 0;
std::vector<rep_bin2D> bins;
{bool first = true;
for(int jbin=ynbin-1;jbin>=0;jbin--) {
for(int ibin=xnbin-1;ibin>=0;ibin--) {
if(hbe && (a_bins.bin_entries(ibin,jbin)<=0)) continue;
float val = a_bins.bin_Sw(ibin,jbin);
float xx = a_bins.bin_lower_edge_x(ibin);
float xe = a_bins.bin_upper_edge_x(ibin);
float yy = a_bins.bin_lower_edge_y(jbin);
float ye = a_bins.bin_upper_edge_y(jbin);
bins.push_back(rep_bin2D(xx,xe,yy,ye,val,ibin,jbin));
if(first) {
first = false;
bmin = val;
bmax = val;
} else {
bmin = min_of<float>(bmin,val);
bmax = max_of<float>(bmax,val);
}
}
}}
size_t number = bins.size();
painting_policy painting = a_data_style.painting;
if(painting==painting_by_value) {
m_bins_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_data_style.color_mapping);
} else if( (painting==painting_grey_scale) ||
(painting==painting_grey_scale_inverse) ||
(painting==painting_violet_to_red) ){
{float dbins = bmax-bmin;
if(dbins!=0.0F) {
for(size_t index=0;index<number;index++) {
bins[index].m_ratio = (bins[index].m_val-bmin)/dbins;
}
}}
if(painting==painting_grey_scale) {
m_bins_cmaps[a_index] = new grey_scale_colormap(bmin,bmax,50);
} else if(painting==painting_grey_scale_inverse) {
m_bins_cmaps[a_index] = new grey_scale_inverse_colormap(bmin,bmax,50);
} else if(painting==painting_violet_to_red) {
m_bins_cmaps[a_index] = new violet_to_red_colormap(bmin,bmax,50);
}
} else {
m_bins_cmaps[a_index] = new const_colormap(a_data_style.color);
}
if(modeling==modeling_solid()) {
rep_bins2D_xy_solid(a_data_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz);
} else if(modeling==modeling_points()) {
rep_bins2D_xy_random_one(a_data_style,bins,a_box_x,a_box_y,bmin,bmax,a_zz/*,std::string(sid)*/);
} else if(modeling==modeling_wire_boxes()) {
rep_bins2D_xy_wire_box(a_data_style,bins,a_box_x,a_box_y,bmin,bmax,a_zz/*,std::string(sid_bin)*/);
} else if(modeling==modeling_texts()) {
rep_bins2D_xy_text(a_data_style,bins,a_box_x,a_box_y/*,std::string(sid_bin)*/);
} else { //default rep modeling==modeling_boxes()
rep_bins2D_xy_box(a_data_style,bins,a_box_x,a_box_y,bmin,bmax,a_zz);
}
} //end if modeling
}
void update_func1D_xy(std::ostream& a_out,const func1D& a_func,
const style& a_style,const rep_box& a_box_x,const rep_box& a_box_y,float a_zz){
if(!a_style.visible) return;
float xmn = m_x_axis_data.min_value();
float xmx = m_x_axis_data.max_value();
unsigned int nstp = a_func.x_steps();
nstp = nstp <=0 ? curve_number_of_points.value() : nstp;
float df = (xmx - xmn)/nstp;
bool problem = false;
std::vector<vec3f> points(nstp+1);
for(unsigned int ibin=0;ibin<=nstp;ibin++) {
float xx = xmn + ibin * df;
float val;
if(!a_func.value(xx,val)) problem = true;
points[ibin].set_value(xx,val,a_zz);
}
if(problem) {
a_out << "tools::sg::plotter::update_func1D_xy :"
<< " problem when getting some function value."
<< std::endl;
}
const std::string& modeling = a_style.modeling;
if(modeling==modeling_points()){
vertices* vtxs = new vertices;
std::vector<float>& pts = vtxs->xyzs.values(); //npt*3
clip_points_2D(points,a_box_x,a_box_y,pts);
if(pts.size()) {
separator* sep = new separator;
m_func_sep.add(sep);
rgba* mat = new rgba();
mat->color = a_style.color;
sep->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_points;
ds->point_size = a_style.point_size;
sep->add(ds);
vtxs->mode = gl::points();
sep->add(vtxs);
} else {
delete vtxs;
}
} else if(modeling==modeling_markers()){
markers* _marks = new markers;
std::vector<float>& pts = _marks->xyzs.values(); //npt*3
clip_points_2D(points,a_box_x,a_box_y,pts);
if(pts.size()) {
separator* sep = new separator;
m_func_sep.add(sep);
rgba* mat = new rgba();
mat->color = a_style.color;
sep->add(mat);
_marks->size = a_style.marker_size;
_marks->style = a_style.marker_style;
sep->add(_marks);
} else {
delete _marks;
}
} else {
vertices* vtxs = new vertices;
std::vector<float>& pts = vtxs->xyzs.values(); //npt*3
clip_polyline_2D(points,a_box_x,a_box_y,pts);
if(pts.size()) {
separator* sep = new separator;
m_func_sep.add(sep);
rgba* mat = new rgba();
mat->color = a_style.color;
sep->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = a_style.line_pattern;
ds->line_width = a_style.line_width;
sep->add(ds);
vtxs->mode = gl::line_strip();
sep->add(vtxs);
} else {
delete vtxs;
}
}
}
static double function_to_contour(double a_X,double a_Y,void* aData) {
SbFunc* func = (SbFunc*)aData;
if( (a_X<func->m_limits_in[0])||
(a_X>func->m_limits_in[1])||
(a_Y<func->m_limits_in[2])||
(a_Y>func->m_limits_in[3])
) return -FLT_MAX;
float value;
if(!func->m_func2D->value((float)a_X,(float)a_Y,value)) func->m_problem = true;
return double(value);
}
static double log_function_to_contour(double a_X,double a_Y,void* aData) {
SbFunc* func =(SbFunc*)aData;
if( (a_X<func->m_limits_in[0])||
(a_X>func->m_limits_in[1])||
(a_Y<func->m_limits_in[2])||
(a_Y>func->m_limits_in[3])
) return -FLT_MAX;
float value;
if(!func->m_func2D->value((float)a_X,(float)a_Y,value)) func->m_problem = true;
return take_log(value);
}
void update_func2D_xy(std::ostream& a_out,const func2D& a_func,int a_index,style& a_data_style,
const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z,float a_zz){
if(!a_data_style.visible.value()) return;
const std::string& modeling = a_data_style.modeling.getValue();
painting_policy painting = a_data_style.painting;
if( (modeling==modeling_curve()) || (modeling==modeling_filled_curve()) ) {
float zmin = a_box_z.m_pos;
float dz = a_box_z.m_width;
bool zlog = a_box_z.m_log;
float xmn = m_x_axis_data.min_value();
float xmx = m_x_axis_data.max_value();
float ymn = m_y_axis_data.min_value();
float ymx = m_y_axis_data.max_value();
clist_contour list_contour;
int nFir = 128;
list_contour.set_first_grid(nFir,nFir); //Default : 32,32
int nSec = 512; //slower than 256
list_contour.set_secondary_grid(nSec,nSec); //Default : 256,256.
double limits[4];
// User limits :
limits[0] = xmn;
limits[1] = xmx;
limits[2] = ymn;
limits[3] = ymx;
SbFunc sbFunc;
sbFunc.m_func2D = &a_func;
sbFunc.m_problem = false;
sbFunc.m_bins2D = 0;
sbFunc.m_limits_in[0] = limits[0];
sbFunc.m_limits_in[1] = limits[1];
sbFunc.m_limits_in[2] = limits[2];
sbFunc.m_limits_in[3] = limits[3];
// Extend the grid to have some borders in order to close contours :
int n = nSec - 2 * 10;
double dx = (limits[1]-limits[0]) /n;
double dy = (limits[3]-limits[2]) /n;
limits[0] = limits[0] - 10 * dx;
limits[1] = limits[1] + 10 * dx;
limits[2] = limits[2] - 10 * dy;
limits[3] = limits[3] + 10 * dy;
sbFunc.m_limits[0] = limits[0];
sbFunc.m_limits[1] = limits[1];
sbFunc.m_limits[2] = limits[2];
sbFunc.m_limits[3] = limits[3];
list_contour.set_limits(limits);
if(levels.getNum()) {
size_t zn = levels.size();
std::vector<double> zs(zn);
for(size_t zi=0;zi<zn;zi++) zs[zi] = levels[zi];
list_contour.set_planes(zs);
} else {
unsigned int zn = number_of_levels;
if(zn<=0) zn = 1;
std::vector<double> zs(zn+1);
float zmax = zmin + dz;
double zd = (zmax-zmin)/zn;
for(unsigned int zi=0;zi<=zn;zi++) zs[zi] = zmin + zi * zd;
list_contour.set_planes(zs);
}
if(zlog) {
list_contour.set_field_fcn(log_function_to_contour,(void*)&sbFunc);
} else {
list_contour.set_field_fcn(function_to_contour,(void*)&sbFunc);
}
list_contour.ccontour::generate();
if(!list_contour.compact_strips ()) {
a_out << "tools::sg::plotter::update_func2D_xy : clist_contour::compact_strips () : failure." << std::endl;
} else {
if( (painting==painting_by_level) || (painting==painting_by_value) ){
m_func_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_data_style.color_mapping.value());
if(zlog) m_func_cmaps[a_index]->set_PAW_coloring();
} else {
m_func_cmaps[a_index] = new const_colormap(a_data_style.color.value());
}
if(modeling==modeling_filled_curve()) {
rep_contour_xy_filled(a_out,a_data_style,
painting,*(m_func_cmaps[a_index]),
list_contour,a_box_x,a_box_y,a_box_z,a_zz /*,std::string(sid.c_str())*/);
} else {
rep_contour_xy(a_out,a_data_style,
painting,*(m_func_cmaps[a_index]),
list_contour,a_box_x,a_box_y,a_box_z,a_zz /*,std::string(sid.c_str())*/);
}
}
if(sbFunc.m_problem) {
a_out << "tools::sg::plotter::update_func2D_xy : problem when getting some function value." << std::endl;
}
} else {
a_out << "tools::sg::plotter::update_func2D_xy :"
<< " modeling " << modeling
<< " does not apply on Functi on2D in XY. Valid modelings ared curve, filled_curve and polygon."
<< std::endl;
}
}
void update_points2D_xy(std::ostream& a_out,const points2D& a_points,const style& a_style,
const rep_box& a_box_x,const rep_box& a_box_y,float a_zz) {
if(!a_style.visible) return;
size_t number = a_points.points();
if(!number) return;
const std::string& modeling = a_style.modeling;
if(modeling==modeling_lines()) {
rep_points2D_xy_lines(a_style,a_points,a_box_x,a_box_y,a_zz);
} else if(modeling==modeling_curve()) {
rep_points2D_xy_curve(a_out,a_style,a_points,a_box_x,a_box_y,a_zz);
} else {
rep_points2D_xy_points(a_out,a_style,a_points,a_box_x,a_box_y,a_zz);
}
}
void update_points3D_xyz(std::ostream& a_out,const points3D& a_points,const style& a_style,
const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z) {
if(!a_style.visible) return;
size_t number = a_points.points();
if(!number) return;
rep_points3D_xyz_points(a_out,a_style,a_points,a_box_x,a_box_y,a_box_z);
}
void get_title(std::string& a_s){
a_s.clear();
bins1D* b1;
bins2D* b2;
func1D* f1;
func2D* f2;
points2D* p2;
points3D* p3;
if(first_bins(b1,b2)) {
if(b1) {
a_s = b1->title();
} else if(b2) {
a_s = b2->title();
}
} else if(first_points(p2,p3)) {
if(p2) {
a_s = p2->title();
} else if(p3) {
a_s = p3->title();
}
} else if(first_func(f1,f2)) {
if(f1) {
a_s = f1->title();
} if(f2) {
a_s = f2->title();
}
}
}
void update_bins2D_xyz(std::ostream& a_out,const bins2D& a_bins,unsigned int a_index,const style& a_style,
const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z){
if(!a_style.visible) return;
unsigned int xnbin = a_bins.x_bins();
unsigned int ynbin = a_bins.y_bins();
if(!xnbin || !ynbin) return;
const std::string& modeling = a_style.modeling;
if(modeling==modeling_boxes()) {
bool hbe = a_bins.has_entries_per_bin();
float bmin = 0;
float bmax = 0;
std::vector<rep_bin2D> bins;
{bool first = true;
for(int jbin=ynbin-1;jbin>=0;jbin--) {
for(int ibin=xnbin-1;ibin>=0;ibin--) {
if(hbe && (a_bins.bin_entries(ibin,jbin)<=0)) continue;
float val = a_bins.bin_Sw(ibin,jbin);
float xx = a_bins.bin_lower_edge_x(ibin);
float xe = a_bins.bin_upper_edge_x(ibin);
float yy = a_bins.bin_lower_edge_y(jbin);
float ye = a_bins.bin_upper_edge_y(jbin);
bins.push_back(rep_bin2D(xx,xe,yy,ye,val,ibin,jbin));
if(first) {
first = false;
bmin = val;
bmax = val;
} else {
bmin = min_of<float>(bmin,val);
bmax = max_of<float>(bmax,val);
}
}
}}
size_t number = bins.size();
painting_policy painting = a_style.painting;
if(painting==painting_by_value) {
m_bins_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_style.color_mapping);
} else if( (painting==painting_grey_scale) ||
(painting==painting_grey_scale_inverse) ||
(painting==painting_violet_to_red) ){
{float dbins = bmax-bmin;
if(dbins!=0.0F) {
for(size_t index=0;index<number;index++) {
bins[index].m_ratio = (bins[index].m_val-bmin)/dbins;
}
}}
if(painting==painting_grey_scale) {
m_bins_cmaps[a_index] = new grey_scale_colormap(bmin,bmax,50);
} else if(painting==painting_grey_scale_inverse) {
m_bins_cmaps[a_index] = new grey_scale_inverse_colormap(bmin,bmax,50);
} else if(painting==painting_violet_to_red) {
m_bins_cmaps[a_index] = new violet_to_red_colormap(bmin,bmax,50);
}
} else {
m_bins_cmaps[a_index] = new const_colormap(a_style.color);
}
rep_bins2D_xyz_box(a_style,*m_bins_cmaps[a_index],bins,a_box_x,a_box_y,a_box_z,bmin,bmax);
} else if(modeling==modeling_curve()){ //gopaw
float bmin = 0;
float bmax = 0;
std::vector<rep_top_face2D> faces((xnbin-1)*(ynbin-1));
{bool first = true;
size_t facei = 0;
unsigned int xnbin_1 = xnbin-1;
unsigned int ynbin_1 = ynbin-1;
for(unsigned int jbin=0;jbin<ynbin_1;jbin++) {
for(unsigned int ibin=0;ibin<xnbin_1;ibin++) {
float xx_0 = a_bins.bin_lower_edge_x(ibin);
float xe_0 = a_bins.bin_upper_edge_x(ibin);
float xx_1 = a_bins.bin_lower_edge_x(ibin+1);
float xe_1 = a_bins.bin_upper_edge_x(ibin+1);
float yy_0 = a_bins.bin_lower_edge_y(jbin);
float ye_0 = a_bins.bin_upper_edge_y(jbin);
float yy_1 = a_bins.bin_lower_edge_y(jbin+1);
float ye_1 = a_bins.bin_upper_edge_y(jbin+1);
float xx = (xx_0+xe_0)/2;
float xe = (xx_1+xe_1)/2;
float yy = (yy_0+ye_0)/2;
float ye = (yy_1+ye_1)/2;
float val1 = a_bins.bin_Sw(ibin,jbin);
float val2 = a_bins.bin_Sw(ibin+1,jbin);
float val3 = a_bins.bin_Sw(ibin+1,jbin+1);
float val4 = a_bins.bin_Sw(ibin,jbin+1);
faces[facei] = rep_top_face2D(xx,xe,yy,ye,val1,val2,val3,val4);
if(first) {
first = false;
bmin = val1;
bmax = val1;
} else {
bmin = min_of<float>(bmin,val1);
bmax = max_of<float>(bmax,val1);
}
facei++;
}
}}
painting_policy painting = a_style.painting;
if((painting==painting_by_value)||(painting==painting_by_level)) {
m_bins_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_style.color_mapping);
} else {
m_bins_cmaps[a_index] = new const_colormap(a_style.color);
}
if(painting==painting_by_level) { //gopaw
rep_top_face2D_xyz_by_level(a_style,painting,*(m_bins_cmaps[a_index]),
faces,a_box_x,a_box_y,a_box_z,
bmin,bmax/*,SbString(sid.c_str())*/);
} else {
bool zlog = a_box_z.m_log;
if(zlog) m_func_cmaps[a_index]->set_PAW_coloring();
rep_top_face2D_xyz(m_bins_sep,a_style,*(m_bins_cmaps[a_index]),faces,a_box_x,a_box_y,a_box_z);
if(a_style.area_style.value()==area_edged) {
style gs;
gs.light_model = light_model_base_color();
gs.line_width = 1;
rep_top_face2D_xyz_line(gs,faces,a_box_x,a_box_y,a_box_z/*,SbString(sid.c_str())*/);
}
if(painting==painting_uniform) { //gopaw SURF3 (s_SURF_CONT).
base_colormap* cmap = new by_value_colormap(a_out,m_cmaps,a_style.color_mapping);
if(cmap->colorn()<=0) {
//a_out << "tools::sg::update_bins2D_xyz : bypass rep_contour_xy_filled." << std::endl;
delete cmap;
} else {
float zmin = a_box_z.m_pos;
float dz = a_box_z.m_width;
float xmn = m_x_axis_data.min_value();
float xmx = m_x_axis_data.max_value();
float ymn = m_y_axis_data.min_value();
float ymx = m_y_axis_data.max_value();
clist_contour list_contour;
int nFir = 128;
list_contour.set_first_grid(nFir,nFir); //Default : 32,32
int nSec = 512;
list_contour.set_secondary_grid(nSec,nSec); //Default : 256,256.
double limits[4];
// User limits :
limits[0] = xmn;
limits[1] = xmx;
limits[2] = ymn;
limits[3] = ymx;
SbFunc sbFunc;
sbFunc.m_func2D = 0;
sbFunc.m_problem = false;
sbFunc.m_bins2D = &a_bins;
sbFunc.m_limits_in[0] = limits[0];
sbFunc.m_limits_in[1] = limits[1];
sbFunc.m_limits_in[2] = limits[2];
sbFunc.m_limits_in[3] = limits[3];
// Extend the grid to have some borders in order to close contours :
int n = nSec - 2 * 10;
double dx = (limits[1]-limits[0]) /n;
double dy = (limits[3]-limits[2]) /n;
limits[0] = limits[0] - 10 * dx;
limits[1] = limits[1] + 10 * dx;
limits[2] = limits[2] - 10 * dy;
limits[3] = limits[3] + 10 * dy;
sbFunc.m_limits[0] = limits[0];
sbFunc.m_limits[1] = limits[1];
sbFunc.m_limits[2] = limits[2];
sbFunc.m_limits[3] = limits[3];
list_contour.set_limits(limits);
size_t zn = cmap->colorn();
if(zn<=0) zn = 1;
std::vector<double> zs(zn+1);
float zmax = zmin + dz;
double zd = (zmax-zmin)/zn;
for(size_t zi=0;zi<=zn;zi++) zs[zi] = zmin + zi * zd;
list_contour.set_planes(zs);
if(zlog) list_contour.set_field_fcn(log_bins2D_to_contour,(void*)&sbFunc);
else list_contour.set_field_fcn(bins2D_to_contour,(void*)&sbFunc);
list_contour.ccontour::generate();
if(!list_contour.compact_strips ()) {
a_out << "tools::sg::plotter::update_bins2D_xyz : clist_contour::compact_strips () : failure." << std::endl;
delete cmap;
} else {
delete m_bins_cmaps[a_index];
m_bins_cmaps[a_index] = cmap; //to visualize the cmap.
matrix* transf = new matrix;
//contour back is at ZZ - 0.01F;
transf->set_translate(0,0,1.02F);
transf->mul_scale(1,1,0.01F); //applied first.
m_bins_sep.add(transf);
style gs;
gs.light_model = light_model_base_color();
//FIXME gs.transparency = 0.3F;
float ZZ = 0.0F;
rep_contour_xy_filled(a_out,gs,painting_by_level,*cmap,list_contour,
a_box_x,a_box_y,a_box_z,ZZ/*,SbString(sid.c_str())*/);
}
}
} //uniform
}
} //end if modeling
}
void update_func2D_xyz(std::ostream& a_out,
const func2D& a_func,
unsigned int a_index,
const style& a_style,
const rep_box& a_box_x,
const rep_box& a_box_y,
const rep_box& a_box_z){
if(!a_style.visible) return;
float xmn = m_x_axis_data.min_value();
float xmx = m_x_axis_data.max_value();
unsigned int nx = a_func.x_steps();
nx = !nx?20:nx;
float ymn = m_y_axis_data.min_value();
float ymx = m_y_axis_data.max_value();
unsigned int ny = a_func.y_steps();
ny = !ny?20:ny;
float dfx = (xmx - xmn)/nx;
float dfy = (ymx - ymn)/ny;
std::vector<rep_top_face2D> faces(nx*ny);
{bool problem = false;
unsigned int facei = 0;
float* vprev = new float[2*nx];
for(int jbin=ny-1;jbin>=0;jbin--) {
float o1 = 0;
float o4 = 0;
for(int ibin=nx-1;ibin>=0;ibin--) {
float xx = xmn + ibin * dfx;
float yy = ymn + jbin * dfy;
float xe = xx + dfx;
float ye = yy + dfy;
// Values at the corner :
float val1;
if(!a_func.value(xx,yy,val1)) problem = true;
float val2;
if(ibin==int(nx-1)) {
if(!a_func.value(xe,yy,val2)) problem = true;
} else {
val2 = o1;
}
float val3,val4;
if(jbin==int(ny-1)) {
if(ibin==int(nx-1)) {
if(!a_func.value(xe,ye,val3)) problem = true;
} else {
val3 = o4;
}
if(!a_func.value(xx,ye,val4)) problem = true;
} else {
val3 = vprev[2*ibin+1];
val4 = vprev[2*ibin];
}
vprev[2*ibin] = val1;
vprev[2*ibin+1] = val2;
o4 = val4;
o1 = val1;
faces[facei] = rep_top_face2D(xx,xe,yy,ye,val1,val2,val3,val4);
facei++;
}
}
delete [] vprev;
if(problem) {
a_out << "tools::sg::plotter::update_func2D_xyz :"
<< " problem when getting some function value."
<< std::endl;
}}
painting_policy painting = a_style.painting;
if(painting==painting_by_value) {
m_func_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_style.color_mapping);
} else if( (painting==painting_grey_scale) ||
(painting==painting_grey_scale_inverse) ||
(painting==painting_violet_to_red) ){
float vmin = faces[0].m_v1;
float vmax = faces[0].m_v1;
size_t number = faces.size();
for(size_t index=0;index<number;index++) {
float vmean = faces[index].m_v1;
vmean += faces[index].m_v2;
vmean += faces[index].m_v3;
vmean += faces[index].m_v4;
vmean /= 4.0f;
vmin = min_of<float>(vmin,vmean);
vmax = max_of<float>(vmax,vmean);
faces[index].m_ratio = vmean;
}
{float dbins = vmax-vmin;
if(dbins!=0.0F) {
for(size_t index=0;index<number;index++) {
faces[index].m_ratio = (faces[index].m_ratio-vmin)/dbins;
}
}}
if(painting==painting_grey_scale) {
m_func_cmaps[a_index] = new grey_scale_colormap(vmin,vmax,50);
} else if(painting==painting_grey_scale_inverse) {
m_func_cmaps[a_index] = new grey_scale_inverse_colormap(vmin,vmax,50);
} else if(painting==painting_violet_to_red) {
m_func_cmaps[a_index] = new violet_to_red_colormap(vmin,vmax,50);
}
} else {
m_func_cmaps[a_index] = new const_colormap(a_style.color);
}
{
bool zlog = a_box_z.m_log;
if(zlog) m_func_cmaps[a_index]->set_PAW_coloring();
rep_top_face2D_xyz(m_func_sep,a_style,*(m_func_cmaps[a_index]),faces,a_box_x,a_box_y,a_box_z);
}
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
float zmin = a_box_z.m_pos;
float dz = a_box_z.m_width;
bool zlog = a_box_z.m_log;
if(func2D_borders_visible.value()) {
// border X (Y=0)
{separator* sep = new separator;
{normal* nm = new normal;
nm->vec = vec3f(0,-1,0);
sep->add(nm);}
{rgba* mat = new rgba();
mat->color = colorf(0.6f,0.2f,0.2f); //brown
sep->add(mat);}
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
sep->add(vtxs);
bool empty = true;
bool problem = false;
{float xx = xmn;
float yy = ymn;
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
vtxs->add(xx,yy,0);}
{float xx = xmx;
float yy = ymn;
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
vtxs->add(xx,yy,0);}
{float val;
{if(!a_func.value(xmx,ymn,val)) problem = true;
val = verify_log(val,zmin,dz,zlog);
if(val<0) val = 0;
if(val>1) val = 1;}
{float xx = xmx;
float yy = ymn;
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
vtxs->add(xx,yy,val);}}
for(int ibin=nx-1;ibin>=0;ibin--) {
float xx = xmn + ibin * dfx;
float yy = ymn;
float val;
{if(!a_func.value(xx,yy,val)) problem = true;
val = verify_log(val,zmin,dz,zlog);
if(val<0) val = 0;
if(val>1) val = 1;}
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
if((xx>=0)&&(xx<=1) && (yy>=0)&&(yy<=1) ) {
vtxs->add(xx,yy,val);
empty = false;
}
}
if(empty) {
delete sep;
} else {
m_func_sep.add(sep);
}
if(problem) {
a_out << "tools::sg::plotter::update_func2D_xyz :"
<< " problem when getting some function value."
<< std::endl;
}}
// border Y (X=0)
{separator* sep = new separator;
{normal* nm = new normal;
nm->vec = vec3f(-1,0,0);
sep->add(nm);}
{rgba* mat = new rgba();
mat->color = colorf(0.6f,0.2f,0.2f); //brown
sep->add(mat);}
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
sep->add(vtxs);
{float xx = xmn;
float yy = ymx;
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
vtxs->add(xx,yy,0);}
{float xx = xmn;
float yy = ymn;
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
vtxs->add(xx,yy,0);}
bool empty = true;
bool problem = false;
for(unsigned int jbin=0;jbin<ny;jbin++) {
float xx = xmn;
float yy = ymn + jbin * dfy;
float val;
{if(!a_func.value(xx,yy,val)) problem = true;
val = verify_log(val,zmin,dz,zlog);
if(val<0) val = 0;
if(val>1) val = 1;}
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
if((xx>=0)&&(xx<=1) &&
(yy>=0)&&(yy<=1) ){
vtxs->add(xx,yy,val);
empty = false;
}
}
{float val;
{if(!a_func.value(xmn,ymx,val)) problem = true;
val = verify_log(val,zmin,dz,zlog);
if(val<0) val = 0;
if(val>1) val = 1;}
{float xx = xmn;
float yy = ymx;
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
vtxs->add(xx,yy,val);}}
if(empty) {
delete sep;
} else {
m_func_sep.add(sep);
}
if(problem) {
a_out << "tools::sg::plotter::update_func2D_xyz :"
<< " problem when getting some function value."
<< std::endl;
}}
} //func2D_borders_visible
}
void update_title(){
if(!m_title_style.visible) return;
if(m_shape==xyz) return;
if(title.value().empty()) return;
// Use the XY layout transform to position the title.
// (Else we would have to compensate the 3D rotation
// in order to bring the title at the right position
// without rotation).
//titleNode->addChild(layout);
rgba* mat = new rgba();
mat->color = m_title_style.color;
m_title_sep.add(mat);
float text_size = title_height * m_title_style.scale;
std::string font = m_title_style.font.value();
if(font==font_hershey()) {
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = m_title_style.line_pattern;
ds->line_width = m_title_style.line_width;
m_title_sep.add(ds);
} else {
m_title_sep.add(new normal);
}
float XSIZ = width;
float XMGL = left_margin;
float XMGR = right_margin;
float wData = XSIZ-XMGL-XMGR;
float YSIZ = height;
float YMGL = bottom_margin;
float YMGU = top_margin;
float hData = YSIZ-YMGL-YMGU;
float xx = wData/2;
float yy = hData + title_to_axis;
float zz = _zinfos();
vjust vjust = bottom;
if(!title_up) {
yy = -title_to_axis;
vjust = top;
}
vec3f TX(1,0,0);
vec3f TY(0,1,0);
add_string(m_title_sep,
font,
m_title_style.font_modeling.value(),
m_title_style.encoding.value(),
m_title_style.smoothing,
title.value(),
xx,yy,zz, //vec
TX,TY,
text_size,
title_hjust,vjust,
m_ttf);
}
void update_title_box(){
if(!m_title_box_style.visible) return;
if(title.value().empty()) return;
// same plane than infos, then in front of data and grid.
float zz = _zinfos();
if(m_shape==xyz) zz = depth*0.5f;
float wbox = width*title_box_width;
float hbox = height*title_box_height;
float xmargin = width*title_box_x_margin; //from left border
float ymargin = height*title_box_y_margin; //from top border
matrix* _tsf = new matrix;
{float xx = -width*0.5f+wbox*0.5f+xmargin; //at left.
float yy = height*0.5f-hbox*0.5F-ymargin; //at top.
_tsf->set_translate(xx,yy,zz);
_tsf->mul_scale(1,1,_zscale_text());}
m_title_box_sep.add(_tsf);
sg::text* title_box = new sg::text(m_ttf);
title_box->width = wbox;
title_box->height = hbox;
title_box->back_area::color = m_title_box_style.back_color;
title_box->color = m_title_box_style.color;
title_box->font = m_title_box_style.font;
title_box->font_modeling = m_title_box_style.font_modeling;
title_box->encoding = m_title_box_style.encoding;
title_box->line_width = m_title_box_style.line_width;
title_box->confine = true;
title_box->back_area::shadow = m_title_box_style.back_shadow;
title_box->strings.add(title.value());
m_title_box_sep.add(title_box);
}
void get_infos(std::string& a_s){
a_s.clear();
const std::string& opts = infos_what.value();
{bins1D* b1;
bins2D* b2;
func1D* f1;
func2D* f2;
points2D* p2;
points3D* p3;
if(first_bins(b1,b2)) {
if(b1) {
b1->infos(opts,a_s);
} else if(b2) {
b2->infos(opts,a_s);
}
} else if(first_points(p2,p3)) {
if(p2) {
p2->infos(opts,a_s);
} else if(p3) {
p3->infos(opts,a_s);
}
} else if(first_func(f1,f2)) {
if(f1) {
f1->infos(opts,a_s);
} if(f2) {
f2->infos(opts,a_s);
}
}}
//look for fit infos :
{tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(object->cast(s_tools_sg_fit2plot())) {
if(a_s.size()) a_s += "\n";
std::string _s;
object->infos(opts,_s);
a_s += _s;
}
}}
}
matrix* get_infos_matrix() {
if(m_infos_sep.empty()) return 0;
return (matrix*)m_infos_sep[0]; //WARNING.
}
sg::infos_box* get_infos_node() {
if(m_infos_sep.empty()) return 0;
return (sg::infos_box*)m_infos_sep[1]; //WARNING.
}
void update_infos(std::ostream&){
if(!m_infos_style.visible) return;
std::string sinfos;
get_infos(sinfos);
std::vector<std::string> ws;
words(sinfos,"\n",false,ws);
size_t linen = ws.size()/2;
float zz = _zinfos(); //xy
if(m_shape==xyz) zz = depth*0.5f;
float _height = height;
if(m_shape==xyz) _height = depth;
float wbox = width*infos_width;
matrix* infos_title_tsf = 0;
sg::text* infos_title_text = 0;
std::string infos_title;
if(m_infos_style.modeling==infos_modeling_ROOT()) {
std::vector<std::string> _ws; //to rm "Name".
for(size_t index=0;index<linen;index++) {
const std::string& name = ws[2*index];
const std::string& value = ws[2*index+1];
if(name=="Name") {
infos_title = value;
} else {
_ws.push_back(name);
_ws.push_back(value);
}
}
ws = std::move(_ws);
linen = ws.size()/2;
}
if(infos_title.size()) {
float hbox = _height*0.05f;
matrix* _tsf = new matrix;
{float xx = width*0.5f - wbox*0.5f - width*infos_x_margin;
float yy = _height*0.5f - hbox*0.5F - _height*infos_y_margin;
_tsf->mul_translate(xx,yy,zz);
_tsf->mul_scale(1,1,_zscale_text());}
//in case of having infos, the tsf is refined below.
m_infos_title_sep.add(_tsf);
// same params as title_box.
sg::text* txt = new sg::text(m_ttf);
txt->width = wbox;
txt->height = hbox;
txt->back_area::color = m_infos_style.back_color;
txt->color = m_infos_style.color;
txt->font = m_infos_style.font;
txt->font_modeling = m_infos_style.font_modeling;
txt->encoding = m_infos_style.encoding;
txt->line_width = m_infos_style.line_width;
txt->confine = true;
txt->back_area::shadow = m_infos_style.back_shadow;
txt->hjust = center;
txt->strings.add(infos_title);
m_infos_title_sep.add(txt);
// to refine height below.
infos_title_tsf = _tsf;
infos_title_text = txt;
}
if(sinfos.empty()) return;
if(!linen) return;
matrix* _tsf = new matrix;
m_infos_sep.add(_tsf);
sg::infos_box* infos = new sg::infos_box(m_ttf);
infos->width = wbox;
infos->back_area::color = m_infos_style.back_color;
infos->color = m_infos_style.color;
infos->font = m_infos_style.font;
infos->encoding = m_infos_style.encoding;
infos->font_modeling = m_infos_style.font_modeling;
infos->line_width = m_infos_style.line_width;
infos->back_area::shadow = m_infos_style.back_shadow;
infos->border_line_width = m_infos_style.line_width;
{for(size_t index=0;index<linen;index++) {
const std::string& name = ws[2*index];
const std::string& value = ws[2*index+1];
infos->lstrings.add(name);
infos->rstrings.add(value);
}}
// enforce an infos::update_sg to get infos::height
// to place the box.
infos->update_sg();
// if any, set infos_title height :
float title_hbox = 0;
if(infos_title_tsf && infos_title_text) {
title_hbox = infos->height/linen;
float xx = width*0.5f - wbox*0.5f - width*infos_x_margin;
float yy = _height*0.5f - title_hbox*0.5F - _height*infos_y_margin;
infos_title_tsf->set_identity();
infos_title_tsf->mul_translate(xx,yy,zz);
infos_title_tsf->mul_scale(1,1,_zscale_text());
infos_title_text->height = title_hbox;
}
float hbox = infos->height;
{float xx = width*0.5f -wbox*0.5f -width*infos_x_margin;
float yy = _height*0.5f -hbox*0.5F - _height*infos_y_margin;
yy -= title_hbox;
_tsf->set_translate(xx,yy,zz);
_tsf->mul_scale(1,1,_zscale_text());}
m_infos_sep.add(infos);
}
void update_legends(std::ostream& a_out) {
if(m_legend_strings.empty()) return;
if(m_legend_strings.size()!=legends_origin.size()) return;
if(legends_size.size()!=legends_origin.size()) return;
if(legends_origin_unit.size()!=legends_origin.size()) return;
float zz = _zinfos();
{matrix* _tsf = new matrix;
_tsf->mul_scale(1,1,_zscale_text());
m_legend_sep.add(_tsf);}
size_t number = m_legend_strings.size();
for(size_t index=0;index<number;index++) {
const style& _style = legend_style(index);
if(!_style.visible) continue;
separator* sep = new separator;
m_legend_sep.add(sep);
matrix* _tsf = new matrix;
sep->add(_tsf);
legend* text = new legend(m_ttf);
text->font = _style.font;
text->font_modeling = _style.font_modeling;
text->encoding = _style.encoding;
text->strings.add(m_legend_strings[index]);
text->color = _style.color;
text->marker_style = _style.marker_style;
text->marker_size = _style.marker_size;
text->back_visible = false;
sep->add(text);
//legends_size is in NDC of [0,width][0,height].
float w = width * legends_size[index][0];
float h = height * legends_size[index][1];
text->width = w;
text->height = h;
float xxx = w * 0.5f;
float yyy = h * 0.5f;
if(legends_origin_unit[index]==unit_axis) {
// legends_origin is in axes coordinates.
float x = legends_origin[index][0];
float y = legends_origin[index][1];
vec3f pos;
if(!axis_2_vp(vec3f(x,y,0),pos)) {
a_out << "tools::sg::plotter::update_legends : axis_2_vp() failed for x=" << x << ", y=" << y << "." << std::endl;
} else {
//pos is in NDC of [0,width][0,height].
float xx = width * (-0.5f+pos[0]);
float yy = height * (-0.5f+pos[1]);
_tsf->set_translate(xx,yy,zz);
}
} else { //unit_percent
// legends_origin is
// the UR corner of legend region relative
// to UR of plotter region.
float xur = legends_origin[index][0];
float yur = legends_origin[index][1];
vec2f ur(1-xur,1-yur);
float x = width*ur[0] - w;
float y = height*ur[1] - h;
float xx = -width*0.5f + x;
float yy = -height*0.5f + y;
_tsf->set_translate(xx,yy,zz);
}
_tsf->mul_translate(xxx,yyy,0); //applied first.
}
}
void update_background(){
m_background_sep.clear();
if(!m_background_style.visible) return;
matrix* _tsf = new matrix;
m_background_sep.add(_tsf);
float w2 = width*0.5F;
float h2 = height*0.5F;
float zz = 0; //in xy, then before first data plane at _zoffset()
if(m_shape==xyz) zz = -depth*0.5f;
{rgba* mat = new rgba();
if(m_background_style.line_width) { //there is a border.
mat->color = m_background_style.color; //then border color !
} else {
mat->color = m_background_style.back_color;
}
m_background_sep.add(mat);
m_background_sep.add(new normal);
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
m_background_sep.add(vtxs);
vtxs->add(-w2,-h2,zz);
vtxs->add( w2,-h2,zz);
vtxs->add( w2, h2,zz);
vtxs->add(-w2, h2,zz);}
if(m_background_style.line_width) { //border
//WARNING : line_width should be in percent of width.
//NOTE : border is done by drawing a front smaller polygon.
rgba* mat = new rgba();
mat->color = m_background_style.back_color; //yes,yes !
m_background_sep.add(mat);
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
m_background_sep.add(vtxs);
float d = width*m_background_style.line_width;
zz += _zoffset()*0.5f;
vtxs->add(-w2+d,-h2+d,zz);
vtxs->add( w2-d,-h2+d,zz);
vtxs->add( w2-d, h2-d,zz);
vtxs->add(-w2+d, h2-d,zz);
}
}
void update_inner_frame_XY(){
if(!m_inner_frame_style.visible) return;
rgba* mat = new rgba();
mat->color = m_inner_frame_style.color;
m_inner_frame_sep.add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = m_inner_frame_style.line_pattern;
ds->line_width = m_inner_frame_style.line_width;
m_inner_frame_sep.add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::line_strip();
m_inner_frame_sep.add(vtxs);
float zz = _zgrid();
vtxs->add(0,0,zz);
vtxs->add(1,0,zz);
vtxs->add(1,1,zz);
vtxs->add(0,1,zz);
vtxs->add(0,0,zz);
}
void update_inner_frame_XYZ(){
if(!m_inner_frame_style.visible) return;
rgba* mat = new rgba();
mat->color = m_inner_frame_style.color;
m_inner_frame_sep.add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = m_inner_frame_style.line_pattern;
ds->line_width = m_inner_frame_style.line_width;
m_inner_frame_sep.add(ds);
vertices* ls = new vertices;
ls->mode = gl::lines();
m_inner_frame_sep.add(ls);
// z bottom :
ls->add(0,0,0);ls->add(1,0,0);
ls->add(1,0,0);ls->add(1,1,0);
ls->add(1,1,0);ls->add(0,1,0);
ls->add(0,1,0);ls->add(0,0,0);
// z top :
ls->add(0,0,1);ls->add(1,0,1);
ls->add(1,0,1);ls->add(1,1,1);
ls->add(1,1,1);ls->add(0,1,1);
ls->add(0,1,1);ls->add(0,0,1);
// sides along z :
ls->add(0,0,0);ls->add(0,0,1);
ls->add(1,0,0);ls->add(1,0,1);
ls->add(1,1,0);ls->add(1,1,1);
ls->add(0,1,0);ls->add(0,1,1);
}
void update_grid_XY(){
if(!m_grid_style.visible) return;
unsigned int number = m_x_axis.tick_number + m_y_axis.tick_number;
if(number<=0) return;
bool draw_vertical = true;
bool draw_horizontal = true;
if(m_grid_style.options.value()=="vertical") draw_horizontal = false;
if(m_grid_style.options.value()=="horizontal") draw_vertical = false;
rgba* mat = new rgba();
mat->color = m_grid_style.color;
m_grid_sep.add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = line_solid;
ds->line_width = m_grid_style.line_width;
m_grid_sep.add(ds);
float zz = _zgrid();
vertices* vtxs = new vertices;
vtxs->mode = gl::lines();
m_grid_sep.add(vtxs);
std::vector<float>& pts = vtxs->xyzs.values();
bool is_solid = m_grid_style.line_pattern.value()==line_solid;
if(draw_vertical) {
float _width = m_y_axis.width;
float xx;
{size_t _number = m_x_axis.coords.size();
if(is_solid) {
pts.reserve(_number*6);
for(size_t count=0;count<_number;count++) {
xx = m_x_axis.coords[count];
vtxs->add(xx, 0 ,zz);
vtxs->add(xx, _width,zz);
}
} else {
pts.reserve(_number*100*6);
for(size_t count=0;count<_number;count++) {
xx = m_x_axis.coords[count];
vtxs->add_dashed_line(xx,0,zz,xx,_width,zz,100);
}
}}
if(m_x_axis.is_log) {
size_t _number = m_x_axis.sub_coords.size();
if(is_solid) {
pts.reserve(_number*6);
for(size_t count=0;count<_number;count++) {
xx = m_x_axis.sub_coords[count];
vtxs->add(xx, 0 ,zz);
vtxs->add(xx,_width,zz);
}
} else {
pts.reserve(_number*100*6);
for(size_t count=0;count<_number;count++) {
xx = m_x_axis.sub_coords[count];
vtxs->add_dashed_line(xx,0,zz,xx,_width,zz,100);
}
}
}
}
if(draw_horizontal) {
float _width = m_x_axis.width;
float yy;
{size_t _number = m_y_axis.coords.size();
if(is_solid) {
pts.reserve(_number*6);
for(size_t count=0;count<_number;count++) {
yy = m_y_axis.coords[count];
vtxs->add(0,yy ,zz);
vtxs->add(_width,yy,zz);
}
} else {
pts.reserve(_number*100*6);
for(size_t count=0;count<_number;count++) {
yy = m_y_axis.coords[count];
vtxs->add_dashed_line(0,yy,zz,_width,yy,zz,100);
}
}}
if(m_y_axis.is_log) {
size_t _number = m_y_axis.sub_coords.size();
if(is_solid) {
pts.reserve(_number*6);
for(size_t count=0;count<_number;count++) {
yy = m_y_axis.sub_coords[count];
vtxs->add(0,yy, zz);
vtxs->add(_width,yy,zz);
}
} else {
pts.reserve(_number*100*6);
for(size_t count=0;count<_number;count++) {
yy = m_y_axis.sub_coords[count];
vtxs->add_dashed_line(0,yy,zz,_width,yy,zz,100);
}
}
}
}
}
void update_grid_XYZ(){
if(!m_grid_style.visible) return;
rgba* mat = new rgba();
mat->color = m_grid_style.color;
m_grid_sep.add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = m_grid_style.line_pattern;
ds->line_width = m_grid_style.line_width;
m_grid_sep.add(ds);
}
protected: //rep
////////////////////////////////////////////////////////////////////////////
// reps xy /////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
void rep_bins1D_xy_top_lines(const style& a_style,
const base_colormap& a_cmap,
const std::vector<rep_bin1D>& a_bins,
const rep_box& a_box_x,
const rep_box& a_box_y,
float a_zz/*,
const std::string& aID*/){
painting_policy painting = a_style.painting;
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
float y0 = 0;
y0 = verify_log(y0,ymin,dy,ylog);
if(y0<0) y0 = 0;
if(y0>1) y0 = 1;
separator* _sep = new separator();
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = a_style.line_pattern;
ds->line_width = a_style.line_width;
_sep->add(ds);
bool empty = true;
colorf clr;
float yp = 0;
size_t xnbin = a_bins.size();
for(size_t index=0;index<xnbin;index++) {
float xx = a_bins[index].m_x_min;
float xe = a_bins[index].m_x_max;
float y = a_bins[index].m_val;
float val = a_bins[index].m_val;
xx = verify_log(xx,xmin,dx,xlog);
xe = verify_log(xe,xmin,dx,xlog);
y = verify_log(y,ymin,dy,ylog);
// Clipping :
if(xe<0) continue;
if(xx>1) continue;
if(xx<0) xx = 0;
if(xe>1) xe = 1;
if(y<0) y = 0;
if(y>1) y = 1;
separator* sep = new separator();
_sep->add(sep);
if(painting==painting_by_value) {
a_cmap.get_color(val,clr);
} else if( (painting==painting_grey_scale) ||
(painting==painting_grey_scale_inverse) ||
(painting==painting_violet_to_red) ){
a_cmap.get_color(a_bins[index].m_ratio,clr);
} else {
clr = a_style.color;
}
rgba* mat = new rgba();
mat->color = clr;
sep->add(mat);
vertices* vtxs = new vertices;
vtxs->mode = gl::line_strip();
sep->add(vtxs);
vtxs->add(xx,yp,a_zz);
vtxs->add(xx,y,a_zz);
vtxs->add(xe,y,a_zz);
if(index==xnbin-1){
vtxs->add(xe,y0,a_zz);
}
empty = false;
yp = y;
}
if(empty) {
delete _sep;
} else {
m_bins_sep.add(_sep);
}
}
void rep_bins1D_xy_points(std::ostream& a_out,
const style& a_style,
const base_colormap& a_cmap,
const std::vector<rep_bin1D>& a_bins,
const rep_box& a_box_x,
const rep_box& a_box_y,
float a_zz/*,
const std::string& aID*/){
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
painting_policy painting = a_style.painting;
separator* _sep = new separator();
if(a_style.modeling==modeling_points()) {
draw_style* ds = new draw_style;
ds->style = draw_points;
ds->point_size = a_style.point_size;
_sep->add(ds);
}
bool empty = true;
colorf clr;
size_t xnbin = a_bins.size();
for(size_t index=0;index<xnbin;index++) {
float x = (a_bins[index].m_x_min + a_bins[index].m_x_max)/2;
float y = a_bins[index].m_val;
float val = a_bins[index].m_val;
x = verify_log(x,xmin,dx,xlog);
y = verify_log(y,ymin,dy,ylog);
if((x<0)||(x>1)||(y<0)||(y>1)) continue;
separator* sep = new separator();
_sep->add(sep);
if(painting==painting_by_value) {
a_cmap.get_color(val,clr);
} else if( (painting==painting_grey_scale) ||
(painting==painting_grey_scale_inverse) ||
(painting==painting_violet_to_red) ){
a_cmap.get_color(a_bins[index].m_ratio,clr);
} else {
clr = a_style.color;
}
rgba* mat = new rgba();
mat->color = clr;
sep->add(mat);
if(a_style.modeling==modeling_points()) {
vertices* vtxs = new vertices;
vtxs->mode = gl::points();
vtxs->add(x,y,a_zz);
sep->add(vtxs);
} else if(a_style.modeling==modeling_markers()) {
markers* _marks = new markers;
_marks->size = a_style.marker_size;
_marks->style = a_style.marker_style;
_marks->add(x,y,a_zz);
sep->add(_marks);
} else {
a_out << "tools::sg::plotter::rep_bins1D_xy_points :"
<< " bad modeling style " << tools::sout(a_style.modeling) << std::endl;
delete _sep;
return;
}
empty = false;
}
if(empty) {
delete _sep;
} else {
m_bins_sep.add(_sep);
}
}
void rep_bins1D_xy_boxes(const style& a_style,
const base_colormap& a_cmap,
const std::vector<rep_bin1D>& a_bins,
const rep_box& a_box_x,
const rep_box& a_box_y,
float a_zz //,const std::string& aID
){
painting_policy painting = a_style.painting;
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
separator* _sep = new separator();
_sep->add(new normal);
bool empty = true;
colorf clr;
tools_vforcit(rep_bin1D,a_bins,it) {
const rep_bin1D& rbin = *it;
float xx = rbin.m_x_min;
float xe = rbin.m_x_max;
float yy = rbin.m_v_min;
float ye = rbin.m_val;
if(ye<yy) {
yy = rbin.m_val;
ye = rbin.m_v_min;
}
float val = rbin.m_val;
xx = verify_log(xx,xmin,dx,xlog);
xe = verify_log(xe,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
ye = verify_log(ye,ymin,dy,ylog);
// Clipping :
if(xx>1) continue;
if(xe<0) continue;
if(xx<0) xx = 0;
if(xe>1) xe = 1;
if(yy>1) continue;
if(ye<0) continue;
if(yy<0) yy = 0;
if(ye>1) ye = 1;
//FIXME if(ye<=yy) continue; //Else we shall have a tessellation error.
separator* sep = new separator();
_sep->add(sep);
if(painting==painting_by_value) {
a_cmap.get_color(val,clr);
} else if( (painting==painting_grey_scale) ||
(painting==painting_grey_scale_inverse) ||
(painting==painting_violet_to_red) ){
a_cmap.get_color(rbin.m_ratio,clr);
} else {
clr = a_style.color;
}
rgba* mat = new rgba();
mat->color = clr;
sep->add(mat);
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
sep->add(vtxs);
vtxs->add(xx,yy,a_zz);
vtxs->add(xe,yy,a_zz);
vtxs->add(xe,ye,a_zz);
vtxs->add(xx,ye,a_zz);
empty = false;
}
if(empty) {
delete _sep;
} else {
m_bins_sep.add(_sep);
}
}
void rep_bins1D_xy_wire_boxes(const style& a_style,
const base_colormap& a_cmap,
const std::vector<rep_bin1D>& a_bins,
const rep_box& a_box_x,const rep_box& a_box_y,
float a_zz,
bool a_bar_chart/*,
const std::string& aID*/){
painting_policy painting = a_style.painting;
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
separator* _sep = new separator();
bool empty = true;
colorf clr;
tools_vforcit(rep_bin1D,a_bins,it) {
const rep_bin1D& rbin = *it;
float xx = rbin.m_x_min;
float xe = rbin.m_x_max;
float yy = rbin.m_v_min;
float ye = rbin.m_val;
if(ye<yy) {
yy = rbin.m_val;
ye = rbin.m_v_min;
}
float val = rbin.m_val;
if(a_bar_chart) {
bar_chart(a_style.bar_offset.value(),
a_style.bar_width.value(),xx,xe);
}
xx = verify_log(xx,xmin,dx,xlog);
xe = verify_log(xe,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
ye = verify_log(ye,ymin,dy,ylog);
// Clipping :
if(xx>1) continue;
if(xe<0) continue;
if(xx<0) xx = 0;
if(xe>1) xe = 1;
if(yy>1) continue;
if(ye<0) continue;
if(yy<0) yy = 0;
if(ye>1) ye = 1;
separator* sep = new separator();
_sep->add(sep);
if(painting==painting_by_value) {
a_cmap.get_color(val,clr);
} else if( (painting==painting_grey_scale) ||
(painting==painting_grey_scale_inverse) ||
(painting==painting_violet_to_red) ){
a_cmap.get_color(rbin.m_ratio,clr);
} else {
clr = a_style.color;
}
rgba* mat = new rgba();
mat->color = clr;
sep->add(mat);
vertices* vtxs = new vertices;
vtxs->mode = gl::line_strip();
sep->add(vtxs);
vtxs->add(xx,yy,a_zz);
vtxs->add(xe,yy,a_zz);
vtxs->add(xe,ye,a_zz);
vtxs->add(xx,ye,a_zz);
vtxs->add(xx,yy,a_zz);
empty = false;
}
if(empty) {
delete _sep;
} else {
m_bins_sep.add(_sep);
}
}
void rep_bins1D_xy_lines_one(const style& a_style,const std::vector<rep_bin1D>& a_bins,
const rep_box& a_box_x,const rep_box& a_box_y,float a_zz/*,const SbString& aID*/) {
// Draw lines connecting top middle of bins.
size_t xnbin = a_bins.size();
std::vector<vec3f> points(xnbin);
for(size_t index=0;index<xnbin;index++) {
float x = (a_bins[index].m_x_min + a_bins[index].m_x_max)/2;
float y = a_bins[index].m_val;
points[index] = vec3f(x,y,a_zz);
}
vertices* vtxs = new vertices;
std::vector<float>& pts = vtxs->xyzs.values(); //npt*3
clip_polyline_2D(points,a_box_x,a_box_y,pts);
if(pts.size()) {
sg::separator* separator = new sg::separator;
rgba* mat = new rgba();
mat->color = a_style.color;
separator->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = a_style.line_pattern;
ds->line_width = a_style.line_width;
separator->add(ds);
vtxs->mode = gl::line_strip();
separator->add(vtxs);
m_bins_sep.add(separator);
} else {
delete vtxs;
}
}
void rep_bins1D_xy_curve_one(std::ostream& a_out,const style& a_style,const std::vector<rep_bin1D>& a_bins,
const rep_box& a_box_x,const rep_box& a_box_y,float a_zz/*,const SbString& aID*/){
size_t number = a_bins.size();
if(!number) return;
double* xs = new double[number];
double* ys = new double[number];
float x,y;
for(size_t index=0;index<number;index++) {
x = (a_bins[index].m_x_min + a_bins[index].m_x_max)/2;
y = a_bins[index].m_val;
xs[index] = x;ys[index] = y;
}
spline::cubic _spline(a_out,number,xs,ys);
delete [] xs;delete [] ys;
float xmn = m_x_axis_data.min_value();
float xmx = m_x_axis_data.max_value();
unsigned int nstp = curve_number_of_points;
float step = (xmx - xmn)/nstp;
std::vector<vec3f> points(nstp+1);
for(unsigned int ibin=0;ibin<=nstp;ibin++) {
float xx = xmn + ibin * step;
double val = _spline.eval(xx);
points[ibin].set_value(xx,float(val),a_zz);
}
vertices* vtxs = new vertices;
std::vector<float>& pts = vtxs->xyzs.values(); //npt*3
clip_polyline_2D(points,a_box_x,a_box_y,pts);
if(pts.size()) {
sg::separator* separator = new sg::separator;
rgba* mat = new rgba();
mat->color = a_style.color;
separator->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = a_style.line_pattern;
ds->line_width = a_style.line_width;
separator->add(ds);
vtxs->mode = gl::line_strip();
separator->add(vtxs);
m_bins_sep.add(separator);
} else {
delete vtxs;
}
}
void rep_bins2D_xy_box(const style& a_style,const std::vector<rep_bin2D>& a_bins,
const rep_box& a_box_x,const rep_box& a_box_y,float a_bmin,float a_bmax,float a_zz) {
// Draw box of size proportionnal to bin value.
separator* _sep = new separator();
_sep->add(new normal);
rgba* mat = new rgba();
mat->color = a_style.color;
_sep->add(mat);
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
bool empty = true;
float range = a_bmax - a_bmin;
tools_vforcit(rep_bin2D,a_bins,it) {
const rep_bin2D& rbin = *it;
float xx = rbin.m_x_min;
float xe = rbin.m_x_max;
float yy = rbin.m_y_min;
float ye = rbin.m_y_max;
float val = rbin.m_val;
float xsize,ysize;
if(range>0) {
// If val = bmax, the box maps the cell.
xsize = (val - a_bmin) * (xe - xx) / range;
ysize = (val - a_bmin) * (ye - yy) / range;
} else {
//If range is 0. ; then all bins that have
// entries have same values. Draw box xdbin * ydbin.
xsize = xe - xx;
ysize = ye - yy;
}
xx = xx + ((xe-xx) - xsize)/2;
xe = xx + xsize;
yy = yy + ((ye-yy) - ysize)/2;
ye = yy + ysize;
xx = verify_log(xx ,xmin,dx ,xlog);
xe = verify_log(xe ,xmin,dx ,xlog);
yy = verify_log(yy ,ymin,dy ,ylog);
ye = verify_log(ye ,ymin,dy ,ylog);
// Clipping :
if(xx>1) continue;
if(xe<0) continue;
if(xx<0) xx = 0;
if(xe>1) xe = 1;
if(yy>1) continue;
if(ye<0) continue;
if(yy<0) yy = 0;
if(ye>1) ye = 1;
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
_sep->add(vtxs);
vtxs->add(xx,yy,a_zz);
vtxs->add(xe,yy,a_zz);
vtxs->add(xe,ye,a_zz);
vtxs->add(xx,ye,a_zz);
empty = false;
}
if(empty) {
delete _sep;
} else {
m_bins_sep.add(_sep);
}
}
void rep_bins2D_xy_wire_box(const style& a_style,
const std::vector<rep_bin2D>& a_bins,
const rep_box& a_box_x,const rep_box& a_box_y,
float a_bmin,float a_bmax,float a_zz
/*,const SbString& aID*/){
// Draw box of size proportionnal to bin value.
sg::separator* separator = new sg::separator;
rgba* mat = new rgba();
mat->color = a_style.color;
separator->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = a_style.line_pattern;
ds->line_width = a_style.line_width;
separator->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::lines();
separator->add(vtxs);
bool empty = true;
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
float range = a_bmax - a_bmin;
size_t number = a_bins.size();
for(size_t index=0;index<number;index++) {
float xx = a_bins[index].m_x_min;
float xe = a_bins[index].m_x_max;
float yy = a_bins[index].m_y_min;
float ye = a_bins[index].m_y_max;
float val = a_bins[index].m_val;
float xsize,ysize;
if(range>0) {
// If val = bmax, the box maps the cell.
xsize = (val - a_bmin) * (xe - xx) / range;
ysize = (val - a_bmin) * (ye - yy) / range;
} else {
//If range is 0. ; then all bins that have
// entries have same values. Draw box xdbin * ydbin.
xsize = xe - xx;
ysize = ye - yy;
}
xx = xx + ((xe-xx) - xsize)/2;
xe = xx + xsize;
yy = yy + ((ye-yy) - ysize)/2;
ye = yy + ysize;
xx = verify_log(xx ,xmin,dx ,xlog);
xe = verify_log(xe ,xmin,dx ,xlog);
yy = verify_log(yy ,ymin,dy ,ylog);
ye = verify_log(ye ,ymin,dy ,ylog);
// Clipping :
if(xx>1) continue;
if(xe<0) continue;
if(xx<0) xx = 0;
if(xe>1) xe = 1;
if(yy>1) continue;
if(ye<0) continue;
if(yy<0) yy = 0;
if(ye>1) ye = 1;
vtxs->add(xx,yy,a_zz);
vtxs->add(xe,yy,a_zz);
vtxs->add(xe,yy,a_zz);
vtxs->add(xe,ye,a_zz);
vtxs->add(xe,ye,a_zz);
vtxs->add(xx,ye,a_zz);
vtxs->add(xx,ye,a_zz);
vtxs->add(xx,yy,a_zz);
empty = false;
}
if(empty) {
delete separator;
} else {
m_bins_sep.add(separator);
}
}
void rep_bins2D_xy_solid(const style& a_style,const base_colormap& a_cmap,const std::vector<rep_bin2D>& a_bins,
const rep_box& a_box_x,const rep_box& a_box_y,float a_zz) {
painting_policy painting = a_style.painting;
separator* _sep = new separator();
_sep->add(new normal);
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
bool empty = true;
colorf clr;
tools_vforcit(rep_bin2D,a_bins,it) {
const rep_bin2D& rbin = *it;
float xx = rbin.m_x_min;
float xe = rbin.m_x_max;
float yy = rbin.m_y_min;
float ye = rbin.m_y_max;
float val = rbin.m_val;
xx = verify_log(xx ,xmin,dx ,xlog);
xe = verify_log(xe ,xmin,dx ,xlog);
yy = verify_log(yy ,ymin,dy ,ylog);
ye = verify_log(ye ,ymin,dy ,ylog);
// Clipping :
if(xx>1) continue;
if(xe<0) continue;
if(xx<0) xx = 0;
if(xe>1) xe = 1;
if(yy>1) continue;
if(ye<0) continue;
if(yy<0) yy = 0;
if(ye>1) ye = 1;
if(painting==painting_by_value) {
a_cmap.get_color(val,clr);
} else if( (painting==painting_grey_scale) ||
(painting==painting_grey_scale_inverse) ||
(painting==painting_violet_to_red) ){
a_cmap.get_color(rbin.m_ratio,clr);
} else {
clr = a_style.color;
}
rgba* mat = new rgba();
mat->color = clr;
_sep->add(mat);
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
//sep->add(vtxs);
_sep->add(vtxs);
vtxs->add(xx,yy,a_zz);
vtxs->add(xe,yy,a_zz);
vtxs->add(xe,ye,a_zz);
vtxs->add(xx,ye,a_zz);
empty = false;
}
if(empty) {
delete _sep;
} else {
m_bins_sep.add(_sep);
}
}
void rep_bins2D_xy_random_one(const style& a_style,const std::vector<rep_bin2D>& a_bins,
const rep_box& a_box_x,const rep_box& a_box_y,float a_bmin,float a_bmax,float a_zz
/*,const SbString& aID*/){
sg::separator* separator = new sg::separator;
rgba* mat = new rgba();
mat->color = a_style.color;
separator->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_points;
ds->point_size = a_style.point_size;
separator->add(ds);
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
// Draw for each bins a number of random
// points proportiannal to bins range.
float range = a_bmax - a_bmin;
bool empty = true;
size_t number = a_bins.size();
for(size_t index=0;index<number;index++) {
float xx = a_bins[index].m_x_min;
float xe = a_bins[index].m_x_max;
float yy = a_bins[index].m_y_min;
float ye = a_bins[index].m_y_max;
float val = a_bins[index].m_val;
// If range is 0. ; then all bins that have entries
// have same values. Draw one point.
int nmin = 1;
int nmax = 50;
int npt = range>0. ? (int)((val - a_bmin)*(nmax-nmin)/range + nmin):1;
if(npt>0) {
vertices* vtxs = new vertices;
vtxs->mode = gl::points();
separator->add(vtxs);
float xdbin = xe - xx;
float ydbin = ye - yy;
for(int count=0;count<npt;count++) {
float xxx = xx + xdbin * m_rtausmef.shoot();
float yyy = yy + ydbin * m_rtausmef.shoot();
xxx = verify_log(xxx ,xmin,dx ,xlog);
yyy = verify_log(yyy ,ymin,dy ,ylog);
if((xxx>=0)&&(xxx<=1) &&
(yyy>=0)&&(yyy<=1) ) {
vtxs->add(xxx,yyy,a_zz);
empty = false;
}
}
}
}//end for
if(empty) {
delete separator;
} else {
m_bins_sep.add(separator);
}
}
void rep_bins2D_xy_text(
const style& //a_style
,const std::vector<rep_bin2D>& //a_bins
,const rep_box& //a_box_x
,const rep_box& //a_box_y
//,const SbString& aID
){
//Draw box and text for number of entries.
}
void rep_contour_xy(std::ostream& a_out,const style& a_style,painting_policy a_painting,
const base_colormap& a_cmap,clist_contour& a_contour,
const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z,float a_zz
/*,const std::string& aID*/){
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
float zmin = a_box_z.m_pos;
float dz = a_box_z.m_width;
sg::separator* separator = new sg::separator;
draw_style* ds = new draw_style;
ds->style.value(draw_lines);
ds->line_pattern.value(a_style.line_pattern);
ds->line_width.value(a_style.line_width);
separator->add(ds);
atb_vertices* vtxs = new atb_vertices;
vtxs->mode = gl::lines(); //segments
separator->add(vtxs);
bool empty = true;
for (unsigned int i=0;i<a_contour.get_number_of_planes();i++) {
cline_strip_list* pStripList = a_contour.get_lines(i);
if(!pStripList) {
a_out << "tools::sg;:plotter::rep_contour_xy : problem with contour." << std::endl;
delete separator;
return;
}
//If zlog true, zz is already in log.
float val = (float)a_contour.get_plane(i);
float zz = val;
zz = verify_log(zz,zmin,dz,false);
if(zz>1) continue;
if(zz<0) continue;
colorf _color;
if(a_painting==painting_by_value) {
a_cmap.get_color(val,_color);
} else if(a_painting==painting_by_level) {
size_t icol = a_cmap.colorn() ? (i % a_cmap.colorn()) :0;
_color = a_cmap.color(icol);
} else {
_color = a_style.color;
}
tools_lforcit(cline_strip*,*pStripList,pos) {
cline_strip* pStrip = (*pos);
if(!pStrip) {
a_out << "tools::sg;:plotter::rep_contour_xy : problem with contour." << std::endl;
delete separator;
return;
}
if (pStrip->empty()) continue;
//// putting point at start and end of strip
//// retreiving index
//unsigned int index=pStrip->front();
//double xb=a_contour.get_xi(index);
//double yb=a_contour.get_yi(index);
//// retreiving index
////glColor4f(0,0,1,.8f);
//index=pStrip->back();
//double xe=a_contour.get_xi(index);
//double ye=a_contour.get_yi(index);
bool first = true;
float xprev = 0;
float yprev = 0;
float xx,yy;
tools_lforcit(unsigned int,*pStrip,pos2) {
xx = (float)a_contour.get_xi(*pos2);
yy = (float)a_contour.get_yi(*pos2);
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
if(
(xx<0) || (xx>1) ||
(yy<0) || (yy>1)
) {
// Throw away this strip :
}
if(first) {
first = false;
} else {
vtxs->add(xprev,yprev,a_zz+zz);
vtxs->add(xx,yy,a_zz+zz);
vtxs->add_color(_color);
vtxs->add_color(_color);
}
xprev = xx;
yprev = yy;
empty = false;
}
}
}
if(empty) {
delete separator;
} else {
m_bins_sep.add(separator);
}
}
void rep_contour_xy_filled(std::ostream& a_out,const style& a_style,painting_policy a_painting,
const base_colormap& a_cmap,clist_contour& a_contour,
const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z,float a_zz
/*,const std::string& aID*/){
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
float zmin = a_box_z.m_pos;
float dz = a_box_z.m_width;
sg::separator* separator = new sg::separator;
vec3f AB,BC,vcross;
{// Draw background :
sg::separator* sep = new sg::separator;
separator->add(sep);
float zz = a_zz - 0.01F;
colorf _color;
if(a_cmap.colorn()) {
_color = a_cmap.color(0);
} else {
_color = a_style.color;
}
rgba* mat = new rgba();
mat->color = _color;
sep->add(mat);
float xx = xmin;
float xe = xmin+dx;
float yy = ymin;
float ye = ymin+dy;
xx = verify_log(xx,xmin,dx,xlog);
xe = verify_log(xe,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
ye = verify_log(ye,ymin,dy,ylog);
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
vtxs->add(xx,yy,zz);
vtxs->add(xe,yy,zz);
vtxs->add(xe,ye,zz);
vtxs->add(xx,ye,zz);
sep->add(vtxs);
} // End background.
bool empty = true;
for (unsigned int i=0;i<a_contour.get_number_of_planes();i++) {
cline_strip_list* pStripList = a_contour.get_lines(i);
if(!pStripList) {
a_out << "tools::sg;:plotter::rep_contour_xy_filled : problem with contour." << std::endl;
delete separator;
return;
}
sg::separator* sep = new sg::separator;
separator->add(sep);
//If zlog true, zz is already in log.
float val = (float)a_contour.get_plane(i);
float zz = val;
zz = verify_log(zz,zmin,dz,false);
if(zz>1) continue;
if(zz<0) continue;
std::vector< std::vector<vec3f> > contourVector;
tools_lforcit(cline_strip*,*pStripList,pos) {
cline_strip* pStrip = (*pos);
if(pStrip->size() >2) {
std::vector<vec3f> v;
for (cline_strip::iterator pos2=pStrip->begin();pos2 != pStrip->end();pos2++) {
unsigned int index=(*pos2);
float xx = (float)a_contour.get_xi(index);
float yy = (float)a_contour.get_yi(index);
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
v.push_back(vec3f(xx,yy,a_zz+zz));
}
contourVector.push_back(std::move(v));
}
}
std::vector<tess_triangle> tris;
tess_contour tessContour(a_out,tris); //we pass a ref to tris.
tessContour.getFilledArea(contourVector);
if(!tris.size()) continue;
colorf _color;
if(a_painting==painting_by_value) {
a_cmap.get_color(val,_color);
} else if(a_painting==painting_by_level) {
int icol = a_cmap.colorn() ? (i % a_cmap.colorn()) :0;
_color = a_cmap.color(icol);
} else {
_color = a_style.color;
}
atb_vertices* vtxs = new atb_vertices; //PAW_C/color.kumac. It needs back face.
vtxs->mode = gl::triangles();
sep->add(vtxs);
for(size_t itri=0;itri<tris.size();itri++) {
tess_triangle& tri = tris[itri];
AB.set_value((float)(tri.pointB[0]-tri.pointA[0]),
(float)(tri.pointB[1]-tri.pointA[1]),
(float)(tri.pointB[2]-tri.pointA[2]));
BC.set_value((float)(tri.pointC[0]-tri.pointB[0]),
(float)(tri.pointC[1]-tri.pointB[1]),
(float)(tri.pointC[2]-tri.pointB[2]));
AB.cross(BC,vcross);
if(vcross.z()>=0) {
vtxs->add((float)tri.pointA[0],(float)tri.pointA[1],(float)tri.pointA[2]);
vtxs->add((float)tri.pointB[0],(float)tri.pointB[1],(float)tri.pointB[2]);
vtxs->add((float)tri.pointC[0],(float)tri.pointC[1],(float)tri.pointC[2]);
} else {
vtxs->add((float)tri.pointA[0],(float)tri.pointA[1],(float)tri.pointA[2]);
vtxs->add((float)tri.pointC[0],(float)tri.pointC[1],(float)tri.pointC[2]);
vtxs->add((float)tri.pointB[0],(float)tri.pointB[1],(float)tri.pointB[2]);
}
vtxs->add_color(_color);
vtxs->add_color(_color);
vtxs->add_color(_color);
}
empty = false;
}
if(empty) {
delete separator;
} else {
m_bins_sep.add(separator);
}
}
void rep_errors_plus_xy(std::ostream& /*a_out*/,const style& a_style,const std::vector<rep_bin1D>& a_bins,
const rep_box& a_box_x,const rep_box& a_box_y,const std::vector<float>& a_bars,float aZ) {
separator* _sep = new separator();
rgba* mat = new rgba();
mat->color = a_style.color;
_sep->add(mat);
draw_style* ds = new draw_style;
ds->style.value(draw_lines);
ds->line_pattern.value(a_style.line_pattern);
ds->line_width.value(a_style.line_width);
_sep->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::lines();
_sep->add(vtxs);
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
size_t xnbin = a_bins.size();
for(size_t index=0;index<xnbin;index++) {
//Need all bins modeled for fitting.
float val = a_bins[index].m_val;
float bar_height = a_bars[index];
float bar_min = val - bar_height/2;
float bar_max = val + bar_height/2;
float xx = a_bins[index].m_x_min;
float xe = a_bins[index].m_x_max;
xx = verify_log(xx,xmin,dx,xlog);
xe = verify_log(xe,xmin,dx,xlog);
val = verify_log(val,ymin,dy,ylog);
bar_min = verify_log(bar_min,ymin,dy,ylog);
bar_max = verify_log(bar_max,ymin,dy,ylog);
if(xe<0) continue;
if(xx>1) continue;
if(xx<0) xx = 0;
if(xe>1) xe = 1;
float ex = (xe+xx)/2;
float edx = 0.3F * (xe-xx);
if((val>=0)&&(val<=1)) {
vtxs->add(ex-edx,val,aZ);
vtxs->add(ex+edx,val,aZ);
}
if(bar_min >1) {
// do nothing
} else if(bar_max <0) {
// do nothing
} else if(bar_min <0) {
if(bar_max >1) {
vtxs->add(ex,0,aZ);
vtxs->add(ex,1,aZ);
} else {
vtxs->add(ex,0,aZ);
vtxs->add(ex,bar_max,aZ);
}
} else if(bar_max >1) {
vtxs->add(ex,bar_min,aZ);
vtxs->add(ex,1,aZ);
} else {
vtxs->add(ex ,bar_min,aZ);
vtxs->add(ex ,bar_max,aZ);
}
}
if(vtxs->number()) {
m_errors_sep.add(_sep);
} else {
delete _sep;
}
}
void rep_errors_I_xy(std::ostream& /*a_out*/,const style& a_style,const std::vector<rep_bin1D>& a_bins,
const rep_box& a_box_x,const rep_box& a_box_y,const std::vector<float>& a_bars,float aZ){
separator* _sep = new separator();
rgba* mat = new rgba();
mat->color = a_style.color;
_sep->add(mat);
draw_style* ds = new draw_style;
ds->style.value(draw_lines);
ds->line_pattern.value(a_style.line_pattern);
ds->line_width.value(a_style.line_width);
_sep->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::lines();
_sep->add(vtxs);
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
size_t xnbin = a_bins.size();
for(size_t index=0;index<xnbin;index++) {
//Need all bins modeled for fitting.
float val = a_bins[index].m_val;
float bar_height = a_bars[index];
float bar_min = val - bar_height/2;
float bar_max = val + bar_height/2;
float xx = a_bins[index].m_x_min;
float xe = a_bins[index].m_x_max;
xx = verify_log(xx,xmin,dx,xlog);
xe = verify_log(xe,xmin,dx,xlog);
val = verify_log(val,ymin,dy,ylog);
bar_min = verify_log(bar_min,ymin,dy,ylog);
bar_max = verify_log(bar_max,ymin,dy,ylog);
if(xe<0) continue;
if(xx>1) continue;
if(xx<0) xx = 0;
if(xe>1) xe = 1;
if(val<0) val = 0;
if(val>1) val = 1;
float ex = (xe+xx)/2;
float edx = 0.3F * (xe-xx);
if(bar_min >1) {
// do nothing
} else if(bar_max <0) {
// do nothing
} else if(bar_min <0) {
if(bar_max >1) {
vtxs->add(ex,0,aZ);
vtxs->add(ex,1,aZ);
} else {
vtxs->add(ex,0,aZ);
vtxs->add(ex,bar_max,aZ);
vtxs->add(ex-edx,bar_max,aZ);
vtxs->add(ex+edx,bar_max,aZ);
}
} else if(bar_max >1) {
vtxs->add(ex-edx,bar_min,aZ);
vtxs->add(ex+edx,bar_min,aZ);
vtxs->add(ex,bar_min,aZ);
vtxs->add(ex,1,aZ);
} else {
vtxs->add(ex-edx,bar_min,aZ);
vtxs->add(ex+edx,bar_min,aZ);
vtxs->add(ex ,bar_min,aZ);
vtxs->add(ex ,bar_max,aZ);
vtxs->add(ex-edx,bar_max,aZ);
vtxs->add(ex+edx,bar_max,aZ);
}
}
if(vtxs->number()) {
m_errors_sep.add(_sep);
} else {
delete _sep;
}
}
void rep_hatch1D_xy(const style& a_style,
const std::vector<rep_bin1D>& a_bins,
const rep_box& a_box_x,const rep_box& a_box_y,float a_zz,
bool a_bar_chart){
separator* _sep = new separator;
rgba* mat = new rgba();
mat->color = a_style.color;
_sep->add(mat);
draw_style* ds = new draw_style;
if(a_style.strip_width.value()==0) {
ds->style = draw_lines;
ds->line_pattern = line_solid;
ds->line_width = a_style.line_width;
} else {
ds->style = draw_filled;
}
_sep->add(ds);
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
bool empty = true;
vec3f points[5];
size_t xnbin = a_bins.size();
for(size_t index=0;index<xnbin;index++) {
float xx = a_bins[index].m_x_min;
float xe = a_bins[index].m_x_max;
float yy = a_bins[index].m_v_min;
float ye = a_bins[index].m_val;
if(ye<yy) {
yy = a_bins[index].m_val;
ye = a_bins[index].m_v_min;
}
if(a_bar_chart) bar_chart(a_style.bar_offset.value(),a_style.bar_width.value(),xx,xe);
xx = verify_log(xx,xmin,dx,xlog);
xe = verify_log(xe,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
ye = verify_log(ye,ymin,dy,ylog);
// Clipping :
if(xx>1) continue;
if(xe<0) continue;
if(xx<0) xx = 0;
if(xe>1) xe = 1;
if(yy>1) continue;
if(ye<0) continue;
if(yy<0) yy = 0;
if(ye>1) ye = 1;
points[0].set_value(xx,yy,a_zz);
points[1].set_value(xe,yy,a_zz);
points[2].set_value(xe,ye,a_zz);
points[3].set_value(xx,ye,a_zz);
points[4].set_value(xx,yy,a_zz);
//FIXME : have picking a hatch picks also the bin.
hatcher _hatcher;
_hatcher.set_offset_point(vec3f(0,0,a_zz));
_hatcher.set_angle(a_style.angle.value());
_hatcher.set_spacing(a_style.spacing.value());
if(!_hatcher.set_strip_width(a_style.strip_width.value())) {}
bool res = _hatcher.check_polyline(points,4);
if(res) res = _hatcher.compute_polyline(points,4);
size_t numPoints = _hatcher.points().size();
size_t numVertices = _hatcher.vertices().size();
if((res) && numPoints && numVertices) {
const std::vector<vec3f>& _points = _hatcher.points();
if(a_style.strip_width.value()==0) {
size_t ipt = 0;
tools_vforcit(unsigned int,_hatcher.vertices(),itv) {
vertices* vtxs = new vertices;
vtxs->mode = gl::line_strip();
for(size_t _index=0;_index<(*itv);_index++) {
vtxs->add(_points[ipt]);
ipt++;
}
_sep->add(vtxs);
empty = false;
}
} else {
size_t ipt = 0;
tools_vforcit(unsigned int,_hatcher.vertices(),itv) {
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
for(size_t _index=0;_index<(*itv);_index++) {
vtxs->add(_points[ipt]);
ipt++;
}
_sep->add(vtxs);
empty = false;
}
}
}
}
if(empty) {
delete _sep;
} else {
m_bins_sep.add(_sep);
}
}
void rep_points2D_xy_lines(const style& a_style,const points2D& a_points,
const rep_box& a_box_x,const rep_box& a_box_y,float a_zz){
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
separator* _sep = new separator();
rgba* mat = new rgba();
mat->color = a_style.color;
_sep->add(mat);
draw_style* ds = new draw_style;
ds->style.value(draw_lines);
ds->line_pattern.value(a_style.line_pattern);
ds->line_width.value(a_style.line_width);
_sep->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::line_strip();
_sep->add(vtxs);
bool empty = true;
float x,y;
unsigned int number = a_points.points();
for(unsigned int index=0;index<number;index++) {
a_points.ith_point(index,x,y);
x = verify_log(x,xmin,dx,xlog);
y = verify_log(y,ymin,dy,ylog);
if((x<0)||(x>1)||(y<0)||(y>1)) continue;
vtxs->add(x,y,a_zz);
empty = false;
}
if(empty) {
delete _sep;
} else {
m_points_sep.add(_sep);
}
}
void rep_points2D_xy_curve(std::ostream& a_out,const style& a_style,const points2D& a_points,
const rep_box& a_box_x,const rep_box& a_box_y,float a_zz){
unsigned int number = a_points.points();
if(!number) return;
double* xs = new double[number];
double* ys = new double[number];
float x,y;
{for(unsigned int index=0;index<number;index++) {
a_points.ith_point(index,x,y);
xs[index] = x;ys[index] = y;
}}
spline::cubic _spline(a_out,number,xs,ys);
delete [] xs;delete [] ys;
float xmn = m_x_axis_data.min_value();
float xmx = m_x_axis_data.max_value();
unsigned int nstp = curve_number_of_points;
float step = (xmx - xmn)/nstp;
std::vector<vec3f> points(nstp+1);
for(unsigned int ibin=0;ibin<=nstp;ibin++) {
float xx = xmn + ibin * step;
double val = _spline.eval(xx);
points[ibin].set_value(xx,float(val),a_zz);
}
vertices* vtxs = new vertices;
std::vector<float>& pts = vtxs->xyzs.values(); //npt*3
clip_polyline_2D(points,a_box_x,a_box_y,pts);
if(pts.size()) {
sg::separator* separator = new sg::separator;
rgba* mat = new rgba();
mat->color = a_style.color;
separator->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = a_style.line_pattern;
ds->line_width = a_style.line_width;
separator->add(ds);
vtxs->mode = gl::line_strip();
separator->add(vtxs);
m_points_sep.add(separator);
} else {
delete vtxs;
}
}
void rep_points2D_xy_points(std::ostream& a_out,
const style& a_style,const points2D& a_points,
const rep_box& a_box_x,const rep_box& a_box_y,float a_zz) {
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
separator* _sep = new separator();
rgba* mat = new rgba();
mat->color = a_style.color;
_sep->add(mat);
mf<float>* _xyzs = 0;
if(a_style.modeling==modeling_markers()) {
markers* _marks = new markers;
_marks->size = a_style.marker_size;
_marks->style = a_style.marker_style;
_xyzs = &(_marks->xyzs);
_sep->add(_marks);
} else if(a_style.modeling==modeling_points()) {
draw_style* ds = new draw_style;
ds->style = draw_points;
ds->point_size = a_style.point_size;
_sep->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::points();
_xyzs = &(vtxs->xyzs);
_sep->add(vtxs);
} else {
a_out << "tools::sg::plotter::rep_points2D_xy_points :"
<< " bad modeling style " << tools::sout(a_style.modeling) << std::endl;
delete _sep;
return;
}
float x,y;
// first round trip to get number of floats :
size_t npts = 0;
{unsigned int number = a_points.points();
for(unsigned int index=0;index<number;index++) {
a_points.ith_point(index,x,y);
x = verify_log(x,xmin,dx,xlog);
y = verify_log(y,ymin,dy,ylog);
if((x<0)||(x>1)||(y<0)||(y>1)) continue;
npts += 3;
}}
_xyzs->values().resize(npts);
size_t xyz_pos = 0;
bool empty = true;
{unsigned int number = a_points.points();
for(unsigned int index=0;index<number;index++) {
a_points.ith_point(index,x,y);
x = verify_log(x,xmin,dx,xlog);
y = verify_log(y,ymin,dy,ylog);
if((x<0)||(x>1)||(y<0)||(y>1)) continue;
_xyzs->add_allocated(xyz_pos,x,y,a_zz);
empty = false;
}}
if(empty) {
delete _sep;
} else {
m_points_sep.add(_sep);
}
}
void rep_points3D_xyz_points(std::ostream& a_out,
const style& a_style,const points3D& a_points,
const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z) {
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
float zmin = a_box_z.m_pos;
float dz = a_box_z.m_width;
bool zlog = a_box_z.m_log;
separator* _sep = new separator();
rgba* mat = new rgba();
mat->color = a_style.color;
_sep->add(mat);
mf<float>* _xyzs = 0;
if(a_style.modeling==modeling_markers()) {
markers* _marks = new markers;
_marks->size = a_style.marker_size;
_marks->style = a_style.marker_style;
_xyzs = &(_marks->xyzs);
_sep->add(_marks);
} else if(a_style.modeling==modeling_points()) {
draw_style* ds = new draw_style;
ds->style = draw_points;
ds->point_size = a_style.point_size;
_sep->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::points();
_xyzs = &(vtxs->xyzs);
_sep->add(vtxs);
} else {
a_out << "tools::sg::plotter::rep_points3D_xy_points :"
<< " bad modeling style " << tools::sout(a_style.modeling) << std::endl;
delete _sep;
return;
}
float x,y,z;
// first round trip to get number of floats :
size_t npts = 0;
{unsigned int number = a_points.points();
for(unsigned int index=0;index<number;index++) {
a_points.ith_point(index,x,y,z);
//float val = a_bins[index].m_val;
x = verify_log(x,xmin,dx,xlog);
y = verify_log(y,ymin,dy,ylog);
z = verify_log(z,zmin,dz,zlog);
if((x<0)||(x>1)||(y<0)||(y>1)||(z<0)||(z>1)) continue;
npts += 3;
}}
_xyzs->values().resize(npts);
size_t xyz_pos = 0;
bool empty = true;
{unsigned int number = a_points.points();
for(unsigned int index=0;index<number;index++) {
a_points.ith_point(index,x,y,z);
//float val = a_bins[index].m_val;
x = verify_log(x,xmin,dx,xlog);
y = verify_log(y,ymin,dy,ylog);
z = verify_log(z,zmin,dz,zlog);
if((x<0)||(x>1)||(y<0)||(y>1)||(z<0)||(z>1)) continue;
_xyzs->add_allocated(xyz_pos,x,y,z);
empty = false;
}}
if(empty) {
delete _sep;
} else {
m_points_sep.add(_sep);
}
}
void rep_bins2D_xyz_box(const style& a_style,const base_colormap& a_cmap,const std::vector<rep_bin2D>& a_bins,
const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z,float a_bmin,float /*a_bmax*/){
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
float zmin = a_box_z.m_pos;
float dz = a_box_z.m_width;
bool zlog = a_box_z.m_log;
painting_policy painting = a_style.painting;
separator* _sep = new separator();
bool empty = true;
colorf clr;
tools_vforcit(rep_bin2D,a_bins,it) {
const rep_bin2D& rbin = *it;
float xx = rbin.m_x_min;
float xe = rbin.m_x_max;
float yy = rbin.m_y_min;
float ye = rbin.m_y_max;
float val = rbin.m_val;
float zz = a_bmin;
float ze = val;
xx = verify_log(xx ,xmin,dx ,xlog);
xe = verify_log(xe ,xmin,dx ,xlog);
yy = verify_log(yy ,ymin,dy ,ylog);
ye = verify_log(ye ,ymin,dy ,ylog);
zz = verify_log(zz ,zmin,dz ,zlog);
ze = verify_log(ze ,zmin,dz ,zlog);
// Clipping :
if(xx>1) continue;
if(xe<0) continue;
if(xx<0) xx = 0;
if(xe>1) xe = 1;
if(yy>1) continue;
if(ye<0) continue;
if(yy<0) yy = 0;
if(ye>1) ye = 1;
if(zz>1) continue;
if(ze<0) continue;
if(zz<0) zz = 0;
if(ze>1) ze = 1;
if(yy>=ye) continue;
if(xx>=xe) continue;
if(zz>=ze) continue;
separator* sep = new separator();
_sep->add(sep);
if(painting==painting_by_value) {
a_cmap.get_color(val,clr);
} else if( (painting==painting_grey_scale) ||
(painting==painting_grey_scale_inverse) ||
(painting==painting_violet_to_red) ){
a_cmap.get_color(rbin.m_ratio,clr);
} else {
clr = a_style.color;
}
rgba* mat = new rgba();
mat->color = clr;
sep->add(mat);
float sx = xe-xx;
float sy = ye-yy;
float sz = ze-zz;
matrix* _tsf = new matrix;
_tsf->set_translate(xx+sx/2,yy+sy/2,sz/2);
sep->add(_tsf);
cube* _cube = new cube;
_cube->width = sx;
_cube->height = sy;
_cube->depth = sz;
sep->add(_cube);
empty = false;
}
if(empty) {
delete _sep;
} else {
m_bins_sep.add(_sep);
}
}
void rep_top_face2D_xyz(separator& a_sep,const style& a_style,const base_colormap& a_cmap,
const std::vector<rep_top_face2D>& a_faces,
const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z) {
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
float zmin = a_box_z.m_pos;
float dz = a_box_z.m_width;
bool zlog = a_box_z.m_log;
bool empty = true;
painting_policy painting = a_style.painting;
separator* _sep = new separator();
atb_vertices* vtxs = new atb_vertices;
vtxs->mode = gl::triangles();
vtxs->do_back = true;
vtxs->epsilon = 1e-6f;
_sep->add(vtxs);
colorf clr;
vec3f nm;
size_t number = a_faces.size();
for(size_t index=0;index<number;index++) {
float xx = a_faces[index].m_x_min;
float xe = a_faces[index].m_x_max;
float yy = a_faces[index].m_y_min;
float ye = a_faces[index].m_y_max;
float val1 = a_faces[index].m_v1;
float val2 = a_faces[index].m_v2;
float val3 = a_faces[index].m_v3;
float val4 = a_faces[index].m_v4;
float val = val1;
val1 = verify_log(val1,zmin,dz,zlog);
val2 = verify_log(val2,zmin,dz,zlog);
val3 = verify_log(val3,zmin,dz,zlog);
val4 = verify_log(val4,zmin,dz,zlog);
xx = verify_log(xx,xmin,dx,xlog);
xe = verify_log(xe,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
ye = verify_log(ye,ymin,dy,ylog);
if(val1<0) val1 = 0;
if(val1>1) val1 = 1;
if(val2<0) val2 = 0;
if(val2>1) val2 = 1;
if(val3<0) val3 = 0;
if(val3>1) val3 = 1;
if(val4<0) val4 = 0;
if(val4>1) val4 = 1;
if((xx>=0)&&(xx<=1) &&
(xe>=0)&&(xe<=1) &&
(yy>=0)&&(yy<=1) &&
(ye>=0)&&(ye<=1) ) {
if(painting==painting_by_value) {
float v = (zlog?take_log(val):val);
a_cmap.get_color(v,clr);
} else if( (painting==painting_grey_scale) ||
(painting==painting_grey_scale_inverse) ||
(painting==painting_violet_to_red) ){
a_cmap.get_color(a_faces[index].m_ratio,clr);
} else {
clr = a_style.color;
}
//////////////////////////////////////
//////////////////////////////////////
vtxs->add(xx,ye,val4);
vtxs->add(xx,yy,val1);
vtxs->add(xe,yy,val2);
vtxs->add_color(clr);
vtxs->add_color(clr);
vtxs->add_color(clr);
direction(xx,ye,val4,
xx,yy,val1,
xe,yy,val2,nm);
nm.normalize();
vtxs->add_normal(nm[0],nm[1],nm[2]);
vtxs->add_normal(nm[0],nm[1],nm[2]);
vtxs->add_normal(nm[0],nm[1],nm[2]);
//////////////////////////////////////
//////////////////////////////////////
vtxs->add(xe,yy,val2);
vtxs->add(xe,ye,val3);
vtxs->add(xx,ye,val4);
vtxs->add_rgba(clr[0],clr[1],clr[2],clr[3]);
vtxs->add_rgba(clr[0],clr[1],clr[2],clr[3]);
vtxs->add_rgba(clr[0],clr[1],clr[2],clr[3]);
direction(xe,yy,val2,
xe,ye,val3,
xx,ye,val4,nm);
nm.normalize();
vtxs->add_normal(nm[0],nm[1],nm[2]);
vtxs->add_normal(nm[0],nm[1],nm[2]);
vtxs->add_normal(nm[0],nm[1],nm[2]);
empty = false;
}
}
if(empty) {
delete _sep;
} else {
a_sep.add(_sep);
}
}
void rep_top_face2D_xyz_line(const style& /*a_style*/,const std::vector<rep_top_face2D>& a_top_faces,
const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z/*,const SbString& aID*/){
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
float zmin = a_box_z.m_pos;
float dz = a_box_z.m_width;
bool zlog = a_box_z.m_log;
sg::separator* separator = new sg::separator;
bool empty = true;
rgba* mat = new rgba();
mat->color = colorf_black();
separator->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = line_solid;
ds->line_width = 1;
separator->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::lines();
separator->add(vtxs);
float zepsilon = 0.02f; //for pawex9.kumac top-left and bottom-right.
size_t number = a_top_faces.size();
for(size_t index=0;index<number;index++) {
float xx = a_top_faces[index].m_x_min;
float xe = a_top_faces[index].m_x_max;
float yy = a_top_faces[index].m_y_min;
float ye = a_top_faces[index].m_y_max;
float val1 = a_top_faces[index].m_v1;
float val2 = a_top_faces[index].m_v2;
float val3 = a_top_faces[index].m_v3;
float val4 = a_top_faces[index].m_v4;
val1 = verify_log(val1,zmin,dz,zlog);
val2 = verify_log(val2,zmin,dz,zlog);
val3 = verify_log(val3,zmin,dz,zlog);
val4 = verify_log(val4,zmin,dz,zlog);
xx = verify_log(xx,xmin,dx,xlog);
xe = verify_log(xe,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
ye = verify_log(ye,ymin,dy,ylog);
if(val1<0) val1 = 0;
if(val1>1) val1 = 1;
if(val2<0) val2 = 0;
if(val2>1) val2 = 1;
if(val3<0) val3 = 0;
if(val3>1) val3 = 1;
if(val4<0) val4 = 0;
if(val4>1) val4 = 1;
if((xx>=0)&&(xx<=1) &&
(xe>=0)&&(xe<=1) &&
(yy>=0)&&(yy<=1) &&
(ye>=0)&&(ye<=1) ) {
vtxs->add(xx,ye,val4+zepsilon);
vtxs->add(xx,yy,val1+zepsilon);
vtxs->add(xx,yy,val1+zepsilon);
vtxs->add(xe,yy,val2+zepsilon);
vtxs->add(xe,yy,val2+zepsilon);
vtxs->add(xe,ye,val3+zepsilon);
vtxs->add(xe,ye,val3+zepsilon);
vtxs->add(xx,ye,val4+zepsilon);
empty = false;
}
}
if(empty) {
delete separator;
} else {
m_bins_sep.add(separator);
}
}
void rep_top_face2D_xyz_by_level(const style& /*a_style*/,painting_policy /*a_painting*/,const base_colormap& a_cmap,
const std::vector<rep_top_face2D>& a_top_faces,
const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z,
float a_bmin,float a_bmax/*,const SbString& aID*/){
size_t ncol = a_cmap.colorn();
if(!ncol) return;
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
float zmin = a_box_z.m_pos;
float dz = a_box_z.m_width;
bool zlog = a_box_z.m_log;
float zz = a_bmin;
zz = verify_log(zz,zmin,dz,zlog);
float zmx = a_bmax;
zmx = verify_log(zmx,zmin,dz,zlog);
bool empty = true;
sg::separator* separator = new sg::separator;
atb_vertices* tris = new atb_vertices;
tris->mode = gl::triangles();
tris->do_back = true;
tris->epsilon = 1e-6f;
separator->add(tris);
colorf _color;
vec3f _point;
float d_z = (zmx-zz)/ncol;
size_t number = a_top_faces.size();
for(size_t icol=0;icol<ncol;icol++) {
_color = a_cmap.color(icol);
for(size_t index=0;index<number;index++) {
float xx = a_top_faces[index].m_x_min;
float xe = a_top_faces[index].m_x_max;
float yy = a_top_faces[index].m_y_min;
float ye = a_top_faces[index].m_y_max;
float val1 = a_top_faces[index].m_v1;
float val2 = a_top_faces[index].m_v2;
float val3 = a_top_faces[index].m_v3;
float val4 = a_top_faces[index].m_v4;
val1 = verify_log(val1,zmin,dz,zlog);
val2 = verify_log(val2,zmin,dz,zlog);
val3 = verify_log(val3,zmin,dz,zlog);
val4 = verify_log(val4,zmin,dz,zlog);
xx = verify_log(xx,xmin,dx,xlog);
xe = verify_log(xe,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
ye = verify_log(ye,ymin,dy,ylog);
if(val1<0) val1 = 0;
if(val1>1) val1 = 1;
if(val2<0) val2 = 0;
if(val2>1) val2 = 1;
if(val3<0) val3 = 0;
if(val3>1) val3 = 1;
if(val4<0) val4 = 0;
if(val4>1) val4 = 1;
if((xx>=0)&&(xx<=1) &&
(xe>=0)&&(xe<=1) &&
(yy>=0)&&(yy<=1) &&
(ye>=0)&&(ye<=1) ) {
//////////////////////////////////////
//////////////////////////////////////
{clip<vec3f> clipper;
clipper.add(vec3f(xx,ye,val4));
clipper.add(vec3f(xx,yy,val1));
clipper.add(vec3f(xe,yy,val2));
//val[n] had been z normalized.
float z1 = zz+d_z*icol;
float z2 = z1+d_z;
plane<vec3f> plane_z_bot(vec3f(0,0,1),vec3f(0,0,z1));
plane<vec3f> plane_z_top(vec3f(0,0,-1),vec3f(0,0,z2));
clipper.execute(plane_z_bot);
clipper.execute(plane_z_top);
const std::vector<vec3f>& result = clipper.result();
if(result.size()) {
plane<vec3f> plane1(vec3f(xx,ye,val4),vec3f(xx,yy,val1),vec3f(xe,yy,val2));
if(result.size()==3) {
tools_vforcit(vec3f,result,it) {
tris->add(*it);
tris->add_color(_color);
tris->add_normal(plane1.normal());
}
} else {
atb_vertices* vtxs = new atb_vertices; //FIXME : ouch! optimize.
vtxs->mode = gl::triangle_fan();
vtxs->do_back = true;
vtxs->epsilon = 1e-6f;
separator->add(vtxs);
tools_vforcit(vec3f,result,it) {
vtxs->add(*it);
vtxs->add_color(_color);
vtxs->add_normal(plane1.normal());
}
}
empty = false;
}}
//////////////////////////////////////
//////////////////////////////////////
{clip<vec3f> clipper;
clipper.add(vec3f(xe,yy,val2));
clipper.add(vec3f(xe,ye,val3));
clipper.add(vec3f(xx,ye,val4));
//val[n] had been z normalized.
float z1 = zz+d_z*icol;
float z2 = z1+d_z;
plane<vec3f> plane_z_bot(vec3f(0,0,1),vec3f(0,0,z1));
plane<vec3f> plane_z_top(vec3f(0,0,-1),vec3f(0,0,z2));
clipper.execute(plane_z_bot);
clipper.execute(plane_z_top);
const std::vector<vec3f>& result = clipper.result();
if(result.size()) {
plane<vec3f> plane2(vec3f(xe,yy,val2),vec3f(xe,ye,val3),vec3f(xx,ye,val4));
if(result.size()==3) {
tools_vforcit(vec3f,result,it) {
tris->add(*it);
tris->add_color(_color);
tris->add_normal(plane2.normal());
}
} else {
atb_vertices* vtxs = new atb_vertices; //FIXME : ouch! optimize.
vtxs->mode = gl::triangle_fan();
vtxs->do_back = true;
vtxs->epsilon = 1e-6f;
separator->add(vtxs);
tools_vforcit(vec3f,result,it) {
vtxs->add(*it);
vtxs->add_color(_color);
vtxs->add_normal(plane2.normal());
}
}
empty = false;
}}
}
} //index faces
} //icol
if(empty) {
delete separator;
} else {
m_bins_sep.add(separator);
}
}
// for OpenPAW /GRAPHICS/PRIMITIVES/TEXT
// for OpenPAW /GRAPHICS/PRIMITIVES/ITX
void update_primitive_text(const plottable_text& a_obj){
if(a_obj.m_TEXT.empty()) return;
float z = xy_depth.value()*1.1F;
vec3f pos;
axis_2_data_frame(vec3f(a_obj.m_X,a_obj.m_Y,z),pos); //FIXME return FALSE
xx_2_yy(pos,pos);
separator* sep = new separator;
rgba* mat = new rgba();
mat->color = a_obj.m_TXCI;
sep->add(mat);
matrix* _tsf = new matrix;
_tsf->set_translate(pos);
_tsf->mul_rotate(0,0,1,a_obj.m_ANGLE*fpi()/180.0f);
_tsf->mul_scale(a_obj.m_SCALE,a_obj.m_SCALE,1);
sep->add(_tsf);
//SIZE is in page coordinate YSIZ.
//float YSIZ = height.value();
//if(YSIZ<=0) YSIZ = 1;
if(a_obj.m_text_mode==plottable_text::text_enforce_width) { // not tested yet.
vec3f pos2;
axis_2_data_frame(vec3f(a_obj.m_X+a_obj.m_SIZE,a_obj.m_Y,z),pos2); //m_SIZE is taken as text width in this text_mode.
xx_2_yy(pos2,pos2);
float _width = pos2.x()-pos.x();
text* _text = new text(m_ttf);
_text->enforce_front_width = true; //it will set _text->width, height.
_text->front_width = _width;
_text->back_visible = false;
_text->encoding = encoding_PAW();
_text->strings.add(a_obj.m_TEXT);
_text->line_width = a_obj.m_line_width;
_text->font = a_obj.m_FONT;
_text->font_modeling = a_obj.m_font_modeling;
if(a_obj.m_HJUST=='R') {
_text->hjust = right;
} else if(a_obj.m_HJUST=='C') {
_text->hjust = center;
} else {
_text->hjust = left;
}
if(a_obj.m_VJUST=='T') {
_text->vjust = top;
} else if(a_obj.m_VJUST=='M') {
_text->vjust = middle;
} else {
_text->vjust = bottom;
}
sep->add(_text);
} else if(a_obj.m_text_mode==plottable_text::text_enforce_height) { // for EsbRootView neard, fard 2D plot.
vec3f pos2;
axis_2_data_frame(vec3f(a_obj.m_X,a_obj.m_Y+a_obj.m_SIZE,z),pos2); //m_SIZE is taken as text height in this text_mode.
xx_2_yy(pos2,pos2);
float _height = pos2.y()-pos.y();
text* _text = new text(m_ttf);
_text->enforce_front_height = true; //it will set _text->width, height.
_text->front_height = _height;
_text->back_visible = false; //if true, we should adapt back_area::width, height to inside text size.
_text->encoding = encoding_PAW();
_text->strings.add(a_obj.m_TEXT);
_text->line_width = a_obj.m_line_width;
_text->font = a_obj.m_FONT;
_text->font_modeling = a_obj.m_font_modeling;
if(a_obj.m_HJUST=='R') {
_text->hjust = right;
} else if(a_obj.m_HJUST=='C') {
_text->hjust = center;
} else {
_text->hjust = left;
}
if(a_obj.m_VJUST=='T') {
_text->vjust = top;
} else if(a_obj.m_VJUST=='M') {
_text->vjust = middle;
} else {
_text->vjust = bottom;
}
sep->add(_text);
} else { //text_as_it (for gopaw/pagpri.cpp).
_tsf->mul_scale(a_obj.m_SIZE,a_obj.m_SIZE,1);
if(a_obj.m_FONT==font_hershey()) {
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = line_solid;
ds->line_width = a_obj.m_line_width;
sep->add(ds);
text_hershey* text = new text_hershey;
text->encoding = encoding_PAW();
text->strings.add(a_obj.m_TEXT);
if(a_obj.m_HJUST=='R') {
text->hjust = right;
} else if(a_obj.m_HJUST=='C') {
text->hjust = center;
} else {
text->hjust = left;
}
if(a_obj.m_VJUST=='T') {
text->vjust = top;
} else if(a_obj.m_VJUST=='M') {
text->vjust = middle;
} else {
text->vjust = bottom;
}
sep->add(text);
} else {
base_freetype* text = base_freetype::create(m_ttf);
text->font = a_obj.m_FONT;
if(a_obj.m_HJUST=='R') {
text->hjust = right;
} else if(a_obj.m_HJUST=='C') {
text->hjust = center;
} else {
text->hjust = left;
}
if(a_obj.m_VJUST=='T') {
text->vjust = top;
} else if(a_obj.m_VJUST=='M') {
text->vjust = middle;
} else {
text->vjust = bottom;
}
text->modeling = a_obj.m_font_modeling;
text->strings.add(a_obj.m_TEXT);
sep->add(text);
}
} //text_mode.
m_primitives_sep.add(sep);
}
// for OpenPAW /GRAPHICS/PRIMITIVES/BOX
void PAW_hatch(int aHTYP,hatching_policy& a_policy,float& a_spacing,float& a_angle_right,float& a_angle_left) {
// PAW hatching encoding (paw.pdf 1.14(1992) p 174) :
a_policy = hatching_none;
a_spacing = 0;
a_angle_right = 0;
a_angle_left = 0;
int code = aHTYP;
if(code==0) return;
// From PAW FAQ web page.
// special code from code [1,25]
if(code==1) {
a_policy = hatching_left_and_right;
a_spacing = 0.04F;
a_angle_right = 3.0F*fpi()/4.0F;
a_angle_left = fpi()/4.0F;
return;
} else if(code==2) {
a_policy = hatching_left_and_right;
a_spacing = 0.08F;
a_angle_right = 3.0F*fpi()/4.0F;
a_angle_left = fpi()/4.0F;
return;
} else if(code==3) {
a_policy = hatching_left_and_right;
a_spacing = 1.6f*0.07F; //cooking
a_angle_right = 3.0F*fpi()/4.0F;
a_angle_left = fpi()/4.0F;
return;
} else if(code==4) {
code = 354;
} else if(code==5) {
code = 345;
} else if(code==6) {
code = 359;
} else if(code==7) {
code = 350;
} else if(code<=25) {
//FIXME : seems to be done with patterns.
a_policy = hatching_none;
return;
} else if(code<=99) {
//FIXME
a_policy = hatching_none;
return;
}
int i = code / 100;
int j = (code - i * 100)/10;
int k = code - i * 100 - j * 10;
// j-hatching on rightHatchStyle :
// k-hatching on leftHatchStyle :
if((j==5)&&(k==5))
a_policy = hatching_none;
else if((j!=5)&&(k==5))
a_policy = hatching_right;
else if((j==5)&&(k!=5))
a_policy = hatching_left;
else if((j!=5)&&(k!=5))
a_policy = hatching_left_and_right;
unsigned int NY = 1;
a_spacing = float(NY) * float(i) * 0.07F; //cooking
if(j!=5) {
float angle = float(j==4?45:j*10);
angle = 180.0F - angle;
angle *= fpi() / 180.0F;
a_angle_right = angle;
}
if(k!=5) {
float angle = float(k==4?45:k*10);
angle *= fpi() / 180.0F;
a_angle_left = angle;
}
}
void rep_box_hatch(separator& a_parent,float a_spacing,float a_angle,float a_strip_width,
float xx,float yy,float xe,float ye,float a_zz){
sg::separator* separator = new sg::separator;
bool empty = true;
vec3f points[5];
points[0].set_value(xx,yy,a_zz);
points[1].set_value(xe,yy,a_zz);
points[2].set_value(xe,ye,a_zz);
points[3].set_value(xx,ye,a_zz);
points[4].set_value(xx,yy,a_zz);
//We can have multiple hatching for a bins ; have a separator :
hatcher _hatcher;
_hatcher.set_offset_point(vec3f(0,0,a_zz));
_hatcher.set_angle(a_angle);
_hatcher.set_spacing(a_spacing);
if(!_hatcher.set_strip_width(a_strip_width)) {}
bool res = _hatcher.check_polyline(points,4);
if(res) res = _hatcher.compute_polyline(points,4);
size_t numPoints = _hatcher.points().size();
size_t numVertices = _hatcher.vertices().size();
if((res) && numPoints && numVertices) {
const std::vector<vec3f>& _points = _hatcher.points();
if(a_strip_width==0) {
size_t ipt = 0;
tools_vforcit(unsigned int,_hatcher.vertices(),itv) {
vertices* vtxs = new vertices;
vtxs->mode = gl::line_strip();
for(size_t index=0;index<(*itv);index++) {
vtxs->add(_points[ipt]);
ipt++;
}
separator->add(vtxs);
empty = false;
}
} else {
size_t ipt = 0;
tools_vforcit(unsigned int,_hatcher.vertices(),itv) {
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
for(size_t index=0;index<(*itv);index++) {
vtxs->add(_points[ipt]);
ipt++;
}
separator->add(vtxs);
empty = false;
}
}
empty = false;
}
if(empty) {
delete separator;
} else {
a_parent.add(separator);
}
}
void update_primitive_box(std::ostream& a_out,const plottable_box& a_obj){
float z = xy_depth.value()*1.1F;
vec3f pos1;
axis_2_data_frame(vec3f(a_obj.m_X1,a_obj.m_Y1,z),pos1);
xx_2_yy(pos1,pos1);
vec3f pos2;
axis_2_data_frame(vec3f(a_obj.m_X2,a_obj.m_Y2,z),pos2);
xx_2_yy(pos2,pos2);
z = pos1[2];
if(a_obj.m_FAIS==plottable_box::HOLLOW) {
separator* sep = new separator;
rgba* mat = new rgba();
mat->color = a_obj.m_PLCI;
sep->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = line_solid;
ds->line_width = a_obj.m_LWID;
sep->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::line_strip();
sep->add(vtxs);
vtxs->add(pos1[0],pos1[1],z);
vtxs->add(pos2[0],pos1[1],z);
vtxs->add(pos2[0],pos2[1],z);
vtxs->add(pos1[0],pos2[1],z);
vtxs->add(pos1[0],pos1[1],z);
m_primitives_sep.add(sep);
} else if(a_obj.m_FAIS==plottable_box::SOLID) {
separator* sep = new separator;
rgba* mat = new rgba();
mat->color = a_obj.m_FACI;
sep->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_filled;
sep->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
sep->add(vtxs);
vtxs->add(pos1[0],pos1[1],z);
vtxs->add(pos2[0],pos1[1],z);
vtxs->add(pos2[0],pos2[1],z);
vtxs->add(pos1[0],pos2[1],z);
m_primitives_sep.add(sep);
} else if(a_obj.m_FAIS==plottable_box::HATCHED) {
{separator* sep = new separator;
rgba* mat = new rgba();
mat->color = a_obj.m_FACI;
sep->add(mat);
hatching_policy hatching;
float spacing;
float angle_right;
float angle_left;
PAW_hatch(a_obj.m_FASI,hatching,spacing,angle_right,angle_left);
float stripWidth = 0;
if((hatching==hatching_right)||((hatching==hatching_left_and_right))) {
rep_box_hatch(*sep,spacing,angle_right,stripWidth,pos1[0],pos1[1],pos2[0],pos2[1],z);
}
if((hatching==hatching_left)||((hatching==hatching_left_and_right))) {
rep_box_hatch(*sep,spacing,angle_left,stripWidth,pos1[0],pos1[1],pos2[0],pos2[1],z);
}
if(hatching==hatching_none) {
draw_style* ds = new draw_style;
ds->style = draw_filled;
sep->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::triangle_fan();
sep->add(vtxs);
vtxs->add(pos1[0],pos1[1],z);
vtxs->add(pos2[0],pos1[1],z);
vtxs->add(pos2[0],pos2[1],z);
vtxs->add(pos1[0],pos2[1],z);
}
m_primitives_sep.add(sep);}
if(a_obj.m_BORD) {
separator* sep = new separator;
rgba* mat = new rgba();
mat->color = a_obj.m_PLCI;
sep->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = line_solid;
ds->line_width = 1;
sep->add(ds);
vertices* vtxs = new vertices;
vtxs->mode = gl::line_strip();
sep->add(vtxs);
z *= 1.01F;
vtxs->add(pos1[0],pos1[1],z);
vtxs->add(pos2[0],pos1[1],z);
vtxs->add(pos2[0],pos2[1],z);
vtxs->add(pos1[0],pos2[1],z);
vtxs->add(pos1[0],pos1[1],z);
m_primitives_sep.add(sep);
}
} else if(a_obj.m_FAIS==plottable_box::PATTERN) {
a_out << "tools::sg::plotter::update_plottable_box FAIS PATTERN not yet handled." << std::endl;
}
}
void update_primitive_ellipse(std::ostream& a_out,const plottable_ellipse& a_obj){
float z = xy_depth.value()*1.1F;
vec3f pos;
axis_2_data_frame(vec3f(a_obj.m_X,a_obj.m_Y,z),pos);
xx_2_yy(pos,pos);
vec3f pos2;
axis_2_data_frame(vec3f(a_obj.m_X+a_obj.m_R1,a_obj.m_Y+a_obj.m_R2,z),pos2);
xx_2_yy(pos2,pos2);
float rx = pos2[0]-pos[0];
float ry = pos2[1]-pos[1];
z = pos[2];
if(a_obj.m_FAIS==plottable_ellipse::HOLLOW) {
separator* sep = new separator;
matrix* _tsf = new matrix;
_tsf->set_translate(pos);
sep->add(_tsf);
rgba* mat = new rgba();
mat->color = a_obj.m_PLCI;
sep->add(mat);
draw_style* ds = new draw_style;
ds->style = draw_lines;
ds->line_pattern = line_solid;
ds->line_width = a_obj.m_LWID;
sep->add(ds);
ellipse* _ellipse = new ellipse;
_ellipse->rx = rx;
_ellipse->ry = ry;
sep->add(_ellipse);
m_primitives_sep.add(sep);
} else {
a_out << "tools::sg::plotter::update_plottable_box FAIS " << a_obj.m_FAIS << " not yet handled." << std::endl;
}
}
void update_primitive_img(std::ostream& /*a_out*/,const plottable_img& a_obj){
float z = xy_depth.value()*1.1F;
vec3f pos;
axis_2_data_frame(vec3f(a_obj.m_X,a_obj.m_Y,z),pos);
xx_2_yy(pos,pos); //pos = center of image in axes coordinates.
z = pos[2];
vec3f top;
axis_2_data_frame(vec3f(0,a_obj.m_Y+a_obj.m_HEIGHT*0.5f,0),top);
xx_2_yy(top,top); //top = (o,y-top) of image in axes coordinates.
float scale = 2.0f*(top[1]-pos[1]);
const img<byte>& img = a_obj.m_img;
separator* sep = new separator;
rgba* mat = new rgba();
mat->color = colorf_white();
sep->add(mat);
normal* nm = new normal;
sep->add(nm);
matrix* _tsf = new matrix;
_tsf->set_translate(pos);
_tsf->mul_rotate(0,1,0,a_obj.m_THETA*fpi()/180.0f);
_tsf->mul_rotate(0,0,1,a_obj.m_PHI*fpi()/180.0f);
_tsf->mul_scale(scale,scale,1);
sep->add(_tsf);
tex_rect* _img = new tex_rect();
_img->img = img;
sep->add(_img);
m_primitives_sep.add(sep);
}
protected: //etc
// background is at z = 0.
// last z items are text in infos, legend boxes that should be at xy_depth().
float _zoffset() const {
// first data plane is at _zoffset.
// last one at m_plottables.size()*_zoffset = xy_depth.value()-_zoffset().
return xy_depth.value()/(float(m_plottables.size())+1.0f);
}
float _zaxis() const {return _zoffset();}
float _zgrid() const {return xy_depth.value()-_zoffset()*0.5f;}
float _ztext() const {return 0.01f;} //if text back is visible else 0. (sf<float> zfront ?)
float _zscale_text() const {return _zoffset()*0.4f/_ztext();} //title and infos boxes thickness.
float _zinfos() const {return xy_depth.value()-_zoffset()*0.4f;} //in front _zgrid
float _zhatch() const {return _zoffset()*0.25f;}
float _zerrors() const {return _zoffset()*0.5f;}
static float take_log(float a_x){
if(a_x<=0) {
return -FLT_MAX;
} else {
return flog10(a_x);
}
}
static float verify_log(float a_val,float a_min,float a_dx,bool a_log){
if(a_log) {
if(a_val>0.0F) {
return (flog10(a_val) - a_min)/a_dx;
} else { // Return a negative large number :
return -100;
}
} else {
// Simple protection against value that could exceed a float :
if(a_val>(a_min+100.0F * a_dx)) return 100;
if(a_val<(a_min-100.0F * a_dx)) return -100;
// Rescale :
return (a_val - a_min)/a_dx;
}
}
static float verify_log_inv(float a_val,float a_min,float a_dx,bool a_log){
if(a_log) {
return fpow(10,a_val*a_dx+a_min);
} else {
return a_val*a_dx+a_min;
}
}
style* merge_bins_style(unsigned int a_index,plottable&) {
style& _style = bins_style(a_index);
//uuu merge with a_p.infos().
return new style(_style);
}
style* merge_left_hatch_style(unsigned int a_index,plottable&) {
style& _style = left_hatch_style(a_index);
//uuu merge with a_p.infos().
return new style(_style);
}
style* merge_right_hatch_style(unsigned int a_index,plottable&) {
style& _style = right_hatch_style(a_index);
//uuu merge with a_p.infos().
return new style(_style);
}
style* merge_errors_style(unsigned int a_index,plottable&) {
style& _style = errors_style(a_index);
//uuu merge with a_p.infos().
return new style(_style);
}
style* merge_func_style(unsigned int a_index,plottable&) {
style& _style = func_style(a_index);
//uuu merge with a_p.infos().
return new style(_style);
}
style* merge_points_style(unsigned int a_index,plottable&) {
style& _style = points_style(a_index);
//uuu merge with a_p.infos().
return new style(_style);
}
shape_type get_shape() const {
if(!shape_automated) return shape.value();
{
return xy; //Default.
}
}
void clear_plottables() {
//unsigned int objn = m_plottables.size();
{std::vector<plottable*>::iterator it;
for(it=m_plottables.begin();it!=m_plottables.end();++it) delete *it;
m_plottables.clear();}
touch();
}
void clear_primitives() {
{std::vector<plotprim*>::iterator it;
for(it=m_primitives.begin();it!=m_primitives.end();++it) delete *it;
m_primitives.clear();}
touch();
}
void clear_todels() {m_todel_group.clear();}
bool first_bins(bins1D*& a_1,bins2D*& a_2) const {
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(bins1D* b1 = safe_cast<plottable,bins1D>(*object)) {
a_1 = b1;
a_2 = 0;
return true;
} else if(bins2D* b2 = safe_cast<plottable,bins2D>(*object)) {
a_1 = 0;
a_2 = b2;
return true;
}
}
a_1 = 0;
a_2 = 0;
return false;
}
bool first_func(func1D*& a_1,func2D*& a_2) const {
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(func1D* f1 = safe_cast<plottable,func1D>(*object)) {
a_1 = f1;
a_2 = 0;
return true;
} else if(func2D* f2 = safe_cast<plottable,func2D>(*object)) {
a_1 = 0;
a_2 = f2;
return true;
}
}
a_1 = 0;
a_2 = 0;
return false;
}
bool first_points(points2D*& a_2,points3D*& a_3) const {
tools_vforcit(plottable*,m_plottables,it) {
plottable* object = *it;
if(!object) continue;
if(points2D* p2 = safe_cast<plottable,points2D>(*object)) {
a_2 = p2;
a_3 = 0;
return true;
} else if(points3D* p3 = safe_cast<plottable,points3D>(*object)) {
a_2 = 0;
a_3 = p3;
return true;
}
}
a_2 = 0;
a_3 = 0;
return false;
}
void clear_sg() {
m_bins_sep.clear();
m_errors_sep.clear();
m_func_sep.clear();
m_points_sep.clear();
}
void DUMP_UPDATE_WHAT(std::ostream&,const std::string&) {}
static void add_pt(std::vector<float>& a_pts,float a_x,float a_y,float a_z){
a_pts.push_back(a_x);
a_pts.push_back(a_y);
a_pts.push_back(a_z);
}
static void clip_points_2D(const std::vector<vec3f>& a_points,
const rep_box& a_box_x,const rep_box& a_box_y,std::vector<float>& a_pts) {
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
a_pts.clear();
float xx,yy,zz;
tools_vforcit(vec3f,a_points,it) {
const vec3f& _point = *it;
xx = _point[0];
yy = _point[1];
zz = _point[2];
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
if((xx>=0)&&(xx<=1)&&(yy>=0)&&(yy<=1)) add_pt(a_pts,xx,yy,zz);
}
}
static void clip_polyline_2D(const std::vector<vec3f>& a_points,
const rep_box& a_box_x,const rep_box& a_box_y,std::vector<float>& a_pts) {
// Clip line in a_box_x, a_box_y.
//NOTE : it is not a general algorithm.
// It is assumed that a_points are ordered with increasing x.
// And the algorithm clips against up and bottom BoxY lines.
// (Use clip<float> for a more general algorithm ?)
float xmin = a_box_x.m_pos;
float dx = a_box_x.m_width;
bool xlog = a_box_x.m_log;
float ymin = a_box_y.m_pos;
float dy = a_box_y.m_width;
bool ylog = a_box_y.m_log;
a_pts.clear();
float xprev = 0;
float yprev = 0;
{unsigned int index = 0;
std::vector<vec3f>::const_iterator it;
for(it=a_points.begin();it!=a_points.end();++it,index++) {
const vec3f& _point = *it;
float xx = _point[0];
float yy = _point[1];
float zz = _point[2];
//add_pt(a_pts,xx,yy,zz);continue; //debug
xx = verify_log(xx,xmin,dx,xlog);
yy = verify_log(yy,ymin,dy,ylog);
if((xx>=0)&&(xx<=1) ) {
if(yy>1) {
if(index==0) {
add_pt(a_pts,xx,1,zz);
} else {
if(yprev>1) {
add_pt(a_pts,xx,1,zz);
} else if(yprev<0) {
float a = (yy - yprev)/(xx - xprev);
float b = yy - a * xx;
add_pt(a_pts,-b/a,0,zz);
add_pt(a_pts,(1 - b)/a,1,zz);
add_pt(a_pts,xx,1,zz);
} else {
float a = (yy - yprev)/(xx - xprev);
float b = yy - a * xx;
add_pt(a_pts,(1 - b)/a,1,zz);
add_pt(a_pts,xx,1,zz);
}
}
} else if (yy < 0) {
if(index==0) {
add_pt(a_pts,xx,0,zz);
} else {
if(yprev<0) {
add_pt(a_pts,xx,0,zz);
} else if(yprev>1) {
float a = (yy - yprev)/(xx - xprev);
float b = yy - a * xx;
add_pt(a_pts,(1 - b)/a,1,zz);
add_pt(a_pts,-b/a,0,zz);
add_pt(a_pts,xx,0,zz);
} else {
float a = (yy - yprev)/(xx - xprev);
float b = yy - a * xx;
add_pt(a_pts,-b/a,0,zz);
add_pt(a_pts,xx,0,zz);
}
}
} else {
if(index==0) {
add_pt(a_pts,xx,yy,zz);
} else if( (yprev>1) || (yprev<0) ) {
// interpolate :
float a = (yy - yprev)/(xx - xprev);
float b = yy - a * xx;
if(yprev>1) {
add_pt(a_pts,(1 - b)/a,1,zz);
} else {
add_pt(a_pts,-b/a,0,zz);
}
add_pt(a_pts,xx,yy,zz);
} else {
add_pt(a_pts,xx,yy,zz);
}
}
}
xprev = xx;
yprev = yy;
}}
}
bool sto(const std::string& a_s,vec2f& a_v) {
std::vector<std::string> ws;
words(a_s," ",false,ws);
if(ws.size()!=2) return false;
float x = 0;
if(!to<float>(ws[0],x)) return false;
float y = 0;
if(!to<float>(ws[1],x)) return false;
a_v.set_value(x,y);
return true;
}
bool sto(const std::string& a_s,unit_type& a_v) {
if(a_s=="percent") {a_v = unit_percent;return true;}
else if(a_s=="axis") {a_v = unit_axis;return true;}
return false;
}
void clear_cmaps() {
{std::vector<base_colormap*>::iterator it;
for(it=m_bins_cmaps.begin();it!=m_bins_cmaps.end();++it) delete *it;
m_bins_cmaps.clear();}
{std::vector<base_colormap*>::iterator it;
for(it=m_points_cmaps.begin();it!=m_points_cmaps.end();++it) delete *it;
m_points_cmaps.clear();}
{std::vector<base_colormap*>::iterator it;
for(it=m_func_cmaps.begin();it!=m_func_cmaps.end();++it) delete *it;
m_func_cmaps.clear();}
}
void bar_chart(float a_bar_offset,float a_bar_width,
float& a_beg,float& a_end){
float xe = (a_end - a_beg)*a_bar_offset;
float xw = (a_end - a_beg)*a_bar_width;
a_end = a_beg + xe + xw;
a_beg = a_beg + xe;
}
protected:
const base_freetype& m_ttf;
protected: //fields for skeleton.
group m_group;
separator m_background_sep;
separator m_cmap_sep;
matrix m_cmap_matrix;
separator m_cmap_cells_sep;
matrix m_cmap_axis_matrix;
sg::axis m_cmap_axis;
separator m_infos_title_sep;
separator m_infos_sep;
separator m_legend_sep;
separator m_title_box_sep;
matrix m_tsf;
matrix m_layout;
separator m_title_sep;
separator m_x_axis_sep;
matrix m_x_axis_matrix;
sg::axis m_x_axis;
separator m_y_axis_sep;
matrix m_y_axis_matrix;
sg::axis m_y_axis;
separator m_z_axis_sep;
matrix m_z_axis_matrix;
sg::axis m_z_axis;
separator m_grid_sep;
separator m_data_sep;
torche m_data_light;
matrix m_data_matrix;
separator m_bins_sep;
separator m_errors_sep;
separator m_func_sep;
separator m_points_sep;
separator m_inner_frame_sep;
separator m_primitives_sep;
separator m_etc_sep;
protected: //fields
shape_type m_shape;
data_axis m_x_axis_data;
data_axis m_y_axis_data;
data_axis m_z_axis_data;
std::vector<plottable*> m_plottables; //it has ownership.
std::vector<style> m_bins_style;
std::vector<style> m_errors_style;
std::vector<style> m_func_style;
std::vector<style> m_points_style;
std::vector<style> m_left_hatch_style;
std::vector<style> m_right_hatch_style;
std::vector<style> m_legend_style;
text_style m_title_style;
text_style m_infos_style;
text_style m_title_box_style;
style m_background_style;
style m_wall_style; //for gopaw.
style m_inner_frame_style;
style m_grid_style;
protected:
std::vector<std::string> m_legend_strings;
std::vector<base_colormap*> m_bins_cmaps;
std::vector<base_colormap*> m_points_cmaps;
std::vector<base_colormap*> m_func_cmaps;
group m_todel_group;
std::vector<plotprim*> m_primitives;
cmaps_t m_cmaps;
rtausmef m_rtausmef;
};
}}
#endif