Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/sg/plotter is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_sg_plotter
0005 #define tools_sg_plotter
0006 
0007 #include "../lina/vec2f"
0008 
0009 #include "render_action"
0010 #include "plottables"
0011 #include "style"
0012 #include "rep"
0013 #include "colormap"
0014 #include "noderef"
0015 #include "atb_vertices"
0016 #include "cube" //for lego
0017 #include "matrix"
0018 #include "normal"
0019 #include "holder"
0020 #include "tex_rect" //for plottable_img.
0021 
0022 #include "axis"
0023 #include "infos_box"
0024 #include "legend"
0025 #include "text"
0026 #include "torche"
0027 #include "ellipse"
0028 
0029 #include "../data_axis"
0030 #include "../hatcher"
0031 #include "../clist_contour"
0032 #include "../tess_contour"
0033 #include "../lina/geom3"
0034 #include "../spline"
0035 #include "../rtausmef"
0036 
0037 //#define INLIBS_SG_PLOTTER_TIMING
0038 #ifdef INLIBS_SG_PLOTTER_TIMING
0039 #include "../sys/atime"
0040 #endif
0041 
0042 namespace tools {
0043 namespace sg {
0044 
0045 class plotter : public node {
0046   TOOLS_NODE(plotter,tools::sg::plotter,node)
0047 private:
0048   static const std::string& s_infos_what_def() {
0049     static const std::string s_v("name entries mean rms fit_quality fit_ndf fit_parameters fit_errors");
0050     return s_v;
0051   }
0052   static float default_infos_margin() {return 0.005f;}
0053   static float default_title_box_width()    {return 0.3f;}
0054   static float default_title_box_height()   {return 0.05f;}
0055   static float default_title_box_x_margin() {return 0.01f;}
0056   static float default_title_box_y_margin() {return 0.005f;}
0057 public:
0058   sf<float> width;          //PAW XSIZ
0059   sf<float> height;         //PAW YSIZ
0060   sf<float> left_margin;    //PAW XMGL
0061   sf<float> right_margin;   //PAW XMGR
0062   sf<float> bottom_margin;  //PAW YMGL
0063   sf<float> top_margin;     //PAW YMGU
0064 
0065   sf<float> depth;
0066   sf<float> down_margin;
0067   sf<float> up_margin;
0068 
0069   sf<bool> title_up;
0070   sf<float> title_to_axis;
0071   sf<float> title_height;
0072   sf<bool> title_automated;
0073   sf_enum<hjust> title_hjust;
0074   sf_string title; //output if title_automated.
0075 
0076   sf<bool> colormap_visible;
0077   enum colormap_axis_labeling_type {
0078     cells = 0,
0079     min_max
0080   };
0081   sf_enum<colormap_axis_labeling_type> colormap_axis_labeling;
0082   sf<bool> colormap_attached;
0083   sf<bool> colormap_axis_visible;
0084 
0085   // Wanted axes parameters.
0086   // They are not necessary realized on the sg::axis nodes.
0087   sf<bool> x_axis_enforced;
0088   sf<bool> x_axis_automated;
0089   sf<float> x_axis_min;
0090   sf<float> x_axis_max;
0091   sf<bool> x_axis_is_log;
0092 
0093   sf<bool> y_axis_enforced;
0094   sf<bool> y_axis_automated;
0095   sf<float> y_axis_min;
0096   sf<float> y_axis_max;
0097   sf<bool> y_axis_is_log;
0098 
0099   sf<bool> z_axis_enforced;
0100   sf<bool> z_axis_automated;
0101   sf<float> z_axis_min;
0102   sf<float> z_axis_max;
0103   sf<bool> z_axis_is_log;
0104 
0105   sf<float> value_top_margin;
0106   sf<float> value_bottom_margin;
0107   sf<bool> value_bins_with_entries;
0108 
0109   sf<float> infos_width; //in percent of width.
0110   sf<float> infos_x_margin; //in percent of width. From right.
0111   sf<float> infos_y_margin; //in percent of height. From top.
0112   sf_string infos_what;
0113 
0114   sf<float> title_box_width;    //in percent of width.
0115   sf<float> title_box_height;   //in percent of height.
0116   sf<float> title_box_x_margin; //in percent of width. From left.
0117   sf<float> title_box_y_margin; //in percent of height. From top.
0118 
0119   sf<bool> func2D_borders_visible;
0120 
0121   // used with shape xyz
0122   sf<float> theta;  //in degrees.
0123   sf<float> phi;    //in degrees.
0124   sf<float> tau;    //in degrees.
0125 
0126   ////////////////////////////////////////////////////////////////
0127   /// legend related :////////////////////////////////////////////
0128   ////////////////////////////////////////////////////////////////
0129   sf<bool> legends_automated;
0130   //sf<bool> legends_attached_to_infos;
0131   //if legends_attached_to_infos is false :
0132   //  legends_origin is used to place the legends. It is then
0133   //  the lower left corner of the box containing all legends.
0134   mf_vec<vec2f,float> legends_origin; //common origin of legend boxes.
0135   enum unit_type {
0136     unit_percent,
0137     unit_axis
0138   };
0139   mf_enum<unit_type> legends_origin_unit;
0140   mf_vec<vec2f,float> legends_size; //overall legend boxes size.
0141   mf_string legends_string;
0142 
0143   ////////////////////////////////////////////////////////////////
0144   ////////////////////////////////////////////////////////////////
0145   ////////////////////////////////////////////////////////////////
0146 
0147   sf<bool> shape_automated;
0148 
0149   enum shape_type {
0150     xy = 0,
0151     xyz
0152   };
0153   sf_enum<shape_type> shape;
0154 
0155   // used with xy shape :
0156   sf<float> xy_depth; //all is in z [0,xy_depth]
0157 
0158   sf<unsigned int> curve_number_of_points;
0159 
0160   sf<bool> data_light_on_automated;
0161 
0162   // for gopaw :
0163   sf<bool> primitives_enforced;
0164   sf<bool> inner_frame_enforced;
0165   // to be implemented :
0166   sf<bool> top_axis_visible;
0167   sf<bool> right_axis_visible;
0168   sf<bool> superpose_bins;
0169   //sf<bool> grid_visible;
0170   // For contours :
0171   sf<unsigned int> number_of_levels;
0172   mf<float> levels;
0173   //sf<bool> frozen;
0174   //sf<float> ttfScale;
0175   //sf<bool> wallEnforced;
0176   //sf<bool> gridEnforced;
0177   //SoMFString infos; //Output
0178   //SoMFString legend; //Output
0179 
0180 public:
0181   virtual const desc_fields& node_desc_fields() const {
0182     TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::plotter)
0183     static const desc_fields s_v(parent::node_desc_fields(),63, //WARNING : take care of count.
0184 
0185       TOOLS_ARG_FIELD_DESC(width),
0186       TOOLS_ARG_FIELD_DESC(height),
0187       TOOLS_ARG_FIELD_DESC(left_margin),
0188       TOOLS_ARG_FIELD_DESC(right_margin),
0189       TOOLS_ARG_FIELD_DESC(bottom_margin),
0190       TOOLS_ARG_FIELD_DESC(top_margin),
0191       TOOLS_ARG_FIELD_DESC(depth),
0192       TOOLS_ARG_FIELD_DESC(down_margin),
0193       TOOLS_ARG_FIELD_DESC(up_margin),
0194       TOOLS_ARG_FIELD_DESC(colormap_visible),  //10
0195 
0196       TOOLS_ARG_FIELD_DESC_ENUMS_BEG(colormap_axis_labeling,2)
0197         TOOLS_ARG_ENUM(cells),
0198         TOOLS_ARG_ENUM(min_max)
0199       TOOLS_ARG_FIELD_DESC_ENUMS_END,
0200 
0201       TOOLS_ARG_FIELD_DESC(colormap_attached),
0202       TOOLS_ARG_FIELD_DESC(colormap_axis_visible),
0203 
0204       TOOLS_ARG_FIELD_DESC(title_up),
0205       TOOLS_ARG_FIELD_DESC(title_to_axis),
0206       TOOLS_ARG_FIELD_DESC(title_height),
0207       TOOLS_ARG_FIELD_DESC(title_automated),
0208 
0209       TOOLS_ARG_FIELD_DESC_ENUMS_BEG(title_hjust,3)
0210         "left",left,
0211         "center",center,
0212         "right",right
0213       TOOLS_ARG_FIELD_DESC_ENUMS_END,
0214 
0215       TOOLS_ARG_FIELD_DESC(title),
0216 
0217       TOOLS_ARG_FIELD_DESC(x_axis_enforced),  //20
0218       TOOLS_ARG_FIELD_DESC(x_axis_automated),
0219       TOOLS_ARG_FIELD_DESC(x_axis_min),
0220       TOOLS_ARG_FIELD_DESC(x_axis_max),
0221       TOOLS_ARG_FIELD_DESC(x_axis_is_log),
0222 
0223       TOOLS_ARG_FIELD_DESC(y_axis_enforced),
0224       TOOLS_ARG_FIELD_DESC(y_axis_automated),
0225       TOOLS_ARG_FIELD_DESC(y_axis_min),
0226       TOOLS_ARG_FIELD_DESC(y_axis_max),
0227       TOOLS_ARG_FIELD_DESC(y_axis_is_log),
0228 
0229       TOOLS_ARG_FIELD_DESC(z_axis_enforced),  //30
0230       TOOLS_ARG_FIELD_DESC(z_axis_automated),
0231       TOOLS_ARG_FIELD_DESC(z_axis_min),
0232       TOOLS_ARG_FIELD_DESC(z_axis_max),
0233       TOOLS_ARG_FIELD_DESC(z_axis_is_log),
0234 
0235       TOOLS_ARG_FIELD_DESC(value_top_margin),
0236       TOOLS_ARG_FIELD_DESC(value_bottom_margin),
0237       TOOLS_ARG_FIELD_DESC(value_bins_with_entries),
0238 
0239       TOOLS_ARG_FIELD_DESC(infos_width),
0240       TOOLS_ARG_FIELD_DESC(infos_x_margin),
0241       TOOLS_ARG_FIELD_DESC(infos_y_margin), //40
0242       TOOLS_ARG_FIELD_DESC(infos_what),
0243 
0244       TOOLS_ARG_FIELD_DESC(func2D_borders_visible),
0245       TOOLS_ARG_FIELD_DESC(theta),
0246       TOOLS_ARG_FIELD_DESC(phi),
0247       TOOLS_ARG_FIELD_DESC(tau),
0248 
0249       TOOLS_ARG_FIELD_DESC(legends_automated),
0250 
0251       TOOLS_ARG_FIELD_DESC_ENUMS_BEG(legends_origin,2)
0252         "unit_percent",unit_percent,
0253         "unit_axis",unit_axis
0254       TOOLS_ARG_FIELD_DESC_ENUMS_END,
0255 
0256       TOOLS_ARG_FIELD_DESC(legends_origin_unit),
0257       TOOLS_ARG_FIELD_DESC(legends_size),
0258       TOOLS_ARG_FIELD_DESC(legends_string), //50
0259 
0260       TOOLS_ARG_FIELD_DESC(shape_automated),
0261 
0262       TOOLS_ARG_FIELD_DESC_ENUMS_BEG(shape,2)
0263         "xy",xy,
0264         "xyz",xyz
0265       TOOLS_ARG_FIELD_DESC_ENUMS_END,
0266 
0267       TOOLS_ARG_FIELD_DESC(xy_depth),
0268       TOOLS_ARG_FIELD_DESC(curve_number_of_points),
0269 
0270       TOOLS_ARG_FIELD_DESC(number_of_levels),
0271       TOOLS_ARG_FIELD_DESC(levels),
0272 
0273       TOOLS_ARG_FIELD_DESC(data_light_on_automated),
0274 
0275       TOOLS_ARG_FIELD_DESC(primitives_enforced),
0276       TOOLS_ARG_FIELD_DESC(inner_frame_enforced),
0277 
0278       TOOLS_ARG_FIELD_DESC(title_box_width), //60
0279       TOOLS_ARG_FIELD_DESC(title_box_height),
0280       TOOLS_ARG_FIELD_DESC(title_box_x_margin),
0281       TOOLS_ARG_FIELD_DESC(title_box_y_margin)   //63
0282 
0283     );
0284     return s_v;
0285   }
0286   virtual bool touched() {
0287     if(parent::touched()) return true;
0288 
0289     if(background_style().touched()) return true;
0290     if(title_style().touched()) return true;
0291     if(infos_style().touched()) return true;
0292     if(title_box_style().touched()) return true;
0293     if(inner_frame_style().touched()) return true;
0294     if(grid_style().touched()) return true;
0295     if(wall_style().touched()) return true;
0296 
0297    {tools_vforit(style,m_bins_style,it) {if((*it).touched()) return true;}}
0298    {tools_vforit(style,m_errors_style,it) {if((*it).touched()) return true;}}
0299    {tools_vforit(style,m_func_style,it) {if((*it).touched()) return true;}}
0300    {tools_vforit(style,m_points_style,it) {if((*it).touched()) return true;}}
0301    {tools_vforit(style,m_left_hatch_style,it) {if((*it).touched()) return true;}}
0302    {tools_vforit(style,m_right_hatch_style,it) {if((*it).touched()) return true;}}
0303    {tools_vforit(style,m_legend_style,it) {if((*it).touched()) return true;}}
0304 
0305     return false;
0306   }
0307   virtual void reset_touched() {
0308     parent::reset_touched();
0309 
0310     background_style().reset_touched();
0311     title_style().reset_touched();
0312     infos_style().reset_touched();
0313     title_box_style().reset_touched();
0314     inner_frame_style().reset_touched();
0315     grid_style().reset_touched();
0316     wall_style().reset_touched();
0317 
0318    {tools_vforit(style,m_bins_style,it) (*it).reset_touched();}
0319    {tools_vforit(style,m_errors_style,it) (*it).reset_touched();}
0320    {tools_vforit(style,m_func_style,it) (*it).reset_touched();}
0321    {tools_vforit(style,m_points_style,it) (*it).reset_touched();}
0322    {tools_vforit(style,m_left_hatch_style,it) (*it).reset_touched();}
0323    {tools_vforit(style,m_right_hatch_style,it) (*it).reset_touched();}
0324    {tools_vforit(style,m_legend_style,it) (*it).reset_touched();}
0325   }
0326 
0327 private:
0328   void add_fields(){
0329     // if adding a field, look for reset_style(), set_from_style() and set_from_string()
0330     add_field(&width);
0331     add_field(&height);
0332     add_field(&left_margin);
0333     add_field(&right_margin);
0334     add_field(&bottom_margin);
0335     add_field(&top_margin);
0336     add_field(&depth);
0337     add_field(&down_margin);
0338     add_field(&up_margin);
0339 
0340     add_field(&title_up);
0341     add_field(&title_to_axis);
0342     add_field(&title_height);
0343     add_field(&title_automated);
0344     add_field(&title_hjust);
0345     add_field(&title);
0346 
0347     add_field(&x_axis_enforced);
0348     add_field(&x_axis_automated);
0349     add_field(&x_axis_min);
0350     add_field(&x_axis_max);
0351     add_field(&x_axis_is_log);
0352 
0353     add_field(&y_axis_enforced);
0354     add_field(&y_axis_automated);
0355     add_field(&y_axis_min);
0356     add_field(&y_axis_max);
0357     add_field(&y_axis_is_log);
0358 
0359     add_field(&z_axis_enforced);
0360     add_field(&z_axis_automated);
0361     add_field(&z_axis_min);
0362     add_field(&z_axis_max);
0363     add_field(&z_axis_is_log);
0364 
0365     add_field(&value_top_margin);
0366     add_field(&value_bottom_margin);
0367     add_field(&value_bins_with_entries);
0368 
0369     add_field(&infos_width);
0370     add_field(&infos_x_margin);
0371     add_field(&infos_y_margin);
0372     add_field(&infos_what);
0373 
0374     add_field(&title_box_width);
0375     add_field(&title_box_height);
0376     add_field(&title_box_x_margin);
0377     add_field(&title_box_y_margin);
0378 
0379     add_field(&func2D_borders_visible);
0380     add_field(&theta);
0381     add_field(&phi);
0382     add_field(&tau);
0383 
0384     add_field(&legends_automated);
0385     //add_field(&legends_attached_to_infos);
0386     add_field(&legends_origin);
0387     add_field(&legends_origin_unit);
0388     add_field(&legends_size);
0389     add_field(&legends_string);
0390 
0391     add_field(&shape_automated);
0392     add_field(&shape);
0393 
0394     add_field(&xy_depth);
0395     add_field(&curve_number_of_points);
0396     add_field(&number_of_levels);
0397     add_field(&levels);
0398     add_field(&data_light_on_automated);
0399     add_field(&primitives_enforced);
0400     add_field(&inner_frame_enforced);
0401   }
0402 public: //style
0403   void copy_style(const plotter& a_from) {  //used in sg::plots.
0404     ////////////////////////////////////////////
0405     ////////////////////////////////////////////
0406     ////////////////////////////////////////////
0407     shape_automated = a_from.shape_automated;
0408     shape = a_from.shape;
0409     xy_depth = a_from.xy_depth;
0410     curve_number_of_points = a_from.curve_number_of_points;
0411     value_top_margin = a_from.value_top_margin;
0412     value_bottom_margin = a_from.value_bottom_margin;
0413     value_bins_with_entries = a_from.value_bins_with_entries;
0414     infos_what = a_from.infos_what;
0415     infos_width = a_from.infos_width;
0416     //infos height is automatic.
0417     infos_x_margin = a_from.infos_x_margin;
0418     infos_y_margin = a_from.infos_y_margin;
0419 
0420     title_box_width = a_from.title_box_width;
0421     title_box_height = a_from.title_box_height;
0422     title_box_x_margin = a_from.title_box_x_margin;
0423     title_box_y_margin = a_from.title_box_y_margin;
0424 
0425     legends_automated = a_from.legends_automated;
0426     title_automated = a_from.title_automated;
0427     title = a_from.title;
0428     title_up = a_from.title_up;
0429     title_hjust = a_from.title_hjust;
0430 
0431     colormap_visible = a_from.colormap_visible;
0432     colormap_axis_labeling = a_from.colormap_axis_labeling;
0433     colormap_attached = a_from.colormap_attached;
0434     colormap_axis_visible = a_from.colormap_axis_visible;
0435 
0436     number_of_levels = a_from.number_of_levels;
0437     levels  = a_from.levels;
0438     data_light_on_automated = a_from.data_light_on_automated;
0439     primitives_enforced = a_from.primitives_enforced;
0440     inner_frame_enforced = a_from.inner_frame_enforced;
0441 
0442     ////////////////////////////////////////////
0443     ////////////////////////////////////////////
0444     ////////////////////////////////////////////
0445     x_axis_enforced = a_from.x_axis_enforced;
0446     x_axis_automated = a_from.x_axis_automated;
0447     x_axis_min = a_from.x_axis_min;
0448     x_axis_max = a_from.x_axis_max;
0449     x_axis_is_log = a_from.x_axis_is_log;
0450 
0451     y_axis_enforced = a_from.y_axis_enforced;
0452     y_axis_automated = a_from.y_axis_automated;
0453     y_axis_min = a_from.y_axis_min;
0454     y_axis_max = a_from.y_axis_max;
0455     y_axis_is_log = a_from.y_axis_is_log;
0456 
0457     z_axis_enforced = a_from.z_axis_enforced;
0458     z_axis_automated = a_from.z_axis_automated;
0459     z_axis_min = a_from.z_axis_min;
0460     z_axis_max = a_from.z_axis_max;
0461     z_axis_is_log = a_from.z_axis_is_log;
0462 
0463     /*
0464     m_x_axis = a_from.m_x_axis;
0465     m_y_axis = a_from.m_y_axis;
0466     m_z_axis = a_from.m_z_axis;
0467     m_cmap_axis = a_from.m_cmap_axis;
0468 
0469     */
0470     ////////////////////////////////////////////
0471     ////////////////////////////////////////////
0472     ////////////////////////////////////////////
0473 
0474     m_background_style = a_from.m_background_style;
0475     m_title_style = a_from.m_title_style;
0476     m_infos_style = a_from.m_infos_style;
0477     m_title_box_style = a_from.m_title_box_style;
0478     m_inner_frame_style = a_from.m_inner_frame_style;
0479     m_grid_style = a_from.m_grid_style;
0480     m_wall_style = a_from.m_wall_style;
0481 
0482     m_bins_style = a_from.m_bins_style;
0483     m_errors_style = a_from.m_errors_style;
0484     m_func_style = a_from.m_func_style;
0485     m_points_style = a_from.m_points_style;
0486     m_left_hatch_style = a_from.m_left_hatch_style;
0487     m_right_hatch_style = a_from.m_right_hatch_style;
0488     m_legend_style = a_from.m_legend_style;
0489   }
0490 
0491   void reset_style(bool a_geom = false) {
0492     //reset fields that are considered as part of the style.
0493 
0494     //::printf("debug : tools::sg::plotter::reset_style :\n");
0495 
0496     shape_automated = true;
0497     shape = xy;
0498 
0499     xy_depth = 0.01f;
0500     curve_number_of_points = 100;
0501     ////////////////////////////////////////////
0502     value_top_margin = 0.1f; //percent.  // CERN-PAW seems to have 0.1F and CERN-ROOT 0.05F.
0503     value_bottom_margin = 0.0f; //percent.
0504     value_bins_with_entries = true; //gopaw uses false.
0505 
0506     infos_what = s_infos_what_def();
0507     infos_width = 0.3f;
0508     //infos height is automatic.
0509     infos_x_margin = default_infos_margin(); //percent of width
0510     infos_y_margin = default_infos_margin(); //percent of height
0511 
0512     title_box_width = default_title_box_width();
0513     title_box_height = default_title_box_height();
0514     title_box_x_margin = default_title_box_x_margin(); //percent of width
0515     title_box_y_margin = default_title_box_y_margin(); //percent of height
0516 
0517     legends_automated = true;
0518 
0519     ////////////////////////////////////////////
0520 
0521     if(a_geom) {
0522     float xfac = 1.0F/20.0F; //0.05
0523     float yfac = 1.0F/20.0F; //0.05
0524 
0525     // Take PAW defaults :
0526     float XSIZ = 20 * xfac;    //1     //page width
0527     float YSIZ = 20 * yfac;    //1     //page height
0528     float XMGL = 2 * xfac;     //0.1   //left x margin (to data frame).
0529     float XMGR = 2 * xfac;     //0.1   //right y margin (to data frame).
0530     float YMGL = 2 * yfac;     //0.1   //low y margin (to data frame).
0531     float YMGU = 2 * yfac;     //0.1   //up y margin (to data frame).
0532     // Axes :
0533     float VSIZ = 0.28F * yfac; //0.014 //tick label character size.
0534     float XVAL = 0.4F * xfac;  //0.02 //x distance of y tick label to data frame.
0535     float YVAL = 0.4F * yfac;  //0.02 //y distance of x tick label to data frame.
0536     float XTIC = 0.3F * yfac;  //0.015 //y length of X axis ticks.
0537     float YTIC = 0.3F * xfac;  //0.015 //x length of Y axis ticks.
0538     float XLAB = 1.4F * xfac;  //0.07  //x distance of y title to data frame.
0539     float YLAB = 0.8F * yfac;  //0.04  //y distance of x title to data frame.
0540     float ASIZ = 0.28F * yfac; //0.014 // axis title (label) character size.
0541 
0542     float YHTI = 1.2F * yfac;  //0.06  //y distance of title to x axis.
0543     float TSIZ = 0.28F * yfac; //0.014 //title character size
0544 
0545     float zfac = 1.0F/20.0F; //0.05
0546     float ZSIZ = 20 * zfac;    //1     //page depth
0547     float ZMGD = 2 * zfac;     //0.1   //low y margin (to data frame).
0548     float ZMGU = 2 * zfac;     //0.1   //up y margin (to data frame).
0549 
0550     // Data area :
0551     //float wData = XSIZ-XMGL-XMGR;
0552     //float hData = YSIZ-YMGL-YMGU;
0553     //float dData = ZSIZ-ZMGD-ZMGU;
0554 
0555     width = XSIZ;
0556     height = YSIZ;
0557     depth = ZSIZ;
0558 
0559     left_margin = XMGL;
0560     right_margin = XMGR;
0561     bottom_margin = YMGL;
0562     top_margin = YMGU;
0563     down_margin = ZMGD;
0564     up_margin = ZMGU;
0565 
0566     title_to_axis = YHTI;
0567     title_height = TSIZ;
0568 
0569     if(shape.value()==xy) {
0570       m_x_axis.tick_length.value(XTIC);
0571       m_x_axis.label_to_axis.value(YVAL);
0572       m_x_axis.label_height.value(VSIZ);
0573       m_x_axis.title_to_axis.value(YLAB);
0574       m_x_axis.title_height.value(ASIZ);
0575 
0576       m_y_axis.tick_length.value(YTIC);
0577       m_y_axis.label_to_axis.value(XVAL);
0578       m_y_axis.label_height.value(VSIZ);
0579       m_y_axis.title_to_axis.value(XLAB);
0580       m_y_axis.title_height.value(ASIZ);
0581 
0582       //set anyway z axis :
0583       //m_z_axis.tick_length.value(YTIC);
0584       //m_z_axis.label_to_axis.value(XVAL);
0585       //m_z_axis.label_height.value(VSIZ);
0586       //m_z_axis.title_to_axis.value(XLAB);
0587       //m_z_axis.title_height.value(ASIZ);
0588 
0589       m_cmap_axis.tick_length.value(YTIC);
0590       m_cmap_axis.label_to_axis.value(XVAL);
0591       m_cmap_axis.label_height.value(VSIZ);
0592       m_cmap_axis.title_to_axis.value(XLAB);
0593       m_cmap_axis.title_height.value(ASIZ);
0594 
0595     } else { //xyz
0596       m_x_axis.tick_length.value(XTIC);
0597       m_x_axis.label_to_axis.value(YVAL);
0598       m_x_axis.label_height.value(VSIZ);
0599       m_x_axis.title_to_axis.value(YLAB);
0600       m_x_axis.title_height.value(ASIZ);
0601 
0602       m_y_axis.tick_length.value(XTIC);
0603       m_y_axis.label_to_axis.value(YVAL);
0604       m_y_axis.label_height.value(VSIZ);
0605       m_y_axis.title_to_axis.value(YLAB);
0606       m_y_axis.title_height.value(ASIZ);
0607 
0608       m_z_axis.tick_length.value(YTIC);
0609       m_z_axis.label_to_axis.value(XVAL);
0610       m_z_axis.label_height.value(VSIZ);
0611       m_z_axis.title_to_axis.value(XLAB);
0612       m_z_axis.title_height.value(ASIZ);
0613 
0614       m_cmap_axis.tick_length.value(XTIC);
0615       m_cmap_axis.label_to_axis.value(YVAL);
0616       m_cmap_axis.label_height.value(VSIZ);
0617       m_cmap_axis.title_to_axis.value(YLAB);
0618       m_cmap_axis.title_height.value(ASIZ);
0619 
0620     }
0621 
0622     }
0623 
0624     title_automated = true;
0625     title.value().clear();
0626     title_up = true;
0627     title_hjust = center;
0628 
0629     ////////////////////////////////////////////
0630     colormap_visible = true;
0631     colormap_axis_labeling = cells;
0632     colormap_attached = true;
0633     colormap_axis_visible = true;
0634 
0635     ////////////////////////////////////////////
0636     x_axis_enforced = false;
0637     x_axis_automated = true;
0638     x_axis_min = 0;
0639     x_axis_max = 1;
0640     x_axis_is_log = false;
0641 
0642     y_axis_enforced = false;
0643     y_axis_automated = true;
0644     y_axis_min = 0;
0645     y_axis_max = 1;
0646     y_axis_is_log = false;
0647 
0648     z_axis_enforced = false;
0649     z_axis_automated = true;
0650     z_axis_min = 0;
0651     z_axis_max = 1;
0652     z_axis_is_log = false;
0653 
0654     m_x_axis.reset_style();
0655     m_y_axis.reset_style();
0656     m_z_axis.reset_style();
0657 
0658     ////////////////////////////////////////////
0659     ////////////////////////////////////////////
0660     ////////////////////////////////////////////
0661     number_of_levels = 10;
0662     levels.clear();
0663     data_light_on_automated = true;
0664     primitives_enforced = false;
0665     inner_frame_enforced = false;
0666 
0667     ////////////////////////////////////////////
0668     // setup styles :
0669     ////////////////////////////////////////////
0670 
0671     m_title_style = text_style();
0672     m_infos_style = text_style();
0673     m_title_box_style = text_style();
0674     m_background_style = style();
0675     m_wall_style = style();
0676     m_inner_frame_style = style();
0677     m_grid_style = style();
0678 
0679     m_title_style.color = colorf_black();
0680     m_title_style.font = font_hershey();
0681     m_title_style.font_modeling = font_filled;
0682     m_title_style.encoding = encoding_PAW();
0683 
0684     m_background_style.back_color = colorf_white();
0685     m_background_style.line_width = 0; //no border
0686     m_background_style.color = colorf_black(); //border
0687 
0688     m_inner_frame_style.color = colorf_black();
0689     m_inner_frame_style.line_pattern = line_solid;
0690 
0691     m_grid_style.color = colorf_black();
0692     m_grid_style.line_pattern = line_dashed;
0693 
0694     m_infos_style.font = font_hershey();
0695     m_infos_style.font_modeling = font_filled;
0696     m_infos_style.encoding = encoding_PAW();
0697 
0698     m_title_box_style.visible = false;
0699     m_title_box_style.font = font_hershey();
0700     m_title_box_style.font_modeling = font_filled;
0701     m_title_box_style.encoding = encoding_PAW();
0702 
0703    {tools_vforit(style,m_bins_style,it) {
0704       (*it) = style();
0705       (*it).modeling = modeling_top_lines();
0706       (*it).marker_size = 5; //for bins1D of profile.
0707     }}
0708    {tools_vforit(style,m_errors_style,it) {(*it) = style();(*it).visible = false;}}
0709    {tools_vforit(style,m_func_style,it) (*it) = style();}
0710    {tools_vforit(style,m_points_style,it) {
0711       (*it) = style();
0712       (*it).modeling = modeling_markers(); //for gopaw.
0713     }}
0714    {tools_vforit(style,m_left_hatch_style,it) {(*it) = style();(*it).visible = false;}}
0715    {tools_vforit(style,m_right_hatch_style,it) {(*it) = style();(*it).visible = false;}}
0716    {tools_vforit(style,m_legend_style,it) {(*it) = style();(*it).visible = false;}}
0717 
0718   }
0719 
0720   void gopaw_reset_style() {
0721    {tools_vforit(style,m_bins_style,it) {
0722       (*it) = style();
0723       (*it).modeling = modeling_top_lines();
0724       (*it).marker_size = 5; //for bins1D of profile.
0725     }}
0726 
0727    {tools_vforit(style,m_errors_style,it) {(*it) = style();(*it).visible = false;}}
0728    {tools_vforit(style,m_func_style,it) (*it) = style();}
0729    {tools_vforit(style,m_points_style,it) {
0730       (*it) = style();
0731       (*it).modeling = modeling_markers(); //for gopaw.
0732     }}
0733    {tools_vforit(style,m_left_hatch_style,it) {(*it) = style();(*it).visible = false;}}
0734    {tools_vforit(style,m_right_hatch_style,it) {(*it) = style();(*it).visible = false;}}
0735    {tools_vforit(style,m_legend_style,it) {(*it) = style();(*it).visible = false;}}
0736   }
0737 
0738   typedef std::pair<std::string,std::string> style_item_t;
0739   typedef std::vector<style_item_t> style_t;
0740   bool set_from_style(std::ostream& a_out,const style_t& a_style) {
0741     tools_vforcit(style_item_t,a_style,it) {
0742       const std::string& key = (*it).first;
0743       const std::string& sv = (*it).second;
0744       //::printf("debug : plotter::set_from_style : key \"%s\" \"%s\"\n",key.c_str(),sv.c_str());
0745       //if(key=="reset") {}
0746       if(key=="tag") {
0747         // key to find back <plotter_style>s.
0748         // see also :
0749         //   xml_style::load_plotter_style()
0750         //   xml_style::find_plotter_styles()
0751 
0752 
0753       //width,height,depth : could set from style (for exa for lego).
0754       } else if(key=="width") {
0755         float v;
0756         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0757         width = v;
0758       } else if(key=="height") {
0759         float v;
0760         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0761         height = v;
0762       } else if(key=="depth") {
0763         float v;
0764         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0765         depth = v;
0766 
0767       } else if(key=="left_margin") {
0768         float v;
0769         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0770         left_margin = v;
0771       } else if(key=="right_margin") {
0772         float v;
0773         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0774         right_margin = v;
0775       } else if(key=="bottom_margin") {
0776         float v;
0777         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0778         bottom_margin = v;
0779       } else if(key=="top_margin") {
0780         float v;
0781         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0782         top_margin = v;
0783       } else if(key=="down_margin") {
0784         float v;
0785         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0786         down_margin = v;
0787       } else if(key=="up_margin") {
0788         float v;
0789         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0790         up_margin = v;
0791 
0792       } else if(key=="title") {
0793         title = sv;
0794       } else if(key=="title_up") {
0795         bool v;
0796         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0797         title_up = v;
0798       } else if(key=="title_to_axis") {
0799         float v;
0800         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0801         title_to_axis = v;
0802       } else if(key=="title_height") {
0803         float v;
0804         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0805         title_height = v;
0806       } else if(key=="title_automated") {
0807         bool v;
0808         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0809         title_automated = v;
0810       } else if(key=="title_hjust") {
0811         hjust v;
0812         if(!shjust(sv,v))
0813           {style_failed(a_out,key,sv);return false;}
0814         title_hjust = v;
0815 
0816       } else if(key=="x_axis_enforced") {
0817         bool v;
0818         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0819         x_axis_enforced = v;
0820       } else if(key=="x_axis_automated") {
0821         bool v;
0822         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0823         x_axis_automated = v;
0824       } else if(key=="x_axis_min") {
0825         float v;
0826         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0827         x_axis_min = v;
0828       } else if(key=="x_axis_max") {
0829         float v;
0830         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0831         x_axis_max = v;
0832       } else if(key=="x_axis_is_log") {
0833         bool v;
0834         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0835         x_axis_is_log = v;
0836 
0837       } else if(key=="y_axis_enforced") {
0838         bool v;
0839         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0840         y_axis_enforced = v;
0841       } else if(key=="y_axis_automated") {
0842         bool v;
0843         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0844         y_axis_automated = v;
0845       } else if(key=="y_axis_min") {
0846         float v;
0847         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0848         y_axis_min = v;
0849       } else if(key=="y_axis_max") {
0850         float v;
0851         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0852         y_axis_max = v;
0853       } else if(key=="y_axis_is_log") {
0854         bool v;
0855         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0856         y_axis_is_log = v;
0857 
0858       } else if(key=="z_axis_enforced") {
0859         bool v;
0860         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0861         z_axis_enforced = v;
0862       } else if(key=="z_axis_automated") {
0863         bool v;
0864         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0865         z_axis_automated = v;
0866       } else if(key=="z_axis_min") {
0867         float v;
0868         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0869         z_axis_min = v;
0870       } else if(key=="z_axis_max") {
0871         float v;
0872         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0873         z_axis_max = v;
0874       } else if(key=="z_axis_is_log") {
0875         bool v;
0876         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0877         z_axis_is_log = v;
0878 
0879       } else if(key=="value_top_margin") {
0880         float v;
0881         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0882         value_top_margin = v;
0883       } else if(key=="value_bottom_margin") {
0884         float v;
0885         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0886         value_bottom_margin = v;
0887       } else if(key=="value_bins_with_entries") {
0888         float v;
0889         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0890         value_bins_with_entries = v;
0891       } else if(key=="infos_width") {
0892         float v;
0893         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0894         infos_width = v;
0895       } else if(key=="infos_x_margin") {
0896         float v;
0897         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0898         infos_x_margin = v;
0899       } else if(key=="infos_y_margin") {
0900         float v;
0901         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0902         infos_y_margin = v;
0903 
0904       } else if(key=="title_box_width") {
0905         float v;
0906         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0907         title_box_width = v;
0908       } else if(key=="title_box_height") {
0909         float v;
0910         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0911         title_box_height = v;
0912       } else if(key=="title_box_x_margin") {
0913         float v;
0914         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0915         title_box_x_margin = v;
0916       } else if(key=="title_box_y_margin") {
0917         float v;
0918         if(!to<float>(sv,v)) {style_failed(a_out,key,sv);return false;}
0919         title_box_y_margin = v;
0920 
0921       } else if(key=="infos_what") {
0922         infos_what = sv;
0923 
0924 //      } else if(key=="legends_visible") {
0925 //        bool v;
0926 //        if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0927 //        legends_visible = v;
0928       } else if(key=="legends_automated") {
0929         bool v;
0930         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0931         legends_automated = v;
0932 //    } else if(key=="legends_attached_to_infos") {
0933 //      bool v;
0934 //      if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0935 //      legends_attached_to_infos = v;
0936       } else if(key=="legends_origin") {
0937         vec2f v;
0938         if(!sto(sv,v)) {style_failed(a_out,key,sv);return false;}
0939         legends_origin.setValue(v);
0940       } else if(key=="legends_size") {
0941         vec2f v;
0942         if(!sto(sv,v)) {style_failed(a_out,key,sv);return false;}
0943         legends_size.setValue(v);
0944       } else if(key=="legends_origin_unit") {
0945         unit_type v;
0946         if(!sto(sv,v)) {style_failed(a_out,key,sv);return false;}
0947         legends_origin_unit.setValue(v);
0948 
0949       } else if(key=="shape_automated") {
0950         bool v;
0951         if(!to(sv,v)) {style_failed(a_out,key,sv);return false;}
0952         shape_automated = v;
0953 
0954       } else if(key=="shape") {
0955         if(sv=="xy") {
0956           shape = xy;
0957         } else if(sv=="xyz") {
0958           shape = xyz;
0959         } else {
0960           style_failed(a_out,key,sv);return false;
0961         }
0962 
0963       //legends_string
0964       //legends_color
0965       //legends_string mf_string
0966       //legends_color mf_vec<colorf,float>
0967 
0968       } else {
0969         a_out << "tools::sg::plotter::set_from_style : unknown key " << key << "." << std::endl;
0970       }
0971     }
0972     return true;
0973   }
0974 
0975 protected:
0976   bool s2axis(const std::string& a_s,sg::axis*& a_axis) {
0977          if(a_s=="x_axis")        {a_axis = &(x_axis());return true;}
0978     else if(a_s=="y_axis")        {a_axis = &(y_axis());return true;}
0979     else if(a_s=="z_axis")        {a_axis = &(z_axis());return true;}
0980     else if(a_s=="colormap_axis") {a_axis = &(colormap_axis());return true;}
0981     else {
0982       a_axis = 0;
0983       return false;
0984     }
0985   }
0986 public:
0987   bool set_from_string(std::ostream& a_out,cmaps_t& a_cmaps,const std::string& a_field,const std::string& a_value) {
0988     // see also plotter_style file.
0989     std::string::size_type pos = a_field.find('.');
0990     bool status = true;
0991     if(pos==std::string::npos) {
0992       style_t _style;
0993       _style.push_back(style_item_t(a_field,a_value));
0994       if(!set_from_style(a_out,_style)) status = false;
0995     } else {
0996       std::vector<std::string> _words;
0997       words(a_field,".",false,_words);
0998       if(_words.size()==2) {
0999         const std::string& word0 = _words[0];
1000         const std::string& word1 = _words[1];
1001         std::string _s = word1+" "+std::string(a_value);
1002         sg::axis* _axis = 0;
1003              if(word0=="background_style")  {if(!background_style().from_string(a_out,a_cmaps,_s)) status = false;}
1004         else if(word0=="title_style")       {if(!title_style().from_string(a_out,a_cmaps,_s)) status = false;}
1005         else if(word0=="infos_style")       {if(!infos_style().from_string(a_out,a_cmaps,_s)) status = false;}
1006         else if(word0=="title_box_style")   {if(!title_box_style().from_string(a_out,a_cmaps,_s)) status = false;}
1007         else if(word0=="inner_frame_style") {if(!inner_frame_style().from_string(a_out,a_cmaps,_s)) status = false;}
1008         else if(word0=="grid_style")        {if(!grid_style().from_string(a_out,a_cmaps,_s)) status = false;}
1009         else if(word0=="wall_style")        {if(!wall_style().from_string(a_out,a_cmaps,_s)) status = false;}
1010         else if(!s2axis(word0,_axis)) {
1011           a_out << "tools::sg::plotter::set_from_string : unexpected axis field " << word0 << "." << std::endl;
1012           status = false;
1013         } else {
1014           style_t _style;
1015           _style.push_back(style_item_t(word1,a_value));
1016           if(!_axis->set_from_style(a_out,_style)) status = false;
1017         }
1018       } else if(_words.size()==3) {
1019         const std::string& word0 = _words[0];
1020         const std::string& word1 = _words[1];
1021         const std::string& word2 = _words[2];
1022         sg::axis* _axis = 0;
1023         std::string _s = word2+" "+std::string(a_value);
1024         unsigned int index;
1025         bool to_status = to<unsigned int>(word1,index);
1026         if(word0=="bins_style") {
1027           if(!to_status) {
1028             a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
1029             status = false;
1030           } else {
1031             if(!bins_style(index).from_string(a_out,a_cmaps,_s)) status = false;
1032           }
1033         } else if(word0=="errors_style") {
1034           if(!to_status) {
1035             a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
1036             status = false;
1037           } else {
1038             if(!errors_style(index).from_string(a_out,a_cmaps,_s)) status = false;
1039           }
1040         } else if(word0=="func_style") {
1041           if(!to_status) {
1042             a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
1043             status = false;
1044           } else {
1045             if(!func_style(index).from_string(a_out,a_cmaps,_s)) status = false;
1046           }
1047         } else if(word0=="points_style") {
1048           if(!to_status) {
1049             a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
1050             status = false;
1051           } else {
1052             if(!points_style(index).from_string(a_out,a_cmaps,_s)) status = false;
1053           }
1054         } else if(word0=="left_hatch_style") {
1055           if(!to_status) {
1056             a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
1057             status = false;
1058           } else {
1059             if(!left_hatch_style(index).from_string(a_out,a_cmaps,_s)) status = false;
1060           }
1061         } else if(word0=="right_hatch_style") {
1062           if(!to_status) {
1063             a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
1064             status = false;
1065           } else {
1066             if(!right_hatch_style(index).from_string(a_out,a_cmaps,_s)) status = false;
1067           }
1068         } else if(word0=="legend_style") {
1069           if(!to_status) {
1070             a_out << "tools::sg::plotter::set_from_string : bad string " << word1 << " for an index." << std::endl;
1071             status = false;
1072           } else {
1073             if(!legend_style(index).from_string(a_out,a_cmaps,_s)) status = false;
1074           }
1075         } else if(!s2axis(word0,_axis)) {
1076           a_out << "tools::sg::plotter::set_from_string : unexpected axis field " << word0 << "." << std::endl;
1077           status = false;
1078         } else {
1079                if(word1=="line_style")   {if(!_axis->line_style().from_string(a_out,a_cmaps,_s)) status = false;}
1080           else if(word1=="ticks_style")  {if(!_axis->ticks_style().from_string(a_out,a_cmaps,_s)) status = false;}
1081           else if(word1=="labels_style") {if(!_axis->labels_style().from_string(a_out,a_cmaps,_s)) status = false;}
1082           else if(word1=="mag_style")    {if(!_axis->mag_style().from_string(a_out,a_cmaps,_s)) status = false;}
1083           else if(word1=="title_style")  {if(!_axis->title_style().from_string(a_out,a_cmaps,_s)) status = false;}
1084           else {
1085             a_out << "tools::sg::plotter::set_from_string : unexpected style field " << word1 << "." << std::endl;
1086             status = false;
1087           }
1088         }
1089       } else {
1090         a_out << "tools::sg::plotter::set_from_string : unexpected number of fields " << _words.size() << "." << std::endl;
1091         status = false;
1092       }
1093     }
1094     return status;
1095   }
1096 
1097   void set_encoding(const std::string& a_value) {
1098     title_style().encoding = a_value;
1099     infos_style().encoding = a_value;
1100     title_box_style().encoding = a_value;
1101     m_x_axis.set_encoding(a_value);
1102     m_y_axis.set_encoding(a_value);
1103     m_z_axis.set_encoding(a_value);
1104     m_cmap_axis.set_encoding(a_value);
1105   }
1106   void set_encoding_none() {set_encoding(encoding_none());}
1107 
1108   void print_available_customization(std::ostream& a_out) const {
1109     a_out << "plotter fields :" << std::endl;
1110    {const std::vector<field_desc>& fds = node_desc_fields();
1111     tools_vforcit(field_desc,fds,itd) {
1112       a_out << " " << (*itd).name() << ", class " << (*itd).cls() << std::endl;
1113     }}
1114     a_out << std::endl;
1115 
1116     a_out << "plotter data available styles :" << std::endl;
1117     a_out << " bins_style.<uint>, class style" << std::endl;
1118     a_out << " errors_style.<uint>, class style" << std::endl;
1119     a_out << " func_style.<uint>, class style" << std::endl;
1120     a_out << " points_style.<uint>, class style" << std::endl;
1121     a_out << " left_hatch_style.<uint>, class style" << std::endl;
1122     a_out << " right_hatch_style.<uint>, class style" << std::endl;
1123     a_out << " legend_style.<uint>, class style" << std::endl;
1124     a_out << std::endl;
1125 
1126     a_out << "plotter available styles :" << std::endl;
1127     a_out << " title_style, class text_style" << std::endl;
1128     a_out << " infos_style, class text_style" << std::endl;
1129     a_out << " title_box_style, class text_style" << std::endl;
1130     a_out << " background_style, class style" << std::endl;
1131     a_out << " inner_frame_style, class style" << std::endl;
1132     a_out << " grid_style, class style" << std::endl;
1133     a_out << " wall_style, class style" << std::endl;
1134     a_out << std::endl;
1135 
1136     a_out << "plotter available axes :" << std::endl;
1137     a_out << " x_axis" << std::endl;
1138     a_out << " y_axis" << std::endl;
1139     a_out << " z_axis" << std::endl;
1140     a_out << " colormap_axis" << std::endl;
1141     a_out << std::endl;
1142 
1143     a_out << "plotter axis available styles :" << std::endl;
1144     a_out << " title_style, class text_style" << std::endl;
1145     a_out << " labels_style, class text_style" << std::endl;
1146     a_out << " mag_style, class text_style" << std::endl;
1147     a_out << " line_style, class line_style" << std::endl;
1148     a_out << " ticks_style, class line_style" << std::endl;
1149     a_out << std::endl;
1150 
1151     a_out << "plotter style class fields :" << std::endl;
1152    {style _style;
1153     const std::vector<field_desc>& fds = _style.node_desc_fields();
1154     tools_vforcit(field_desc,fds,itd) {
1155       a_out << " " << (*itd).name() << ", class " << (*itd).cls() << std::endl;
1156     }}
1157     a_out << std::endl;
1158 
1159     a_out << "plotter text_style class fields :" << std::endl;
1160    {text_style _style;
1161     const std::vector<field_desc>& fds = _style.node_desc_fields();
1162     tools_vforcit(field_desc,fds,itd) {
1163       a_out << " " << (*itd).name() << ", class " << (*itd).cls() << std::endl;
1164     }}
1165     a_out << std::endl;
1166 
1167     a_out << "plotter line_style class fields :" << std::endl;
1168    {line_style _style;
1169     const std::vector<field_desc>& fds = _style.node_desc_fields();
1170     tools_vforcit(field_desc,fds,itd) {
1171       a_out << " " << (*itd).name() << ", class " << (*itd).cls() << std::endl;
1172     }}
1173     a_out << std::endl;
1174   }
1175 protected:
1176   void style_failed(std::ostream& a_out,const std::string& a_key,const std::string& a_value) {
1177     a_out << "tools::sg::plotter::set_from_style :"
1178           << " failed for key " << sout(a_key)
1179           << " and value " << sout(a_value) << "."
1180           << std::endl;
1181   }
1182 public:
1183   virtual void render(render_action& a_action) {
1184     if(touched()) {
1185       update_sg(a_action.out());
1186       reset_touched();
1187     }
1188     m_group.render(a_action);
1189   }
1190   virtual void pick(pick_action& a_action) {
1191     if(touched()) {
1192       update_sg(a_action.out());
1193       reset_touched();
1194     }
1195     nodekit_pick(a_action,m_group,this);
1196   }
1197   virtual void search(search_action& a_action) {
1198     if(touched()) {
1199       update_sg(a_action.out());
1200       reset_touched();
1201     }
1202     node::search(a_action);
1203     if(a_action.done()) return;
1204     m_group.search(a_action);
1205   }
1206   virtual void bbox(bbox_action& a_action) {
1207     if(touched()) {
1208       update_sg(a_action.out());
1209       reset_touched();
1210     }
1211     m_group.bbox(a_action);
1212   }
1213 
1214   virtual bool write(write_action& a_action) {
1215     if(touched()) {
1216       update_sg(a_action.out());
1217       reset_touched();
1218     }
1219     //if(!write_fields(a_action)) return false;
1220     return m_group.write(a_action);
1221   }
1222 public:
1223   plotter(const base_freetype& a_ttf)
1224   :parent()
1225   ,width(0)
1226   ,height(0)
1227   ,left_margin(0)
1228   ,right_margin(0)
1229   ,bottom_margin(0)
1230   ,top_margin(0)
1231   ,depth(0)
1232   ,down_margin(0)
1233   ,up_margin(0)
1234 
1235   ,title_up(true)
1236   ,title_to_axis(0) //set below.
1237   ,title_height(0)  //set below.
1238   ,title_automated(true)
1239   ,title_hjust(center)
1240   ,title("")
1241 
1242   ,colormap_visible(true)
1243   ,colormap_axis_labeling(cells)
1244   ,colormap_attached(true)
1245   ,colormap_axis_visible(true)
1246 
1247   ,x_axis_enforced(false)
1248   ,x_axis_automated(true)
1249   ,x_axis_min(0)
1250   ,x_axis_max(1)
1251   ,x_axis_is_log(false)
1252   ,y_axis_enforced(false)
1253   ,y_axis_automated(true)
1254   ,y_axis_min(0)
1255   ,y_axis_max(1)
1256   ,y_axis_is_log(false)
1257   ,z_axis_enforced(false)
1258   ,z_axis_automated(true)
1259   ,z_axis_min(0)
1260   ,z_axis_max(1)
1261   ,z_axis_is_log(false)
1262 
1263   ,value_top_margin(0.1f) //percent. // CERN-PAW seems to have 0.1F and CERN-ROOT 0.05F.
1264   ,value_bottom_margin(0.0f) //percent.
1265   ,value_bins_with_entries(true)
1266 
1267   ,infos_width(0.3f) //percent of width
1268   ,infos_x_margin(default_infos_margin()) //percent of width
1269   ,infos_y_margin(default_infos_margin()) //percent of height
1270   ,infos_what(s_infos_what_def())
1271 
1272   ,title_box_width(default_title_box_width())       //percent of width
1273   ,title_box_height(default_title_box_height())     //percent of height
1274   ,title_box_x_margin(default_title_box_x_margin()) //percent of width
1275   ,title_box_y_margin(default_title_box_y_margin()) //percent of height
1276 
1277   ,func2D_borders_visible(true)
1278   ,theta(30)
1279   ,phi(30)
1280   ,tau(-90)
1281 
1282   ,legends_automated(true)
1283   //,legends_attached_to_infos(true)
1284   // if legends_attached_to_infos is false and
1285   // unit_percent, legends_origin is the position
1286   // of the upper right corner of the legends
1287   // relative to the upper right corner of the plotter
1288   // with positive values going in reverse x,y axis.
1289   //,legends_origin(vec2f(0.01f,0.01f))
1290   //,legends_origin_unit(unit_percent)
1291   //,legends_size(vec2f(0.2f,0.16f))
1292   //legends_string
1293 
1294   ,shape_automated(true)
1295   ,shape(xy)
1296 
1297   ,xy_depth(0.01f)
1298   ,curve_number_of_points(100)
1299   ,data_light_on_automated(true)
1300   ,primitives_enforced(false)
1301   ,inner_frame_enforced(false)
1302   ,number_of_levels(10)
1303   ,levels()
1304 
1305   ,m_ttf(a_ttf)
1306 
1307   ,m_cmap_axis(a_ttf)
1308   ,m_x_axis(a_ttf)
1309   ,m_y_axis(a_ttf)
1310   ,m_z_axis(a_ttf)
1311 
1312   ,m_shape(xy)
1313   {
1314     m_cmaps[style_default_colormap::s_default()] = style_default_colormap(); //costly
1315 
1316     add_fields();
1317     reset_style(true);
1318 
1319     init_sg(); // skeleton of scene graph.
1320   }
1321   virtual ~plotter(){
1322     clear_plottables();
1323     clear_primitives();
1324     clear_cmaps();
1325   }
1326 public:
1327   plotter(const plotter& a_from)
1328   :parent(a_from)
1329   ,width(a_from.width)
1330   ,height(a_from.height)
1331   ,left_margin(a_from.left_margin)
1332   ,right_margin(a_from.right_margin)
1333   ,bottom_margin(a_from.bottom_margin)
1334   ,top_margin(a_from.top_margin)
1335   ,depth(a_from.depth)
1336   ,down_margin(a_from.down_margin)
1337   ,up_margin(a_from.up_margin)
1338 
1339   ,title_up(a_from.title_up)
1340   ,title_to_axis(a_from.title_to_axis)
1341   ,title_height(a_from.title_height)
1342   ,title_automated(a_from.title_automated)
1343   ,title_hjust(a_from.title_hjust)
1344   ,title(a_from.title)
1345 
1346   ,colormap_visible(a_from.colormap_visible)
1347   ,colormap_axis_labeling(a_from.colormap_axis_labeling)
1348   ,colormap_attached(a_from.colormap_attached)
1349   ,colormap_axis_visible(a_from.colormap_axis_visible)
1350 
1351   ,x_axis_enforced(a_from.x_axis_enforced)
1352   ,x_axis_automated(a_from.x_axis_automated)
1353   ,x_axis_min(a_from.x_axis_min)
1354   ,x_axis_max(a_from.x_axis_max)
1355   ,x_axis_is_log(a_from.x_axis_is_log)
1356   ,y_axis_enforced(a_from.y_axis_enforced)
1357   ,y_axis_automated(a_from.y_axis_automated)
1358   ,y_axis_min(a_from.y_axis_min)
1359   ,y_axis_max(a_from.y_axis_max)
1360   ,y_axis_is_log(a_from.y_axis_is_log)
1361   ,z_axis_enforced(a_from.z_axis_enforced)
1362   ,z_axis_automated(a_from.z_axis_automated)
1363   ,z_axis_min(a_from.z_axis_min)
1364   ,z_axis_max(a_from.z_axis_max)
1365   ,z_axis_is_log(a_from.z_axis_is_log)
1366   ,value_top_margin(a_from.value_top_margin)
1367   ,value_bottom_margin(a_from.value_bottom_margin)
1368   ,value_bins_with_entries(a_from.value_bins_with_entries)
1369 
1370   ,infos_width(a_from.infos_width)
1371   ,infos_x_margin(a_from.infos_x_margin)
1372   ,infos_y_margin(a_from.infos_y_margin)
1373   ,infos_what(a_from.infos_what)
1374 
1375   ,title_box_width(a_from.title_box_width)
1376   ,title_box_height(a_from.title_box_height)
1377   ,title_box_x_margin(a_from.title_box_x_margin)
1378   ,title_box_y_margin(a_from.title_box_y_margin)
1379 
1380   ,func2D_borders_visible(a_from.func2D_borders_visible)
1381   ,theta(a_from.theta)
1382   ,phi(a_from.phi)
1383   ,tau(a_from.tau)
1384 
1385   ,legends_automated(a_from.legends_automated)
1386 //,legends_attached_to_infos(a_from.legends_attached_to_infos)
1387   ,legends_origin(a_from.legends_origin)
1388   ,legends_origin_unit(a_from.legends_origin_unit)
1389   ,legends_size(a_from.legends_size)
1390   ,legends_string(a_from.legends_string)
1391 
1392   ,shape_automated(a_from.shape_automated)
1393   ,shape(a_from.shape)
1394 
1395   ,xy_depth(a_from.xy_depth)
1396   ,curve_number_of_points(a_from.curve_number_of_points)
1397   ,data_light_on_automated(a_from.data_light_on_automated)
1398   ,primitives_enforced(a_from.primitives_enforced)
1399   ,inner_frame_enforced(a_from.inner_frame_enforced)
1400   ,number_of_levels(a_from.number_of_levels)
1401   ,levels(a_from.levels)
1402 
1403   ,m_ttf(a_from.m_ttf)
1404 
1405   ,m_background_sep()
1406 
1407   ,m_cmap_axis(m_ttf)
1408   ,m_x_axis(m_ttf)
1409   ,m_y_axis(m_ttf)
1410   ,m_z_axis(m_ttf)
1411 
1412   ,m_etc_sep(a_from.m_etc_sep)
1413 
1414   ,m_shape(a_from.m_shape)
1415 
1416   ,m_bins_style(a_from.m_bins_style)
1417   ,m_errors_style(a_from.m_errors_style)
1418   ,m_func_style(a_from.m_func_style)
1419   ,m_points_style(a_from.m_points_style)
1420   ,m_left_hatch_style(a_from.m_left_hatch_style)
1421   ,m_right_hatch_style(a_from.m_right_hatch_style)
1422   ,m_legend_style(a_from.m_legend_style)
1423 
1424   ,m_title_style(a_from.m_title_style)
1425   ,m_infos_style(a_from.m_infos_style)
1426   ,m_title_box_style(a_from.m_title_box_style)
1427   ,m_background_style(a_from.m_background_style)
1428   ,m_wall_style(a_from.m_wall_style)
1429   ,m_inner_frame_style(a_from.m_inner_frame_style)
1430   ,m_grid_style(a_from.m_grid_style)
1431   ,m_cmaps(a_from.m_cmaps)
1432   {
1433     add_fields();
1434 
1435     // to copy axes styles :
1436     m_x_axis = a_from.m_x_axis;
1437     m_y_axis = a_from.m_y_axis;
1438     m_z_axis = a_from.m_z_axis;
1439     m_cmap_axis = a_from.m_cmap_axis;
1440 
1441     init_sg(); // skeleton of scene graph.
1442 
1443    {tools_vforcit(plottable*,a_from.m_plottables,it) {m_plottables.push_back((*it)->copy());}}
1444    {tools_vforcit(plotprim*,a_from.m_primitives,it) {m_primitives.push_back((*it)->copy());}}
1445   }
1446   plotter& operator=(const plotter& a_from){
1447     parent::operator=(a_from);
1448     if(&a_from==this) return *this;
1449 
1450     width = a_from.width;
1451     height = a_from.height;
1452     left_margin = a_from.left_margin;
1453     right_margin = a_from.right_margin;
1454     bottom_margin = a_from.bottom_margin;
1455     top_margin = a_from.top_margin;
1456     depth = a_from.depth;
1457     down_margin = a_from.down_margin;
1458     up_margin = a_from.up_margin;
1459 
1460     title_up = a_from.title_up;
1461     title_to_axis = a_from.title_to_axis;
1462     title_height = a_from.title_height;
1463     title_automated = a_from.title_automated;
1464     title_hjust = a_from.title_hjust;
1465     title = a_from.title;
1466 
1467     colormap_visible = a_from.colormap_visible;
1468     colormap_axis_labeling = a_from.colormap_axis_labeling;
1469     colormap_attached = a_from.colormap_attached;
1470     colormap_axis_visible = a_from.colormap_axis_visible;
1471 
1472     x_axis_enforced = a_from.x_axis_enforced;
1473     x_axis_automated = a_from.x_axis_automated;
1474     x_axis_min = a_from.x_axis_min;
1475     x_axis_max = a_from.x_axis_max;
1476     x_axis_is_log = a_from.x_axis_is_log;
1477     y_axis_enforced = a_from.y_axis_enforced;
1478     y_axis_automated = a_from.y_axis_automated;
1479     y_axis_min = a_from.y_axis_min;
1480     y_axis_max = a_from.y_axis_max;
1481     y_axis_is_log = a_from.y_axis_is_log;
1482     z_axis_enforced = a_from.z_axis_enforced;
1483     z_axis_automated = a_from.z_axis_automated;
1484     z_axis_min = a_from.z_axis_min;
1485     z_axis_max = a_from.z_axis_max;
1486     z_axis_is_log = a_from.z_axis_is_log;
1487     value_top_margin = a_from.value_top_margin;
1488     value_bottom_margin = a_from.value_bottom_margin;
1489     value_bins_with_entries = a_from.value_bins_with_entries;
1490 
1491     infos_width = a_from.infos_width;
1492     infos_x_margin = a_from.infos_x_margin;
1493     infos_y_margin = a_from.infos_y_margin;
1494     infos_what = a_from.infos_what;
1495 
1496     title_box_width = a_from.title_box_width;
1497     title_box_height = a_from.title_box_height;
1498     title_box_x_margin = a_from.title_box_x_margin;
1499     title_box_y_margin = a_from.title_box_y_margin;
1500 
1501     func2D_borders_visible = a_from.func2D_borders_visible;
1502     theta = a_from.theta;
1503     phi = a_from.phi;
1504     tau = a_from.tau;
1505 
1506     legends_automated = a_from.legends_automated;
1507   //legends_attached_to_infos = a_from.legends_attached_to_infos;
1508     legends_origin = a_from.legends_origin;
1509     legends_origin_unit = a_from.legends_origin_unit;
1510     legends_size = a_from.legends_size;
1511     legends_string = a_from.legends_string;
1512 
1513     shape_automated = a_from.shape_automated;
1514     shape = a_from.shape;
1515 
1516     xy_depth = a_from.xy_depth;
1517     curve_number_of_points = a_from.curve_number_of_points;
1518     number_of_levels = a_from.number_of_levels;
1519     levels = a_from.levels;
1520     data_light_on_automated = a_from.data_light_on_automated;
1521     primitives_enforced = a_from.primitives_enforced;
1522     inner_frame_enforced = a_from.inner_frame_enforced;
1523 
1524     m_etc_sep = a_from.m_etc_sep;
1525 
1526     m_bins_style = a_from.m_bins_style;
1527     m_errors_style = a_from.m_errors_style;
1528     m_func_style = a_from.m_func_style;
1529     m_points_style = a_from.m_points_style;
1530     m_left_hatch_style = a_from.m_left_hatch_style;
1531     m_right_hatch_style = a_from.m_right_hatch_style;
1532     m_legend_style = a_from.m_legend_style;
1533 
1534     m_title_style = a_from.m_title_style;
1535     m_infos_style = a_from.m_infos_style;
1536     m_title_box_style = a_from.m_title_box_style;
1537     m_background_style = a_from.m_background_style;
1538     m_wall_style = a_from.m_wall_style;
1539     m_inner_frame_style = a_from.m_inner_frame_style;
1540     m_grid_style = a_from.m_grid_style;
1541 
1542     // to copy axes styles :
1543     m_x_axis = a_from.m_x_axis;
1544     m_y_axis = a_from.m_y_axis;
1545     m_z_axis = a_from.m_z_axis;
1546     m_cmap_axis = a_from.m_cmap_axis;
1547 
1548     m_cmaps = a_from.m_cmaps;
1549 
1550     clear_plottables();
1551     clear_primitives();
1552     clear_todels();
1553 
1554    {tools_vforcit(plottable*,a_from.m_plottables,it) {m_plottables.push_back((*it)->copy());}}
1555    {tools_vforcit(plotprim*,a_from.m_primitives,it) {m_primitives.push_back((*it)->copy());}}
1556 
1557     return *this;
1558   }
1559 public:
1560   size_t number_of_plottables() const {
1561     size_t number = 0;
1562     tools_vforcit(plottable*,m_plottables,it) {
1563       plottable* object = *it;
1564       if(!object) continue;
1565       if(!object->is_valid()) continue;
1566       // take into account all valid plottables, even the one without a representation.
1567       number++;
1568     }
1569     return number;
1570   }
1571 
1572 #define TOOLS_SG_PLOTTER_NUMBER_OF(a__what) \
1573   size_t number_of_plotted_##a__what##s() const {\
1574     size_t number = 0;\
1575     tools_vforcit(plottable*,m_plottables,it) {\
1576       plottable* object = *it;\
1577       if(!object) continue;\
1578       if(!object->is_valid()) continue;\
1579       if(safe_cast<plottable,a__what>(*object)) number++;\
1580     }\
1581     return number;\
1582   }
1583 
1584   TOOLS_SG_PLOTTER_NUMBER_OF(bins1D)
1585   TOOLS_SG_PLOTTER_NUMBER_OF(bins2D)
1586   TOOLS_SG_PLOTTER_NUMBER_OF(points2D)
1587   TOOLS_SG_PLOTTER_NUMBER_OF(points3D)
1588   TOOLS_SG_PLOTTER_NUMBER_OF(func1D)
1589   TOOLS_SG_PLOTTER_NUMBER_OF(func2D)
1590 
1591 #undef TOOLS_SG_PLOTTER_NUMBER_OF
1592 
1593   void plotted_object_names(std::vector<std::string>& a_names) const {
1594     a_names.clear();
1595     tools_vforcit(plottable*,m_plottables,it) {
1596       plottable* object = *it;
1597       if(!object) continue;
1598       if(!object->is_valid()) continue;
1599       // take into account all valid plottables, even the one without a representation.
1600       a_names.push_back(object->name());
1601     }
1602   }
1603 
1604 public: //public
1605   const torche& data_light() const {return m_data_light;}
1606   torche& data_light() {return m_data_light;}
1607 
1608   matrix& tsf() {return m_tsf;}
1609 
1610   const separator& etc_sep() const {return m_etc_sep;}
1611   separator& etc_sep() {return m_etc_sep;}
1612 
1613   const std::vector<plottable*>& plottables() const {return m_plottables;}
1614 
1615   void add_plottable(plottable* a_p) {
1616     //WARNING : it takes ownership of a_p object.
1617     m_plottables.push_back(a_p);
1618     touch();
1619   }
1620 
1621   void prep_plottable(plottable* a_p) {
1622     //WARNING : it takes ownership of a_p object.
1623     m_plottables.insert(m_plottables.begin(),a_p);
1624     touch();
1625   }
1626 
1627   void transfer_plottables(std::vector<plottable*>& a_to) {
1628     a_to = m_plottables;
1629     m_plottables.clear(); //do not delete plottables !
1630     touch();
1631   }
1632 
1633   template <class T>
1634   bool remove_plottables() {
1635     bool found = false;
1636     std::vector<plottable*>::iterator it;
1637     for(it=m_plottables.begin();it!=m_plottables.end();) {
1638       plottable* object = *it;
1639       if(object && safe_cast<plottable,T>(*object)) {
1640         it = m_plottables.erase(it);
1641         delete object;
1642         found = true;
1643       } else {
1644         it++;
1645       }
1646     }
1647     if(found) touch();
1648     return found;
1649   }
1650 
1651   void add_primitive(plotprim* a_prim) {m_primitives.push_back(a_prim);touch();}
1652 
1653   void transfer_primitives(std::vector<plotprim*>& a_to) {
1654     a_to = m_primitives;
1655     m_primitives.clear(); //do not delete primitives !
1656     touch();
1657   }
1658 
1659   template <class T>
1660   void add_todel(T* a_obj) {
1661     m_todel_group.add(new sg::holder<T>(a_obj));
1662   }
1663   template <class T>
1664   void remove_todels(){
1665     remove_holders<T>(m_todel_group.children());
1666   }
1667   void transfer_todels(std::vector<node*>& a_to) { //used in sg::plots.
1668     m_todel_group.transfer(a_to);
1669   }
1670   void add_node_todel(node* a_node) { //used in sg::plots.
1671     m_todel_group.add(a_node);
1672   }
1673 
1674   void clear() {
1675     clear_plottables();
1676     clear_primitives();
1677     clear_todels();
1678 
1679     legends_string.clear();
1680     legends_origin_unit.clear();
1681     legends_origin.clear();
1682     legends_size.clear();
1683 
1684     //wallEnforced.setValue(false);
1685     //gridEnforced.setValue(false);
1686     primitives_enforced = false;
1687     inner_frame_enforced = false;
1688 
1689     //getEtcSeparator()->removeAllChildren();
1690     //getEtcDataSeparator()->removeAllChildren();
1691   }
1692 
1693   const sg::axis& x_axis() const {return m_x_axis;}
1694   sg::axis& x_axis() {return m_x_axis;}
1695 
1696   const sg::axis& y_axis() const {return m_y_axis;}
1697   sg::axis& y_axis() {return m_y_axis;}
1698 
1699   const sg::axis& z_axis() const {return m_z_axis;}
1700   sg::axis& z_axis() {return m_z_axis;}
1701 
1702   const sg::axis& colormap_axis() const {return m_cmap_axis;}
1703   sg::axis& colormap_axis() {return m_cmap_axis;}
1704 
1705   text_style& title_style() {return m_title_style;}
1706   style& background_style() {return m_background_style;}
1707   style& wall_style() {return m_wall_style;}
1708   style& inner_frame_style() {return m_inner_frame_style;}
1709   style& grid_style() {return m_grid_style;}
1710   text_style& infos_style() {return m_infos_style;}
1711   text_style& title_box_style() {return m_title_box_style;}
1712 
1713   style& bins_style(size_t a_index) {
1714     size_t sz = m_bins_style.size();
1715     if(a_index>=sz) {
1716       //012345 sz=6
1717       //         9 a_index wanted
1718       //      6789 loop
1719       for(size_t index=sz;index<=a_index;index++) {
1720         m_bins_style.push_back(style());
1721         m_bins_style.back().modeling = modeling_top_lines();
1722         m_bins_style.back().marker_size = 5; //for bins1D of profile.
1723       }
1724     }
1725     return m_bins_style[a_index];
1726   }
1727 
1728   style& errors_style(size_t a_index) {
1729     size_t sz = m_errors_style.size();
1730     if(a_index>=sz) {
1731       for(size_t index=sz;index<=a_index;index++) {
1732         m_errors_style.push_back(style());
1733         m_errors_style.back().visible = false;
1734       }
1735     }
1736     return m_errors_style[a_index];
1737   }
1738 
1739   style& func_style(size_t a_index) {
1740     size_t sz = m_func_style.size();
1741     if(a_index>=sz) {
1742       for(size_t index=sz;index<=a_index;index++) {
1743         m_func_style.push_back(style());
1744       }
1745     }
1746     return m_func_style[a_index];
1747   }
1748 
1749   style& points_style(size_t a_index) {
1750     size_t sz = m_points_style.size();
1751     if(a_index>=sz) {
1752       //012345 sz=6
1753       //         9 a_index wanted
1754       //      6789 loop
1755       for(size_t index=sz;index<=a_index;index++) {
1756         m_points_style.push_back(style());
1757         m_points_style.back().modeling = modeling_markers(); //for gopaw.
1758       }
1759     }
1760     return m_points_style[a_index];
1761   }
1762 
1763   style& left_hatch_style(size_t a_index) {
1764     size_t sz = m_left_hatch_style.size();
1765     if(a_index>=sz) {
1766       for(size_t index=sz;index<=a_index;index++) {
1767         m_left_hatch_style.push_back(style());
1768         m_left_hatch_style.back().visible = false;
1769       }
1770     }
1771     return m_left_hatch_style[a_index];
1772   }
1773 
1774   style& right_hatch_style(size_t a_index) {
1775     size_t sz = m_right_hatch_style.size();
1776     if(a_index>=sz) {
1777       for(size_t index=sz;index<=a_index;index++) {
1778         m_right_hatch_style.push_back(style());
1779         m_right_hatch_style.back().visible = false;
1780       }
1781     }
1782     return m_right_hatch_style[a_index];
1783   }
1784 
1785   style& legend_style(size_t a_index) {
1786     size_t sz = m_legend_style.size();
1787     if(a_index>=sz) {
1788       for(size_t index=sz;index<=a_index;index++) {
1789         m_legend_style.push_back(style());
1790       }
1791     }
1792     return m_legend_style[a_index];
1793   }
1794 
1795   void bins_modelings(size_t a_index,std::vector<std::string>& a_opts) {
1796     a_opts.clear();
1797     update_shape();
1798     if(m_shape==xy) {
1799       size_t ibins = 0;
1800       tools_vforcit(plottable*,m_plottables,it) {
1801         plottable* object = *it;
1802         if(!object) continue;
1803         if(bins1D* b1 = safe_cast<plottable,bins1D>(*object)) {
1804           //update_bins1D_xy
1805           if(a_index==ibins) {
1806             if(b1->is_profile()) {
1807               a_opts.push_back(modeling_points());
1808               a_opts.push_back(modeling_markers());
1809               return;
1810             } else {
1811               a_opts.push_back(modeling_boxes());
1812               a_opts.push_back(modeling_wire_boxes());
1813               a_opts.push_back(modeling_bar_chart());
1814               a_opts.push_back(modeling_top_lines());
1815               a_opts.push_back(modeling_points());
1816               a_opts.push_back(modeling_markers());
1817               return;
1818             }
1819           }
1820           ibins++;
1821         } if(safe_cast<plottable,bins2D>(*object)) {
1822           //update_bins2D_xy
1823           if(a_index==ibins) {
1824             a_opts.push_back(modeling_curve());
1825             a_opts.push_back(modeling_filled_curve());
1826             a_opts.push_back(modeling_boxes());
1827             a_opts.push_back(modeling_wire_boxes());
1828             a_opts.push_back(modeling_solid());
1829             a_opts.push_back(modeling_points());
1830             return;
1831           }
1832           ibins++;
1833         }
1834       }
1835     }
1836   }
1837 
1838   bool xx_2_yy(const vec3f& a_pos,vec3f& a_out) const {
1839     // a_pos is in data frame NDC coordinates.
1840    {float XSIZ = width;
1841     float XMGL = left_margin;
1842     float XMGR = right_margin;
1843     float wData = XSIZ-XMGL-XMGR;
1844     a_out[0] = wData*a_pos[0];}
1845 
1846    {float YSIZ = height;
1847     float YMGL = bottom_margin;
1848     float YMGU = top_margin;
1849     float hData = YSIZ-YMGL-YMGU;
1850     a_out[1] = hData*a_pos[1];}
1851 
1852    {float ZSIZ = depth;
1853     float ZMGD = down_margin;
1854     float ZMGU = up_margin;
1855     float dData = ZSIZ-ZMGD-ZMGU;
1856     a_out[2] = dData*a_pos[2];}
1857 
1858     return true;
1859   }
1860 
1861   bool data_frame_2_vp(const vec3f& a_pos,vec3f& a_vp) const {
1862     // a_pos is in data frame NDC coordinates.
1863     // a_vp is in viewport/screen coordinates (in [0,1]).
1864    {float XSIZ = width;
1865     float XMGL = left_margin;
1866     float XMGR = right_margin;
1867     float wData = XSIZ-XMGL-XMGR;
1868     if(XSIZ==0.0F) {
1869       //SoDebugError::postInfo("tools::sg;:plotter::data_frame_2_vp","XSIZ is 0");
1870       return false;
1871     }
1872     a_vp[0] = (wData*a_pos[0] + XMGL)/XSIZ;}
1873 
1874    {float YSIZ = height;
1875     float YMGL = bottom_margin;
1876     float YMGU = top_margin;
1877     float hData = YSIZ-YMGL-YMGU;
1878     if(YSIZ==0.0F) {
1879       //SoDebugError::postInfo("tools::sg;:plotter::data_frame_2_vp","YSIZ is 0");
1880       return false;
1881     }
1882     a_vp[1] = (hData*a_pos[1] + YMGL)/YSIZ;}
1883 
1884    {float ZSIZ = depth;
1885     float ZMGD = down_margin;
1886     float ZMGU = up_margin;
1887     float dData = ZSIZ-ZMGD-ZMGU;
1888     if(ZSIZ==0.0F) {
1889       //SoDebugError::postInfo("tools::sg;:plotter::data_frame_2_vp","ZSIZ is 0");
1890       return false;
1891     }
1892     a_vp[2] = (dData*a_pos[2] + ZMGD)/ZSIZ;}
1893 
1894     return true;
1895   }
1896 
1897   bool vp_2_data_frame(const vec3f& a_vp,vec3f& a_pos) const {
1898     // a_vp is in viewport/screen coordinates (in [0,1]).
1899     // a_pos is in data frame NDC coordinates.
1900 
1901    {float XSIZ = width;
1902     float XMGL = left_margin;
1903     float XMGR = right_margin;
1904     float wData = XSIZ-XMGL-XMGR;
1905     if(wData==0.0F) {
1906       //SoDebugError::postInfo("tools::sg;:plotter::vp_2_data_frame","wData is 0");
1907       return false;
1908     }
1909     a_pos[0] = (a_vp[0]*XSIZ - XMGL)/wData;}
1910 
1911    {float YSIZ = height;
1912     float YMGL = bottom_margin;
1913     float YMGU = top_margin;
1914     float hData = YSIZ-YMGL-YMGU;
1915     if(hData==0.0F) {
1916       //SoDebugError::postInfo("tools::sg;:plotter::vp_2_data_frame","hData is 0");
1917       return false;
1918     }
1919     a_pos[1] = (a_vp[1]*YSIZ - YMGL)/hData;}
1920 
1921    {float ZSIZ = depth;
1922     float ZMGD = down_margin;
1923     float ZMGU = up_margin;
1924     float dData = ZSIZ-ZMGD-ZMGU;
1925     if(dData==0.0F) {
1926       //SoDebugError::postInfo("tools::sg;:plotter::vp_2_data_frame","dData is 0");
1927       return false;
1928     }
1929     a_pos[2] = (a_vp[2]*ZSIZ - ZMGD)/dData;}
1930 
1931     return true;
1932   }
1933 
1934   bool data_frame_2_axis(const vec3f& aDF,vec3f& a_pos) const {
1935     // aDF is in data area coordinates. In [0,1][0,1][0,1].
1936     // a_pos is in axes coordinates.
1937 
1938     // Assume that axes min,max,is_log are up to date.
1939 
1940    {float mn = m_x_axis.minimum_value;
1941     float mx = m_x_axis.maximum_value;
1942     bool lg = m_x_axis.is_log;
1943     if(lg) {
1944       mn = fpow(10,mn);
1945       mx = fpow(10,mx);
1946     }
1947     a_pos[0] = verify_log_inv(aDF[0],mn,mx-mn,lg);}
1948 
1949    {float mn = m_y_axis.minimum_value;
1950     float mx = m_y_axis.maximum_value;
1951     bool lg = m_y_axis.is_log;
1952     if(lg) {
1953       mn = fpow(10,mn);
1954       mx = fpow(10,mx);
1955     }
1956     a_pos[1] = verify_log_inv(aDF[1],mn,mx-mn,lg);}
1957 
1958    {float mn = m_z_axis.minimum_value;
1959     float mx = m_z_axis.maximum_value;
1960     bool lg = m_z_axis.is_log;
1961     if(lg) {
1962       mn = fpow(10,mn);
1963       mx = fpow(10,mx);
1964     }
1965     a_pos[2] = verify_log_inv(aDF[2],mn,mx-mn,lg);}
1966 
1967     return true;
1968   }
1969 
1970   bool axis_2_data_frame(const vec3f& a_pos,vec3f& aDF) const {
1971     // a_pos is in axes coordinates.
1972     // aDF in data area coordinate. In [0,1][0,1][0,1].
1973 
1974     // Assume that axes min,max,logScale are up to date.
1975 
1976    {float mn = m_x_axis.minimum_value;
1977     float mx = m_x_axis.maximum_value;
1978     if(mx==mn) {
1979       //SoDebugError::postInfo
1980       //  ("tools::sg;:plotter::axis_2_data_frame","x : mn (%g) == mx (%g)",mn,mx);
1981       return false;
1982     }
1983     bool lg = m_x_axis.is_log;
1984     if(lg) {
1985       if(mn<=0) {
1986         //SoDebugError::postInfo
1987         //  ("tools::sg;:plotter::axis_2_data_frame","x log but mn (%g) <=0",mn);
1988         return false;
1989       }
1990       if(mx<=0) {
1991         //SoDebugError::postInfo
1992         //  ("tools::sg;:plotter::axis_2_data_frame","x log but mx (%g) <=0",mx);
1993         return false;
1994       }
1995       mn = flog10(mn);
1996       mx = flog10(mx);
1997     }
1998     aDF[0] = verify_log(a_pos[0],mn,mx-mn,lg);}
1999 
2000    {float mn = m_y_axis.minimum_value;
2001     float mx = m_y_axis.maximum_value;
2002     if(mx==mn) {
2003       //SoDebugError::postInfo
2004       //  ("tools::sg;:plotter::axis_2_data_frame","y : mn (%g) == mx (%g)",mn,mx);
2005       return false;
2006     }
2007     bool lg = m_y_axis.is_log;
2008     if(lg) {
2009       if(mn<=0) {
2010         //SoDebugError::postInfo
2011         //  ("tools::sg;:plotter::axis_2_data_frame","y log but mn (%g) <=0",mn);
2012         return false;
2013       }
2014       if(mx<=0) {
2015         //SoDebugError::postInfo
2016         //  ("tools::sg;:plotter::axis_2_data_frame","y log but mx (%g) <=0",mx);
2017         return false;
2018       }
2019       mn = flog10(mn);
2020       mx = flog10(mx);
2021     }
2022     aDF[1] = verify_log(a_pos[1],mn,mx-mn,lg);}
2023 
2024    {float mn = m_z_axis.minimum_value;
2025     float mx = m_z_axis.maximum_value;
2026     if(mx==mn) {
2027       //SoDebugError::postInfo
2028       //  ("tools::sg;:plotter::axis_2_data_frame","z : mn (%g) == mx (%g)",mn,mx);
2029       return false;
2030     }
2031     bool lg = m_z_axis.is_log;
2032     if(lg) {
2033       if(mn<=0) {
2034         //SoDebugError::postInfo
2035         //  ("tools::sg;:plotter::axis_2_data_frame","z log but mn (%g) <=0",mn);
2036         return false;
2037       }
2038       if(mx<=0) {
2039         //SoDebugError::postInfo
2040         //  ("tools::sg;:plotter::axis_2_data_frame","z log but mx (%g) <=0",mx);
2041         return false;
2042       }
2043       mn = flog10(mn);
2044       mx = flog10(mx);
2045     }
2046     aDF[2] = verify_log(a_pos[2],mn,mx-mn,lg);}
2047 
2048     return true;
2049   }
2050 
2051   bool axis_2_vp(const vec3f& a_pos,vec3f& a_vp) const {
2052     // a_pos is in axes coordinates.
2053     // a_vp is in viewport/screen coordinates (in [0,1]).
2054     vec3f d; // In data area coordinate. In [0,1][0,1][0,1].
2055     if(!axis_2_data_frame(a_pos,d)) return false;
2056     return data_frame_2_vp(d,a_vp);
2057   }
2058 
2059   bool vp_2_axis(const vec3f& a_vp,vec3f& a_pos) const {
2060     // a_vp is in viewport/screen coordinates (in [0,1]).
2061     // a_pos is in axes coordinates.
2062     vec3f d; // In data area coordinate. In [0,1][0,1][0,1].
2063     if(!vp_2_data_frame(a_vp,d)) return false;
2064     return data_frame_2_axis(d,a_pos);
2065   }
2066 
2067 public:
2068   void set_axes_modeling(const std::string& a_v){
2069     m_x_axis.modeling = a_v;
2070     m_y_axis.modeling = a_v;
2071     m_z_axis.modeling = a_v;
2072     m_cmap_axis.modeling = a_v;
2073   }
2074 
2075   void set_axes_color(const colorf& a_color){
2076     m_x_axis.line_style().color = a_color;
2077     m_x_axis.ticks_style().color = a_color;
2078     m_x_axis.labels_style().color = a_color;
2079     m_x_axis.title_style().color = a_color;
2080     m_x_axis.mag_style().color = a_color;
2081 
2082     m_y_axis.line_style().color = a_color;
2083     m_y_axis.ticks_style().color = a_color;
2084     m_y_axis.labels_style().color = a_color;
2085     m_y_axis.title_style().color = a_color;
2086     m_y_axis.mag_style().color = a_color;
2087 
2088     m_z_axis.line_style().color = a_color;
2089     m_z_axis.ticks_style().color = a_color;
2090     m_z_axis.labels_style().color = a_color;
2091     m_z_axis.title_style().color = a_color;
2092     m_z_axis.mag_style().color = a_color;
2093 
2094     m_cmap_axis.line_style().color = a_color;
2095     m_cmap_axis.ticks_style().color = a_color;
2096     m_cmap_axis.labels_style().color = a_color;
2097     m_cmap_axis.title_style().color = a_color;
2098     m_cmap_axis.mag_style().color = a_color;
2099   }
2100 
2101   void set_axes_text_scale(float a_v){
2102     m_x_axis.labels_style().scale = a_v;
2103     m_x_axis.title_style().scale = a_v;
2104     m_x_axis.mag_style().scale = a_v;
2105 
2106     m_y_axis.labels_style().scale = a_v;
2107     m_y_axis.title_style().scale = a_v;
2108     m_y_axis.mag_style().scale = a_v;
2109 
2110     m_z_axis.labels_style().scale = a_v;
2111     m_z_axis.title_style().scale = a_v;
2112     m_z_axis.mag_style().scale = a_v;
2113 
2114     m_cmap_axis.labels_style().scale = a_v;
2115     m_cmap_axis.title_style().scale = a_v;
2116     m_cmap_axis.mag_style().scale = a_v;
2117   }
2118 
2119   void set_axes_line_pattern(unsigned short a_v){
2120     m_x_axis.line_style().pattern = a_v;
2121     m_y_axis.line_style().pattern = a_v;
2122     m_z_axis.line_style().pattern = a_v;
2123     m_cmap_axis.line_style().pattern = a_v;
2124   }
2125 
2126   void set_axes_line_width(int a_v){
2127     m_x_axis.line_style().width = float(a_v);
2128     m_y_axis.line_style().width = float(a_v);
2129     m_z_axis.line_style().width = float(a_v);
2130     m_cmap_axis.line_style().width = float(a_v);
2131 
2132     m_x_axis.ticks_style().width = float(a_v);
2133     m_y_axis.ticks_style().width = float(a_v);
2134     m_z_axis.ticks_style().width = float(a_v);
2135     m_cmap_axis.ticks_style().width = float(a_v);
2136   }
2137 
2138   void set_axes_tick_length(float a_v){
2139     m_x_axis.tick_length = a_v;
2140     m_y_axis.tick_length = a_v;
2141     m_z_axis.tick_length = a_v;
2142     m_cmap_axis.tick_length = a_v;
2143   }
2144 
2145   void set_axes_title_height(float a_v){
2146     m_x_axis.title_height = a_v;
2147     m_y_axis.title_height = a_v;
2148     m_z_axis.title_height = a_v;
2149     m_cmap_axis.title_height = a_v;
2150   }
2151 
2152   void set_axes_label_height(float a_v){
2153     m_x_axis.label_height = a_v;
2154     m_y_axis.label_height = a_v;
2155     m_z_axis.label_height = a_v;
2156     m_cmap_axis.label_height = a_v;
2157   }
2158 
2159   void set_axes_font_modeling(font_modeling a_v){
2160     m_x_axis.labels_style().font_modeling = a_v;
2161     m_x_axis.title_style().font_modeling = a_v;
2162     m_x_axis.mag_style().font_modeling = a_v;
2163 
2164     m_y_axis.labels_style().font_modeling = a_v;
2165     m_y_axis.title_style().font_modeling = a_v;
2166     m_y_axis.mag_style().font_modeling = a_v;
2167 
2168     m_z_axis.labels_style().font_modeling = a_v;
2169     m_z_axis.title_style().font_modeling = a_v;
2170     m_z_axis.mag_style().font_modeling = a_v;
2171 
2172     m_cmap_axis.labels_style().font_modeling = a_v;
2173     m_cmap_axis.title_style().font_modeling = a_v;
2174     m_cmap_axis.mag_style().font_modeling = a_v;
2175   }
2176 
2177   void set_font_modeling(font_modeling a_v){
2178     set_axes_font_modeling(a_v);
2179     title_style().font_modeling = a_v;
2180     infos_style().font_modeling = a_v;
2181     title_box_style().font_modeling = a_v;
2182   }
2183 protected:
2184   void init_sg(){
2185 
2186     m_group.add(new noderef(m_background_sep));
2187     m_group.add(new noderef(m_cmap_sep));
2188     m_group.add(new noderef(m_infos_title_sep));
2189     m_group.add(new noderef(m_infos_sep));
2190     m_group.add(new noderef(m_legend_sep));
2191     m_group.add(new noderef(m_title_box_sep));
2192     m_group.add(new noderef(m_tsf));
2193     m_group.add(new noderef(m_layout));
2194     m_group.add(new noderef(m_title_sep));
2195     m_group.add(new noderef(m_x_axis_sep));
2196     m_group.add(new noderef(m_y_axis_sep));
2197     m_group.add(new noderef(m_z_axis_sep));
2198     m_group.add(new noderef(m_grid_sep));
2199     m_group.add(new noderef(m_data_sep));
2200     m_group.add(new noderef(m_primitives_sep));
2201 
2202     m_cmap_sep.add(new noderef(m_cmap_matrix));
2203     m_cmap_sep.add(new noderef(m_cmap_cells_sep));
2204     m_cmap_sep.add(new noderef(m_cmap_axis_matrix));
2205     m_cmap_sep.add(new noderef(m_cmap_axis));
2206 
2207     m_x_axis_sep.add(new noderef(m_x_axis_matrix));
2208     m_x_axis_sep.add(new noderef(m_x_axis));
2209 
2210     m_y_axis_sep.add(new noderef(m_y_axis_matrix));
2211     m_y_axis_sep.add(new noderef(m_y_axis));
2212 
2213     m_z_axis_sep.add(new noderef(m_z_axis_matrix));
2214     m_z_axis_sep.add(new noderef(m_z_axis));
2215 
2216     m_data_sep.add(new noderef(m_data_light));
2217     m_data_sep.add(new noderef(m_data_matrix));
2218 
2219     m_data_sep.add(new noderef(m_bins_sep));
2220     m_data_sep.add(new noderef(m_errors_sep));
2221     m_data_sep.add(new noderef(m_func_sep));
2222     m_data_sep.add(new noderef(m_points_sep));
2223     m_data_sep.add(new noderef(m_inner_frame_sep));
2224     m_data_sep.add(new noderef(m_etc_sep));
2225   }
2226 
2227   void update_layout(){
2228     float XSIZ = width;
2229     float XMGL = left_margin;
2230     float XMGR = right_margin;
2231     float wData = XSIZ-XMGL-XMGR;
2232 
2233     float YSIZ = height;
2234     float YMGL = bottom_margin;
2235     float YMGU = top_margin;
2236     float hData = YSIZ-YMGL-YMGU;
2237 
2238     float ZSIZ = depth;
2239     float ZMGD = down_margin;
2240     float ZMGU = up_margin;
2241     float dData = ZSIZ-ZMGD-ZMGU;
2242 
2243    {mat4f& mtx = m_layout.mtx.value();
2244     mtx.set_identity();
2245 
2246     if(m_shape==xy) {
2247       // in rep primitives (0,0) is the lower left corner
2248       // of the data area square;
2249       mtx.mul_translate(-XSIZ/2+XMGL,-YSIZ/2+YMGL,0);
2250 
2251       if(data_light_on_automated.value()) m_data_light.on = false;
2252       vec3f dir(0,0,-1);
2253       m_data_light.direction = dir;
2254 
2255     } else { //xyz
2256       //printf("debug : update_layout : X : %g %g %g %g\n",
2257       //  XSIZ,XMGL,XMGR,wData);
2258       //printf("debug : update_layout : Y : %g %g %g %g\n",
2259       //  YSIZ,YMGL,YMGU,hData);
2260 
2261       // global transformation (to have a "lego" layout) :
2262       //  translate so that the center of the scene
2263       //  is the center of the data area cube;
2264       //  then rotate to have lego 3D layout.
2265 
2266       mtx.mul_rotate(1,0,0,theta*fdeg2rad());
2267       mtx.mul_rotate(0,1,0,phi*fdeg2rad());
2268       mtx.mul_rotate(1,0,0,tau*fdeg2rad());
2269 
2270       // To place as CERN-PAW default.
2271       // In CERN-PAW, it is the projection
2272       // which fits in the (XSIZ,XMGL,XMGR)/(YSIZ,YMGL,YMGU)
2273       // page setup.
2274 
2275       rotf r1(vec3f(1,0,0),theta * fdeg2rad());
2276       rotf r2(vec3f(0,1,0),phi * fdeg2rad());
2277       rotf r3(vec3f(1,0,0),tau * fdeg2rad());
2278 
2279       rotf r = r1*r2*r3;
2280       mat4f _m;
2281       r.value(_m);
2282 
2283       float xmn = -0.5F*wData;
2284       float ymn = -0.5F*hData;
2285       float zmn = -0.5F*dData;
2286       float xmx =  0.5F*wData;
2287       float ymx =  0.5F*hData;
2288       float zmx =  0.5F*dData;
2289 
2290       box3f _box;
2291       float x,y,z;
2292       // zmn face :
2293      {x = xmn;y = ymn;z = zmn;
2294       _m.mul_3f(x,y,z);
2295       _box.extend_by(x,y,z);}
2296      {x = xmx;y = ymn;z = zmn;
2297       _m.mul_3f(x,y,z);
2298       _box.extend_by(x,y,z);}
2299      {x = xmx;y = ymx;z = zmn;
2300       _m.mul_3f(x,y,z);
2301       _box.extend_by(x,y,z);}
2302      {x = xmn;y = ymx;z = zmn;
2303       _m.mul_3f(x,y,z);
2304       _box.extend_by(x,y,z);}
2305 
2306       // zmx face :
2307      {x = xmn;y = ymn;z = zmx;
2308       _m.mul_3f(x,y,z);
2309       _box.extend_by(x,y,z);}
2310      {x = xmx;y = ymn;z = zmx;
2311       _m.mul_3f(x,y,z);
2312       _box.extend_by(x,y,z);}
2313      {x = xmx;y = ymx;z = zmx;
2314       _m.mul_3f(x,y,z);
2315       _box.extend_by(x,y,z);}
2316      {x = xmn;y = ymx;z = zmx;
2317       _m.mul_3f(x,y,z);
2318       _box.extend_by(x,y,z);}
2319 
2320       float xfac = _box.mx()[0]-_box.mn()[0];
2321       float yfac = _box.mx()[1]-_box.mn()[1];
2322       float zfac = _box.mx()[2]-_box.mn()[2];
2323 
2324       //cube setup (driven by hData) :
2325       mtx.mul_scale(hData/xfac,hData/yfac,hData/zfac);
2326 
2327       mtx.mul_translate(-wData/2,-hData/2,-dData/2); //Applied first.
2328 
2329       if(data_light_on_automated.value()) m_data_light.on = true;
2330      {vec3f dir(1,-1,-10);
2331       float dx,dy,dz;dir.value(dx,dy,dz);
2332       mat4f inv;
2333       if(mtx.invert(inv)) {
2334         inv.mul_dir_3f(dx,dy,dz);
2335         m_data_light.direction = vec3f(dx,dy,dz);
2336       }}
2337     }}
2338 
2339    {mat4f& mtx = m_data_matrix.mtx.value();
2340     mtx.set_identity();
2341     if(m_shape==xy) {
2342       mtx.mul_scale(wData,hData,1); //z size decided with xy_depth
2343     } else if(m_shape==xyz) {
2344       mtx.mul_scale(wData,hData,dData);
2345     }}
2346 
2347   }
2348 
2349 public:
2350   void update_sg(std::ostream& a_out) {
2351 
2352     update_shape();
2353     update_axes_data(a_out);
2354 
2355     update_background();
2356     update_layout();
2357 
2358     // roundtrip over plottables to check if they are valids. Done first.
2359     unsigned int nplottables = 0;
2360     unsigned int nbins = 0;
2361     unsigned int npoints = 0;
2362     unsigned int nfunc = 0;
2363    {tools_vforit(plottable*,m_plottables,it) {
2364       plottable* object = *it;
2365       if(!object) continue;
2366       if(!object->is_valid()) {
2367         *it = 0;
2368         delete object;
2369       } else {
2370         if(safe_cast<plottable,bins1D>(*object)) {
2371           nplottables++;
2372           nbins++;
2373         } else if(safe_cast<plottable,bins2D>(*object)) {
2374           nplottables++;
2375           nbins++;
2376 
2377         } else if(safe_cast<plottable,points2D>(*object)) {
2378           nplottables++;
2379           npoints++;
2380         } else if(safe_cast<plottable,points3D>(*object)) {
2381           nplottables++;
2382           npoints++;
2383 
2384         } else if(safe_cast<plottable,func1D>(*object)) {
2385           nplottables++;
2386           nfunc++;
2387         } else if(safe_cast<plottable,func2D>(*object)) {
2388           nplottables++;
2389           nfunc++;
2390         }
2391       }
2392     }}
2393 
2394     clear_cmaps();
2395     m_bins_cmaps.resize(nbins,0);
2396     m_points_cmaps.resize(npoints,0);
2397     m_func_cmaps.resize(nfunc,0);
2398 
2399     // even if !nplottables we continue.
2400 
2401     m_infos_title_sep.clear();
2402     m_infos_sep.clear();
2403     m_legend_strings.clear();
2404 
2405     bool superpose = false;
2406     /*uuuu
2407     bool superpose = superposeBins;
2408     if(superpose) {
2409       // Check compatibility of bins :
2410       if( (nbins1D<=0) || (m_shape!=XY) ) {
2411         superpose = false;
2412       } else {
2413         SbPlottableBins1D* bins = f_bins1DList[0];
2414         int xnbin = bins->getAxisNumberOfBins();
2415         float xmn = bins->get_axis_min();
2416         float xmx = bins->get_axis_max();
2417         superpose = true;
2418         for(int ibins=1;ibins<nbins1D;ibins++) {
2419           SbPlottableBins1D* binsloop = f_bins1DList[ibins];
2420           if( (xnbin!=binsloop->getAxisNumberOfBins()) ||
2421               (xmn!=binsloop->get_axis_min()) ||
2422               (xmx!=binsloop->get_axis_max()) ) {
2423             superpose = false;
2424             break;
2425           }
2426         }
2427         if(superpose) { //Compatible bins :
2428           if(y_axis_automated) {
2429             // Correct Y axis if XY shape and superposing bins.
2430             // Get min/max
2431             float bmin,bmax;
2432             getHeight(nbins1D-1,f_bins1DList,bins1DListSwMnMx,0,bmin,bmax);
2433             bmin = bmax;
2434             for(int ibin=1;ibin<xnbin;ibin++) {
2435               float mini,maxi;
2436               getHeight
2437                 (nbins1D-1,f_bins1DList,bins1DListSwMnMx,ibin,mini,maxi);
2438               bmin = SbMinimum(bmin,maxi);
2439               bmax = SbMaximum(bmax,maxi);
2440             }
2441             f_yDataAxis.setMinimumValue(bmin);
2442             f_yDataAxis.setMaximumValue(bmax);
2443             f_yDataAxis.adjustAxis();
2444           }
2445         }
2446       }
2447     }*/
2448 
2449     float xmin =  m_x_axis_data.min_value();
2450     float xmax =  m_x_axis_data.max_value();
2451     bool xlog = m_x_axis_data.is_log();
2452     if(xlog) {
2453       if((xmin<=0) || (xmax<=0) ) {
2454         m_x_axis_data.adjust();
2455         xmin =  m_x_axis_data.min_value();
2456         xmax =  m_x_axis_data.max_value();
2457         // now should have reasonable values.
2458       }
2459       if((xmin<=0) || (xmax<=0) ) {
2460         xlog = false;
2461       } else {
2462         xmin = flog10(xmin);
2463         xmax = flog10(xmax);
2464       }
2465     }
2466 
2467     float ymin =  m_y_axis_data.min_value();
2468     float ymax =  m_y_axis_data.max_value();
2469     bool ylog = m_y_axis_data.is_log();
2470     if(ylog) {
2471       if((ymin<=0) || (ymax<=0) ) {
2472         m_y_axis_data.adjust();
2473         ymin = m_y_axis_data.min_value();
2474         ymax = m_y_axis_data.max_value();
2475         // now should have reasonable values.
2476       }
2477       if((ymin<=0) || (ymax<=0) ) {
2478         ylog = false;
2479       }else{
2480         ymin = flog10(ymin);
2481         ymax = flog10(ymax);
2482       }
2483     }
2484 
2485     float zmin =  m_z_axis_data.min_value();
2486     float zmax =  m_z_axis_data.max_value();
2487     bool zlog = m_z_axis_data.is_log();
2488     if(zlog) {
2489       if((zmin<=0) || (zmax<=0) ) {
2490         m_z_axis_data.adjust();
2491         zmin = m_z_axis_data.min_value();
2492         zmax = m_z_axis_data.max_value();
2493         // now should have reasonable values.
2494       }
2495       if((zmin<=0) || (zmax<=0) ) {
2496         zlog = false;
2497       }else{
2498         zmin = flog10(zmin);
2499         zmax = flog10(zmax);
2500       }
2501     }
2502 
2503     if(m_shape==xy) {
2504       if(xmin>=xmax) {
2505         DUMP_UPDATE_WHAT(a_out,"bad min/max x axes");
2506       }
2507       if(ymin>=ymax) {
2508         DUMP_UPDATE_WHAT(a_out,"bad min/max y axes");
2509       }
2510     } else if(m_shape==xyz) {
2511       if(xmin>=xmax) {
2512         DUMP_UPDATE_WHAT(a_out,"bad min/max x axes");
2513       }
2514       if(ymin>=ymax) {
2515         DUMP_UPDATE_WHAT(a_out,"bad min/max y axes");
2516       }
2517       if(zmin>=zmax) {
2518         DUMP_UPDATE_WHAT(a_out,"bad min/max z axes");
2519       }
2520     }
2521 
2522    {float XSIZ = width;
2523     float XMGL = left_margin;
2524     float XMGR = right_margin;
2525     float wData = XSIZ-XMGL-XMGR;
2526 
2527     float YSIZ = height;
2528     float YMGL = bottom_margin;
2529     float YMGU = top_margin;
2530     float hData = YSIZ-YMGL-YMGU;
2531     if(m_shape==xy) {
2532       if(wData<=0) {
2533         DUMP_UPDATE_WHAT(a_out,"null w data area");
2534       }
2535       if(hData<=0) {
2536         DUMP_UPDATE_WHAT(a_out,"null h data area");
2537       }
2538     } else if(m_shape==xyz) {
2539       float ZSIZ = depth;
2540       float ZMGD = down_margin;
2541       float ZMGU = up_margin;
2542       float dData = ZSIZ-ZMGD-ZMGU;
2543       if(wData<=0) {
2544         DUMP_UPDATE_WHAT(a_out,"null w data area");
2545       }
2546       if(hData<=0) {
2547         DUMP_UPDATE_WHAT(a_out,"null h data area");
2548       }
2549       if(dData<=0) {
2550         DUMP_UPDATE_WHAT(a_out,"null d data area");
2551       }
2552     }}
2553 
2554     float dx   = xmax - xmin;
2555     float dy   = ymax - ymin;
2556     float dz   = zmax - zmin;
2557 
2558     rep_box boxX(xmin,dx,xlog);
2559     rep_box boxY(ymin,dy,ylog);
2560     rep_box boxZ(zmin,dz,zlog);
2561 
2562     ////////////////////////////////////
2563     /// data : /////////////////////////
2564     ////////////////////////////////////
2565     if(m_shape==xy) {
2566       //a_out << "tools::sg::plotter::update_sg : shape xy :" << std::endl;
2567 
2568       // first data plane is at zz = _zoffset().
2569 
2570       float zz = 0;
2571 
2572       ////////////////////////////////////
2573       /// binss //////////////////////////
2574       ////////////////////////////////////
2575 
2576       //if(verbose) {
2577       //  SoDebugError::postInfo("tools::sg;:plotter::updateChildren",
2578       //  "%lu : XY : update bins",(unsigned long)this);
2579       //}
2580 
2581      {m_bins_sep.clear();
2582       m_errors_sep.clear();
2583 
2584       unsigned int ibins = 0; //used to get each bins style and colormap.
2585       //unsigned int ibins1D = 0;
2586       //unsigned int ibins2D = 0;
2587       tools_vforcit(plottable*,m_plottables,it) {
2588         plottable* object = *it;
2589         if(!object) continue;
2590         if(bins1D* b1 = safe_cast<plottable,bins1D>(*object)) {
2591 
2592           zz += _zoffset(); // ibins = 0 back (PAW convention).
2593           style* data_style = merge_bins_style(ibins,*object);
2594           style* _left_hatch_style = merge_left_hatch_style(ibins,*object);
2595           style* _right_hatch_style = merge_right_hatch_style(ibins,*object);
2596           style* error_style = merge_errors_style(ibins,*object);
2597 
2598           update_bins1D_xy(a_out,*b1,
2599                            *data_style,*_left_hatch_style,*_right_hatch_style,*error_style,ibins,
2600                            superpose,boxX,boxY,zz);
2601 
2602           if(legends_automated.value()) {
2603             m_legend_strings.push_back(object->legend());
2604             style& _style = legend_style(m_legend_strings.size()-1);
2605             _style.color = data_style->color;
2606             _style.marker_style = data_style->marker_style;
2607             _style.marker_size = data_style->marker_size;
2608           }
2609 
2610           delete data_style;
2611           delete _left_hatch_style;
2612           delete _right_hatch_style;
2613           delete error_style;
2614           ibins++;
2615           //ibins1D++;
2616         } if(bins2D* b2 = safe_cast<plottable,bins2D>(*object)) {
2617           //a_out << "tools::sg::plotter::update_sg : bins2D." << std::endl;
2618           zz += _zoffset(); // ibins = 0 back (PAW convention).
2619           style* data_style = merge_bins_style(ibins,*object);
2620 
2621           update_bins2D_xy(a_out,*b2,*data_style,ibins,boxX,boxY,boxZ,zz);
2622 
2623           if(legends_automated.value()) {
2624             m_legend_strings.push_back(object->legend());
2625             style& _style = legend_style(m_legend_strings.size()-1);
2626             _style.color = data_style->color;
2627             _style.marker_style = data_style->marker_style;
2628             _style.marker_size = data_style->marker_size;
2629           }
2630 
2631           delete data_style;
2632           ibins++;
2633         }
2634       }}
2635 
2636       ////////////////////////////////////
2637       /// funcs //////////////////////////
2638       ////////////////////////////////////
2639 
2640      {m_func_sep.clear();
2641       //zz = 0; // Functions in front.
2642       unsigned int ifunc = 0; //used to get each func style and colormap.
2643       tools_vforcit(plottable*,m_plottables,it) {
2644         plottable* object = *it;
2645         if(!object) continue;
2646         if(func1D* f1 = safe_cast<plottable,func1D>(*object)) {
2647           zz += _zoffset();
2648           style* data_style = merge_func_style(ifunc,*object);
2649           update_func1D_xy(a_out,*f1,*data_style,boxX,boxY,zz);
2650           if(legends_automated.value()) {
2651             m_legend_strings.push_back(object->legend());
2652             style& _style = legend_style(m_legend_strings.size()-1);
2653             _style.color = data_style->color;
2654             _style.marker_style = data_style->marker_style;
2655             _style.marker_size = data_style->marker_size;
2656           }
2657           delete data_style;
2658           ifunc++;
2659         } else if(func2D* f2 = safe_cast<plottable,func2D>(*object)) {
2660           zz += _zoffset();
2661           style* data_style = merge_func_style(ifunc,*object);
2662           update_func2D_xy(a_out,*f2,ifunc,*data_style,boxX,boxY,boxZ,zz);
2663           if(legends_automated.value()) {
2664             m_legend_strings.push_back(object->legend());
2665             style& _style = legend_style(m_legend_strings.size()-1);
2666             _style.color = data_style->color;
2667             _style.marker_style = data_style->marker_style;
2668             _style.marker_size = data_style->marker_size;
2669           }
2670           delete data_style;
2671           ifunc++;
2672         }
2673       }}
2674 
2675       ////////////////////////////////////
2676       /// pointss ////////////////////////
2677       ////////////////////////////////////
2678      {m_points_sep.clear();
2679       unsigned int ipoints = 0; //used to get each points style and colormap.
2680       tools_vforcit(plottable*,m_plottables,it) {
2681         plottable* object = *it;
2682         if(!object) continue;
2683         if(points2D* p2 = safe_cast<plottable,points2D>(*object)) {
2684 
2685           zz += _zoffset(); // ibins = 0 back (PAW convention).
2686           style* data_style = merge_points_style(ipoints,*object);
2687           update_points2D_xy(a_out,*p2,*data_style,boxX,boxY,zz);
2688 
2689           if(legends_automated.value()) {
2690             m_legend_strings.push_back(object->legend());
2691             style& _style = legend_style(m_legend_strings.size()-1);
2692             _style.color = data_style->color;
2693             _style.modeling = data_style->modeling;
2694             _style.marker_style = data_style->marker_style;
2695             _style.marker_size = data_style->marker_size;
2696             _style.point_size = data_style->point_size;
2697           }
2698 
2699           delete data_style;
2700           ipoints++;
2701         }
2702       }}
2703     }
2704 
2705     if(m_shape==xyz) {
2706 
2707       ////////////////////////////////////
2708       /// binss //////////////////////////
2709       ////////////////////////////////////
2710      {m_bins_sep.clear();
2711       m_errors_sep.clear();
2712       unsigned int ibins = 0; //used to get each bins style and colormap.
2713       tools_vforcit(plottable*,m_plottables,it) {
2714         plottable* object = *it;
2715         if(!object) continue;
2716         if(safe_cast<plottable,bins1D>(*object)) {
2717           ibins++;
2718         } else if(bins2D* b2 = safe_cast<plottable,bins2D>(*object)) {
2719           style* data_style = merge_bins_style(ibins,*object);
2720           update_bins2D_xyz(a_out,*b2,ibins,*data_style,boxX,boxY,boxZ);
2721           delete data_style;
2722           ibins++;
2723         }
2724       }}
2725 
2726       ////////////////////////////////////
2727       /// funcs //////////////////////////
2728       ////////////////////////////////////
2729 
2730      {m_func_sep.clear();
2731       unsigned int ifunc = 0; //used to get each func style and colormap.
2732       tools_vforcit(plottable*,m_plottables,it) {
2733         plottable* object = *it;
2734         if(!object) continue;
2735         if(safe_cast<plottable,func1D>(*object)) {
2736           ifunc++;
2737         } else if(func2D* f2 = safe_cast<plottable,func2D>(*object)) {
2738           style* data_style = merge_func_style(ifunc,*object);
2739           update_func2D_xyz(a_out,*f2,ifunc,*data_style,boxX,boxY,boxZ);
2740           delete data_style;
2741           ifunc++;
2742         }
2743       }}
2744 
2745       ////////////////////////////////////
2746       /// pointss ////////////////////////
2747       ////////////////////////////////////
2748      {m_points_sep.clear();
2749       unsigned int ipoints = 0; //used to get each points style and colormap.
2750       tools_vforcit(plottable*,m_plottables,it) {
2751         plottable* object = *it;
2752         if(!object) continue;
2753         if(points3D* p3 = safe_cast<plottable,points3D>(*object)) {
2754 
2755           style* data_style = merge_points_style(ipoints,*object);
2756           update_points3D_xyz(a_out,*p3,*data_style,boxX,boxY,boxZ);
2757 
2758           if(legends_automated.value()) {
2759             m_legend_strings.push_back(object->legend());
2760             style& _style = legend_style(m_legend_strings.size()-1);
2761             _style.color = data_style->color;
2762             _style.modeling = data_style->modeling;
2763             _style.marker_style = data_style->marker_style;
2764             _style.marker_size = data_style->marker_size;
2765             _style.point_size = data_style->point_size;
2766           }
2767 
2768           delete data_style;
2769           ipoints++;
2770         }
2771       }}
2772     }
2773 
2774     ////////////////////////////////////
2775     /// axes : /////////////////////////
2776     ////////////////////////////////////
2777     // done before update_legends() which needs
2778     // the x_axis min/max if legends_origin_unit
2779     // is unit_axis.
2780 
2781     // axes :
2782     if(m_shape==xy){
2783       if(x_axis_enforced.value()) {
2784         update_x_axis_2D();
2785         m_x_axis.minimum_value = x_axis_min.value();
2786         m_x_axis.maximum_value = x_axis_max.value();
2787         m_x_axis.is_log = x_axis_is_log.value();
2788         m_x_axis.update_sg(a_out); // So that the grid be correct.
2789         m_x_axis.reset_touched();
2790       } else {
2791         if(!nplottables) {
2792           m_x_axis.width = 0;
2793         } else {
2794           update_x_axis_2D();
2795           update_axis(a_out,m_x_axis,m_x_axis_data);
2796         }
2797       }
2798 
2799       if(y_axis_enforced.value()) {
2800         update_y_axis_2D();
2801         m_y_axis.minimum_value = y_axis_min.value();
2802         m_y_axis.maximum_value = y_axis_max.value();
2803         m_y_axis.is_log = y_axis_is_log.value();
2804         m_y_axis.update_sg(a_out); // So that the grid be correct.
2805         m_y_axis.reset_touched();
2806       } else {
2807         if(!nplottables) {
2808           m_y_axis.width = 0;
2809         } else {
2810           update_y_axis_2D();
2811           update_axis(a_out,m_y_axis,m_y_axis_data);
2812         }
2813       }
2814 
2815       if(z_axis_enforced.value()) {
2816         update_z_axis_2D();
2817         m_z_axis.minimum_value = z_axis_min.value();
2818         m_z_axis.maximum_value = z_axis_max.value();
2819         m_z_axis.is_log = z_axis_is_log.value();
2820         m_z_axis.update_sg(a_out); // So that the grid be correct.
2821         m_z_axis.reset_touched();
2822       } else {
2823         if(!nplottables) {
2824           m_z_axis.width = 0;
2825         } else {
2826           update_z_axis_2D();
2827         }
2828       }
2829     }
2830 
2831     if(m_shape==xyz){
2832       if(x_axis_enforced.value()) {
2833         update_x_axis_3D();
2834         m_x_axis.minimum_value = x_axis_min.value();
2835         m_x_axis.maximum_value = x_axis_max.value();
2836         m_x_axis.is_log = x_axis_is_log.value();
2837         m_x_axis.update_sg(a_out); // So that the grid be correct.
2838         m_x_axis.reset_touched();
2839       } else {
2840         if(!nplottables) {
2841           m_x_axis.width = 0;
2842         } else {
2843           update_x_axis_3D();
2844           update_axis(a_out,m_x_axis,m_x_axis_data);
2845         }
2846       }
2847 
2848       if(y_axis_enforced.value()) {
2849         update_y_axis_3D();
2850         m_y_axis.minimum_value = y_axis_min.value();
2851         m_y_axis.maximum_value = y_axis_max.value();
2852         m_y_axis.is_log = y_axis_is_log.value();
2853         m_y_axis.update_sg(a_out); // So that the grid be correct.
2854         m_y_axis.reset_touched();
2855       } else {
2856         if(!nplottables) {
2857           m_y_axis.width = 0;
2858         } else {
2859           update_y_axis_3D();
2860           update_axis(a_out,m_y_axis,m_y_axis_data);
2861         }
2862       }
2863 
2864       if(z_axis_enforced.value()) {
2865         update_z_axis_3D();
2866         m_z_axis.minimum_value = z_axis_min.value();
2867         m_z_axis.maximum_value = z_axis_max.value();
2868         m_z_axis.is_log = z_axis_is_log.value();
2869         m_z_axis.update_sg(a_out); // So that the grid be correct.
2870         m_z_axis.reset_touched();
2871       } else {
2872         if(!nplottables) {
2873           m_z_axis.width = 0;
2874         } else {
2875           update_z_axis_3D();
2876           update_axis(a_out,m_z_axis,m_z_axis_data);
2877         }
2878       }
2879     }
2880 
2881     if(nplottables) {
2882       // infos box is done before update_legends()
2883       // because legends may be placed relative to it.
2884       update_infos(a_out);
2885     }
2886     m_legend_sep.clear();
2887 
2888     if(!legends_automated) {
2889       m_legend_strings = legends_string.values();
2890     }
2891     update_legends(a_out);
2892 
2893     if(title_automated) {
2894       std::string _s;
2895       get_title(_s);
2896       title.value(_s);
2897       title.reset_touched(); //output field.
2898     }
2899     m_title_sep.clear();
2900     if(nplottables) update_title();
2901 
2902     m_title_box_sep.clear();
2903     if(nplottables) update_title_box();
2904 
2905     m_inner_frame_sep.clear();
2906     if(inner_frame_enforced.value() || nplottables) {
2907       if(m_shape==xy) {
2908         update_inner_frame_XY();
2909       } else {
2910         update_inner_frame_XYZ();
2911       }
2912     }
2913 
2914     m_grid_sep.clear();
2915     if(nplottables) {
2916       if(m_shape==xy) {
2917         update_grid_XY();
2918       } else {
2919         update_grid_XYZ();
2920       }
2921     }
2922 
2923     m_cmap_axis.width = 0;
2924     m_cmap_cells_sep.clear();
2925     if(m_bins_cmaps.size() && m_bins_cmaps[0] && m_bins_cmaps[0]->valn()) {     //major_bins
2926       update_cmap(a_out,*(m_bins_cmaps[0]));
2927     } else if(m_points_cmaps.size() && m_points_cmaps[0] && m_points_cmaps[0]->valn()) { //major_points
2928       update_cmap(a_out,*(m_points_cmaps[0]));
2929     } else if(m_func_cmaps.size() && m_func_cmaps[0] && m_func_cmaps[0]->valn()) { //major_func
2930       update_cmap(a_out,*(m_func_cmaps[0]));
2931     }
2932 
2933     update_primitives(a_out);
2934   }
2935 
2936   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) {
2937     if(a_Sw_mn>a_Sw_mx) {
2938       a_min = 0;
2939       a_max = 0;
2940       return;
2941     }
2942     // a_Sw_mx >= a_Sw_mn.
2943     if(a_is_log && (a_Sw_mn<=0) ) { //let data_axis.adjust() do something.
2944       a_min = a_Sw_mn;
2945       a_max = a_Sw_mx;
2946       return;
2947     }
2948     float mn;
2949     if(a_is_log) {
2950       if(value_bottom_margin.value()!=0) {
2951         float log_Sw_mn = flog10(a_Sw_mn);
2952         float log_Sw_mx = flog10(a_Sw_mx);
2953         float log_mn = log_Sw_mn - (log_Sw_mx-log_Sw_mn)*value_bottom_margin;
2954         mn = fpow(10,log_mn);
2955       } else {
2956         mn = a_Sw_mn;
2957         if(a_min_visible) { // arrang so that the bin with a_Sw_mn be visible.
2958           float log_Sw_mn = flog10(a_Sw_mn);
2959           mn = fpow(10,log_Sw_mn)*(1.0f-0.4f);
2960         }
2961       }
2962     } else {
2963       if(value_bottom_margin.value()!=0) {
2964         mn = a_Sw_mn - (a_Sw_mx-a_Sw_mn)*value_bottom_margin;
2965       } else {
2966         if(a_min_visible) {
2967           // Arrange so that the bin with a_Sw_mn (if not 0) be visible. (If 0, it will be anyway on the x axis) :
2968           if(a_Sw_mn>0) {
2969             mn = 0; //PAW logic.
2970           } else if(a_Sw_mn==0) {
2971             mn = 0; //PAW logic. min bin will be anyway on x axis.
2972           } else {
2973             mn = a_Sw_mn; // min bin will be anyway on x axis.
2974           }
2975         } else {
2976           mn = a_Sw_mn; //min bin will be on x axis.
2977         }
2978       }
2979     }
2980     a_min = mn;
2981 
2982     float mx;
2983     if(a_is_log) {
2984       if(value_top_margin.value()!=0) {
2985         float log_Sw_mn = flog10(a_Sw_mn);
2986         float log_Sw_mx = flog10(a_Sw_mx);
2987         float log_mx = log_Sw_mx + (log_Sw_mx-log_Sw_mn)*value_top_margin;
2988         mx = fpow(10,log_mx);
2989       } else {
2990         mx = a_Sw_mx; //max bin will be on top of frame (then not visible if same color).
2991       }
2992     } else {
2993       mx = a_Sw_mx + (a_Sw_mx-mn)*value_top_margin;
2994     //mx = a_Sw_mx + (a_Sw_mx-a_Sw_mn)*value_top_margin; //not compatible with gopaw.
2995     }
2996     a_max = mx;
2997   }
2998 
2999   void update_axes_data(std::ostream& a_out){
3000     m_x_axis_data.set_min_value(0);
3001     m_x_axis_data.set_max_value(0);
3002     m_x_axis_data.set_is_log(x_axis_is_log);
3003 
3004     m_y_axis_data.set_min_value(0);
3005     m_y_axis_data.set_max_value(0);
3006     m_y_axis_data.set_is_log(y_axis_is_log);
3007 
3008     m_z_axis_data.set_min_value(0);
3009     m_z_axis_data.set_max_value(0);
3010     m_z_axis_data.set_is_log(z_axis_is_log);
3011 
3012     if(!x_axis_automated) { //def = true
3013       m_x_axis_data.set_min_value(x_axis_min);
3014       m_x_axis_data.set_max_value(x_axis_max);
3015     }
3016 
3017     if(!y_axis_automated) {
3018       m_y_axis_data.set_min_value(y_axis_min);
3019       m_y_axis_data.set_max_value(y_axis_max);
3020     }
3021 
3022     if(!z_axis_automated) {
3023       m_z_axis_data.set_min_value(z_axis_min);
3024       m_z_axis_data.set_max_value(z_axis_max);
3025     }
3026 
3027     bins1D* b1;
3028     bins2D* b2;
3029 
3030     func1D* f1;
3031     func2D* f2;
3032 
3033     points2D* p2;
3034     points3D* p3;
3035 
3036     if(first_bins(b1,b2)) {
3037 
3038       if(b1) {
3039 
3040         if(x_axis_automated) {
3041           m_x_axis_data.set_min_value(b1->axis_min());
3042           m_x_axis_data.set_max_value(b1->axis_max());
3043         }
3044 
3045         if(y_axis_automated) {
3046         //::printf("debug : value %g %g %d : is log %d\n",
3047         //    value_bottom_margin.value(),value_top_margin.value(),value_bins_with_entries.value(),
3048         //    m_y_axis_data.is_log());
3049           float Sw_mn,Sw_mx;
3050           b1->bins_Sw_range(Sw_mn,Sw_mx,value_bins_with_entries.value());
3051         //::printf("debug : Sw %g %g\n",Sw_mn,Sw_mx);
3052           float mn,mx;
3053           get_value_axis_min_max(Sw_mn,Sw_mx,m_y_axis_data.is_log(),mn,mx,true);
3054         //::printf("debug : mn mx %g %g\n",mn,mx);
3055           m_y_axis_data.set_min_value(mn);
3056           m_y_axis_data.set_max_value(mx);
3057 
3058           m_y_axis_data.adjust();
3059         //::printf("debug : adjusted : mn mx %g %g\n",mn,mx);
3060         }
3061 
3062       } if(b2) {
3063         if(x_axis_automated) {
3064           m_x_axis_data.set_min_value(b2->x_axis_min());
3065           m_x_axis_data.set_max_value(b2->x_axis_max());
3066         }
3067 
3068         if(y_axis_automated) {
3069           m_y_axis_data.set_min_value(b2->y_axis_min());
3070           m_y_axis_data.set_max_value(b2->y_axis_max());
3071         }
3072 
3073         if(z_axis_automated) {
3074           float Sw_mn,Sw_mx;
3075           b2->bins_Sw_range(Sw_mn,Sw_mx,value_bins_with_entries.value());
3076           float mn,mx;
3077           get_value_axis_min_max(Sw_mn,Sw_mx,m_z_axis_data.is_log(),mn,mx,false);
3078           m_z_axis_data.set_min_value(mn);
3079           m_z_axis_data.set_max_value(mx);
3080 
3081           m_z_axis_data.adjust();
3082         }
3083       } /*else if(f_binsList[0]->getDimension()==3) {
3084         //FIXME : should do something.
3085       } else {
3086         // Unusual case.
3087       }*/
3088 
3089     } else if(first_points(p2,p3)) {
3090       if(p2) {
3091         if(x_axis_automated) {
3092           m_x_axis_data.set_min_value(p2->x_axis_min());
3093           m_x_axis_data.set_max_value(p2->x_axis_max());
3094         }
3095         if(y_axis_automated) {
3096           float ymn = p2->y_axis_min();
3097           float ymx = p2->y_axis_max();
3098           // For pawex22 ?
3099           //m_y_axis_data.set_min_value(ymn*1.1F);
3100           //m_y_axis_data.set_max_value(ymx*1.1F);
3101           m_y_axis_data.set_min_value(ymn);
3102           m_y_axis_data.set_max_value(ymx);
3103         }
3104       } else if(p3) {
3105 
3106         if(x_axis_automated) {
3107           m_x_axis_data.set_min_value(p3->x_axis_min());
3108           m_x_axis_data.set_max_value(p3->x_axis_max());
3109         }
3110 
3111         if(y_axis_automated) {
3112           m_y_axis_data.set_min_value(p3->y_axis_min());
3113           m_y_axis_data.set_max_value(p3->y_axis_max());
3114         }
3115 
3116         if(z_axis_automated) {
3117           m_z_axis_data.set_min_value(p3->z_axis_min());
3118           m_z_axis_data.set_max_value(p3->z_axis_max());
3119         }
3120       }
3121 
3122     } else if(first_func(f1,f2)) {
3123 
3124       if(f1) {
3125 
3126         if(x_axis_automated) {
3127           float xmn = f1->x_min();
3128           float xmx = f1->x_max();
3129           if(xmx<=xmn) {
3130             xmn = -1;
3131             xmx = 1;
3132           }
3133           m_x_axis_data.set_min_value(xmn);
3134           m_x_axis_data.set_max_value(xmx);
3135         }
3136 
3137         if(y_axis_automated) {
3138           float xmn = m_x_axis_data.min_value();
3139           float xmx = m_x_axis_data.max_value();
3140           unsigned int nstp = f1->x_steps();
3141           nstp = nstp <=0 ? curve_number_of_points.value(): nstp;
3142 
3143           float df = (xmx - xmn)/nstp;
3144           bool problem = false;
3145           float vmin;
3146           if(!f1->value(xmn,vmin)) problem = true;
3147           float vmax = vmin;
3148           for(unsigned int ibin=0;ibin<=nstp;ibin++) {
3149             float xx = xmn + ibin * df;
3150             float val;
3151             if(!f1->value(xx,val)) problem = true;
3152             vmax = mx<float>(vmax,val);
3153             vmin = mn<float>(vmin,val);
3154           }
3155           if(problem) {
3156             a_out << "tools::sg::plotter :"
3157                   << " problem when getting some function value."
3158                   << std::endl;
3159           }
3160           m_y_axis_data.set_min_value(vmin);
3161           m_y_axis_data.set_max_value(vmax);
3162           m_y_axis_data.adjust();
3163         }
3164 
3165       } else if(f2) {
3166         if(x_axis_automated) {
3167           float xmn = f2->x_min();
3168           float xmx = f2->x_max();
3169           if(xmx<=xmn) {
3170             xmn = -1;
3171             xmx = 1;
3172           }
3173           m_x_axis_data.set_min_value(xmn);
3174           m_x_axis_data.set_max_value(xmx);
3175         }
3176 
3177         if(y_axis_automated) {
3178           float ymn =  f2->y_min();
3179           float ymx =  f2->y_max();
3180           if(ymx<=ymn) {
3181             ymn = -1;
3182             ymx = 1;
3183           }
3184           m_y_axis_data.set_min_value(ymn);
3185           m_y_axis_data.set_max_value(ymx);
3186         }
3187 
3188         if(z_axis_automated) {
3189 
3190           float xmn = m_x_axis_data.min_value();
3191           float xmx = m_x_axis_data.max_value();
3192           int nx = f2->x_steps();
3193           nx = nx <=0 ? curve_number_of_points.value() : nx;
3194 
3195           float ymn = m_y_axis_data.min_value();
3196           float ymx = m_y_axis_data.max_value();
3197           int ny = f2->y_steps();
3198           ny = ny <=0 ? curve_number_of_points.value() : ny;
3199 
3200           float dfx = (xmx - xmn)/nx;
3201           float dfy = (ymx - ymn)/ny;
3202 
3203           bool problem = false;
3204           float vmin;
3205           if(!f2->value(xmn,ymn,vmin)) problem = true;
3206           float vmax = vmin;
3207           for(int jbin=ny-1;jbin>=0;jbin--) {
3208             for(int ibin=nx-1;ibin>=0;ibin--) {
3209               float xx = xmn + ibin * dfx;
3210               float yy = ymn + jbin * dfy;
3211               float val;
3212               if(!f2->value(xx,yy,val)) problem = true;
3213               vmin = mn<float>(vmin,val);
3214               vmax = mx<float>(vmax,val);
3215             }
3216           }
3217           if(problem) {
3218             a_out << "tools::sg::plotter :"
3219                   << " problem when getting some function value."
3220                   << std::endl;
3221           }
3222           m_z_axis_data.set_min_value(vmin);
3223           m_z_axis_data.set_max_value(vmax);
3224           m_z_axis_data.adjust();
3225         }
3226       }
3227     }
3228   }
3229   void update_shape(){
3230     m_shape = get_shape();
3231     //uuuu if(shapeAutomated) {
3232     //  shape.setValue(m_shape);
3233     //}
3234   }
3235 
3236   void update_axis(std::ostream& a_out,sg::axis& a_axis,data_axis& a_data){
3237     a_axis.minimum_value = a_data.min_value();
3238     a_axis.maximum_value = a_data.max_value();
3239     a_axis.is_log = a_data.is_log();
3240     a_axis.update_sg(a_out); // So that the grid be correct.
3241     a_axis.reset_touched();
3242   }
3243 
3244   void update_x_axis_2D(){
3245     float XSIZ = width;
3246     float XMGL = left_margin;
3247     float XMGR = right_margin;
3248     float wData = XSIZ-XMGL-XMGR;
3249 
3250     //m_x_axis.verbose.setValue(verbose);
3251     m_x_axis.tick_up = true;
3252     m_x_axis.width = wData;
3253 
3254    {text_style& style = m_x_axis.labels_style();
3255     if(!style.enforced.value()) { //gopaw may enforce style.
3256       style.x_orientation = vec3f(1,0,0);
3257       style.y_orientation = vec3f(0,1,0);
3258       style.hjust = center;
3259       style.vjust = top;
3260     }}
3261 
3262    {text_style& style = m_x_axis.title_style();
3263     style.x_orientation = vec3f(1,0,0);
3264     style.y_orientation = vec3f(0,1,0);
3265     style.hjust = m_x_axis.title_hjust;
3266     style.vjust = top;}
3267 
3268    {text_style& style = m_x_axis.mag_style();
3269     style.hjust = left;
3270     style.vjust = bottom;}
3271 
3272     m_x_axis_matrix.set_translate(0,0,_zaxis());
3273   }
3274 
3275   void update_y_axis_2D(){
3276     float YSIZ = height;
3277     float YMGL = bottom_margin;
3278     float YMGU = top_margin;
3279     float hData = YSIZ-YMGL-YMGU;
3280 
3281     //m_x_axis.verbose.setValue(verbose);
3282     m_y_axis.tick_up.value(true);
3283     m_y_axis.width.value(hData);
3284 
3285    {text_style& style = m_y_axis.labels_style();
3286     if(!style.enforced.value()) {
3287       style.x_orientation = vec3f(0,1,0);
3288       style.y_orientation = vec3f(1,0,0);
3289       style.hjust = right;
3290       style.vjust = middle;
3291     }}
3292 
3293    {text_style& style = m_y_axis.title_style();
3294     style.x_orientation = vec3f(1,0,0);
3295     style.y_orientation = vec3f(0,-1,0);
3296     style.hjust = m_y_axis.title_hjust;
3297     style.vjust = bottom;}
3298 
3299    {text_style& style = m_y_axis.mag_style();
3300     style.x_orientation = vec3f(0,1,0);
3301     style.y_orientation = vec3f(1,0,0);
3302     style.hjust = right;
3303     style.vjust = bottom;}
3304 
3305    {mat4f& mtx = m_y_axis_matrix.mtx.value();
3306     mtx.set_translate(0,0,_zaxis());
3307     mtx.mul_rotate(0,1,0,fpi());
3308     mtx.mul_rotate(0,0,1,fhalf_pi());}
3309   }
3310 
3311   void update_z_axis_2D(){
3312     m_z_axis.width = 0;
3313     m_z_axis_matrix.set_identity();
3314   }
3315 
3316   void update_x_axis_3D(){
3317     float XSIZ = width;
3318     float XMGL = left_margin;
3319     float XMGR = right_margin;
3320     float wData = XSIZ-XMGL-XMGR;
3321 
3322     //m_x_axis.verbose.setValue(verbose);
3323     m_x_axis.tick_up = false;
3324     m_x_axis.width = wData;
3325 
3326    {text_style& style = m_x_axis.labels_style();
3327     if(!style.enforced.value()) {
3328       //style->font_name = SbFont_Hershey; //Enforce Hershey.
3329       style.x_orientation = vec3f(1,0,0);
3330       style.y_orientation = vec3f(0,1,0);
3331       style.hjust = center;
3332       style.vjust = top;
3333     }}
3334 
3335    {text_style& style = m_x_axis.title_style();
3336     style.x_orientation = vec3f(1,0,0);
3337     style.y_orientation = vec3f(0,1,0);
3338     style.hjust = right;
3339     style.vjust = top;}
3340 
3341    //{text_style& style = m_x_axis.mag_style();
3342    // style.hjust = left;
3343    // style.vjust = bottom;}
3344 
3345     m_x_axis_matrix.set_rotate(1,0,0,fhalf_pi());
3346 
3347   }
3348 
3349   void update_y_axis_3D(){
3350     float YSIZ = height;
3351     float YMGL = bottom_margin;
3352     float YMGU = top_margin;
3353     float hData = YSIZ-YMGL-YMGU;
3354 
3355     //m_x_axis.verbose.setValue(verbose);
3356     m_y_axis.tick_up = false;
3357     m_y_axis.width = hData;
3358 
3359    {text_style& style = m_y_axis.labels_style();
3360     if(!style.enforced.value()) {
3361       //style->fontName.setValue(SbFont_Hershey); //Enforce Hershey.
3362       style.x_orientation = vec3f(-1,0,0);
3363       style.y_orientation = vec3f( 0,1,0);
3364       style.hjust = center;
3365       style.vjust = top;
3366     }}
3367 
3368    {text_style& style = m_y_axis.title_style();
3369     style.x_orientation = vec3f(-1,0,0);
3370     style.y_orientation = vec3f( 0,1,0);
3371     style.hjust = left;
3372     style.vjust = top;}
3373 
3374    //{text_style& style = m_y_axis.mag_style();
3375    // style.x_orientation = vec3f(0,1,0);
3376    // style.y_orientation = vec3f(1,0,0);
3377    // style.hjust = right;
3378    // style.vjust = bottom;}
3379 
3380    {mat4f& mtx = m_y_axis_matrix.mtx.value();
3381     mtx.set_rotate(0,1,0,fhalf_pi());
3382     mtx.mul_rotate(0,0,1,fhalf_pi());}
3383   }
3384 
3385   void update_z_axis_3D(){
3386     float ZSIZ = depth;
3387     float ZMGD = down_margin;
3388     float ZMGU = up_margin;
3389     float dData = ZSIZ-ZMGD-ZMGU;
3390 
3391     m_z_axis.tick_up = false;
3392     m_z_axis.width = dData;
3393 
3394    {text_style& style = m_z_axis.labels_style();
3395     if(!style.enforced.value()) {
3396       //style->fontName.setValue(SbFont_Hershey); //Enforce Hershey.
3397       style.x_orientation = vec3f(0,1,0);
3398       style.y_orientation = vec3f(1,0,0);
3399       style.hjust = right;
3400       style.vjust = middle;
3401     }}
3402 
3403    {text_style& style = m_z_axis.title_style();
3404     style.x_orientation = vec3f(0,1,0);
3405     style.y_orientation = vec3f(1,0,0);
3406     style.hjust = right;
3407     style.vjust = bottom;}
3408 
3409    //{text_style& style = m_z_axis.mag_style();
3410    // style.hjust = center;
3411    // style.vjust = bottom;}
3412 
3413    {mat4f& mtx = m_z_axis_matrix.mtx.value();
3414     mtx.set_translate(0,m_y_axis.width.value(),0);
3415     mtx.mul_rotate(0,0,1,-fhalf_pi());
3416     mtx.mul_rotate(0,1,0,-fhalf_pi());}
3417 
3418   }
3419 
3420   void update_cmap(std::ostream& a_out,const base_colormap& a_cmap){
3421     if(!colormap_visible.value()) return;
3422 
3423     size_t valn = a_cmap.valn();
3424     if(!valn) return;
3425     size_t coln = a_cmap.colorn();
3426     if(!coln) return;
3427 
3428     float XSIZ = width;
3429     float XMGL = left_margin;
3430     float XMGR = right_margin;
3431     float wData = XSIZ-XMGL-XMGR;
3432 
3433     float YSIZ = height;
3434     float YMGL = bottom_margin;
3435     float YMGU = top_margin;
3436     float hData = YSIZ-YMGL-YMGU;
3437 
3438     float hcmap = hData;
3439 
3440    {mat4f& mtx = m_cmap_matrix.mtx.value();
3441     if(m_shape==xy) {
3442       mtx = m_layout.mtx.value();
3443       mtx.mul_translate(0,0,_zgrid());
3444     } else {
3445       float ZSIZ = depth;
3446       float ZMGD = down_margin;
3447       float ZMGU = up_margin;
3448       float dData = ZSIZ-ZMGD-ZMGU;
3449       hcmap = dData;
3450       if(colormap_attached.value()) {
3451         mtx = m_layout.mtx.value();
3452         mtx.mul_rotate(1,0,0,90.0F*fdeg2rad());
3453       } else { //OpenPAW
3454         float zz = -depth*0.5f;
3455         mtx.set_translate(-XSIZ/2+XMGL,-YSIZ/2+YMGL,zz); //applied first
3456       }
3457     }}
3458 
3459     float w  = XMGR*0.3F;
3460     float xx = wData+XMGR*0.1F;
3461     float zz = 0;
3462 
3463     float yy = 0;
3464     float h = hcmap/float(coln);
3465 
3466     // colored cells :
3467    {m_cmap_cells_sep.clear();
3468     m_cmap_cells_sep.add(new normal);
3469     for(unsigned int index=0;index<coln;index++)        {
3470       rgba* mat = new rgba();
3471       mat->color = a_cmap.color(index);
3472       m_cmap_cells_sep.add(mat);
3473 
3474       vertices* vtxs = new vertices;
3475       vtxs->mode = gl::triangle_fan();
3476       m_cmap_cells_sep.add(vtxs);
3477 
3478       vtxs->add(xx      ,yy     ,zz);
3479       vtxs->add(xx + w  ,yy     ,zz);
3480       vtxs->add(xx + w  ,yy + h ,zz);
3481       vtxs->add(xx      ,yy + h ,zz);
3482 
3483       yy += h;
3484     }}
3485 
3486     // surrounding box :
3487    {rgba* mat = new rgba();
3488     mat->color = colorf_black();
3489     m_cmap_cells_sep.add(mat);
3490 
3491     draw_style* ds = new draw_style;
3492     ds->style = draw_lines;
3493     ds->line_pattern = line_solid;
3494     ds->line_width = 1;
3495     m_cmap_cells_sep.add(ds);
3496 
3497     vertices* vtxs = new vertices;
3498     vtxs->mode = gl::line_strip();
3499     m_cmap_cells_sep.add(vtxs);
3500 
3501     vtxs->add(xx      ,0     ,zz);
3502     vtxs->add(xx + w  ,0     ,zz);
3503     vtxs->add(xx + w  ,hcmap ,zz);
3504     vtxs->add(xx      ,hcmap ,zz);
3505     vtxs->add(xx      ,0     ,zz);}
3506 
3507     if(!colormap_axis_visible.value()) {
3508       m_cmap_axis.width = 0;
3509     } else {
3510 
3511     // right axis :
3512     mat4f& mtx = m_cmap_axis_matrix.mtx.value();
3513     mtx.set_identity();
3514 
3515     zz += _zoffset()*0.01f;
3516 
3517     if(safe_cast<base_colormap,by_value_colormap>(a_cmap)) {
3518       if(colormap_axis_labeling.value()==cells) {
3519         if((valn+1)==coln) { // <col> <num> <col> ... <num> <col>
3520           mtx.set_translate(xx+w,h,zz);
3521         } else {
3522           mtx.set_translate(xx+w,0,zz);
3523         }
3524       } else {
3525         mtx.set_translate(xx+w,0,zz);
3526       }
3527     } else { //grey_scale,grey_scale_inverse,violet_to_red
3528       mtx.set_translate(xx+w,0,zz);
3529     }
3530 
3531     mtx.mul_rotate(0,0,1,fhalf_pi());
3532 
3533     m_cmap_axis.title = "";
3534     m_cmap_axis.tick_up = true;
3535     //m_cmap_axis.label_to_axis = 0.01F;
3536     //m_cmap_axis.label_height = 0.10F;
3537     //m_cmap_axis.ttf_scale = 10.0F;
3538 
3539     if(safe_cast<base_colormap,by_value_colormap>(a_cmap)) {
3540       if(colormap_axis_labeling.value()==cells) {
3541         if((valn+1)==coln) { // <col> <num> <col> ... <num> <col>
3542           m_cmap_axis.width = hcmap-2*h;
3543           m_cmap_axis.modeling = tick_modeling_none();
3544           m_cmap_axis.tick_number = uint32(valn);
3545           m_cmap_axis.labels.clear();
3546           m_cmap_axis.coords.clear();
3547           for(unsigned int index=0;index<valn;index++)        {
3548             //FIXME : for the labels, have a "mag" logic similar to SoAxis.
3549             char tmp[32];
3550             snpf(tmp,sizeof(tmp),"%g",a_cmap.value(index));
3551             m_cmap_axis.labels.add(tmp);
3552             m_cmap_axis.coords.add(h*index);
3553           }
3554         } else if((coln+1)==valn) { // <num> <col> <num> ... <col> <num>
3555           m_cmap_axis.width = hcmap;
3556           m_cmap_axis.modeling = tick_modeling_none();
3557           m_cmap_axis.tick_number = uint32(valn);
3558           m_cmap_axis.labels.clear();
3559           m_cmap_axis.coords.clear();
3560           for(unsigned int index=0;index<valn;index++)        {
3561             //FIXME : for the labels, have a "mag" logic similar to SoAxis.
3562             char tmp[32];
3563             snpf(tmp,sizeof(tmp),"%g",a_cmap.value(index));
3564             m_cmap_axis.labels.add(tmp);
3565             m_cmap_axis.coords.add(h*index);
3566           }
3567         } else {
3568           a_out << "tools::sg::plotter::update_cmap :"
3569                 << " inconsistent by value colormap."
3570                 << std::endl;
3571         }
3572       } else {
3573         m_cmap_axis.modeling = tick_modeling_hippo();
3574         m_cmap_axis.width = hcmap;
3575         m_cmap_axis.minimum_value = a_cmap.value(0);
3576         m_cmap_axis.maximum_value = a_cmap.value(uint32(valn)-1);
3577       }
3578     } else { //grey_scale,grey_scale_inverse,violet_to_red
3579       m_cmap_axis.modeling = tick_modeling_hippo();
3580       m_cmap_axis.width = hcmap;
3581       m_cmap_axis.minimum_value = a_cmap.value(0);
3582       m_cmap_axis.maximum_value = a_cmap.value(uint32(valn)-1);
3583     }
3584 
3585    {text_style& style = m_cmap_axis.labels_style();
3586     style.x_orientation = vec3f(0,-1,0);
3587     style.y_orientation = vec3f(1,0,0);
3588     style.hjust = left;
3589     style.vjust = middle;}
3590 
3591    {text_style& style = m_cmap_axis.mag_style();
3592     style.hjust = center;
3593     style.vjust = bottom;}
3594 
3595     }//end axis
3596   }
3597 
3598   void update_primitives(std::ostream& a_out) {
3599 //    if(primitives_enforced.value()) {
3600       m_primitives_sep.clear();
3601       tools_vforcit(plotprim*,m_primitives,it) {
3602         if(plottable_text* ptext = safe_cast<plotprim,plottable_text>(*(*it))) {
3603           update_primitive_text(*ptext);
3604         } else if(plottable_box* pbox = safe_cast<plotprim,plottable_box>(*(*it))) {
3605           update_primitive_box(a_out,*pbox);
3606         } else if(plottable_ellipse* pellipse = safe_cast<plotprim,plottable_ellipse>(*(*it))) {
3607           update_primitive_ellipse(a_out,*pellipse);
3608         } else if(plottable_img* pimg = safe_cast<plotprim,plottable_img>(*(*it))) {
3609           update_primitive_img(a_out,*pimg);
3610         }
3611       }
3612     //}
3613   }
3614 
3615 protected: //vis bins
3616   void update_bins1D_xy(std::ostream& a_out,
3617                         const bins1D& a_bins,
3618                         const style& a_data_style,
3619                         const style& a_left_hatch_style,
3620                         const style& a_right_hatch_style,
3621                         const style& a_errors_style,
3622                         int a_index,
3623                       /*SoStyle& aGraphicStyle,
3624                         int aIndex1D,
3625                         const std::vector<SbPlottableBins1D*>& a_bins1DList,
3626                         const SbPList& a_bins1DListSwMnMx,*/
3627                         bool /*aSuperpose*/,
3628                         const rep_box& a_box_x,
3629                         const rep_box& a_box_y,
3630                         float a_zz){
3631 
3632     //char sid[128];
3633     //::sprintf(sid,"tools::sg::bins1D/0x%lx",
3634     //  (unsigned long)const_cast<bins1D*>(&a_bins));
3635 
3636   //bool hbe = a_bins.has_entries_per_bin();
3637 
3638     float bmin = 0;
3639     float bmax = 0;
3640 
3641     size_t xnbin = a_bins.bins();
3642     std::vector<rep_bin1D> bins(xnbin);
3643    {bool first = true;
3644     for(size_t ibin=0;ibin<xnbin;ibin++) {
3645     //if(hbe && (a_bins.bin_entries(size_t(ibin))<=0)) continue;
3646       float val = a_bins.bin_Sw(int(ibin));
3647       float xx = float(a_bins.bin_lower_edge(int(ibin)));
3648       float xe = float(a_bins.bin_upper_edge(int(ibin)));
3649       bins[ibin] = rep_bin1D(xx,xe,0,val);
3650       if(first) {
3651         first = false;
3652         bmin = val;
3653         bmax = val;
3654       } else {
3655         bmin = mn<float>(bmin,val);
3656         bmax = mx<float>(bmax,val);
3657       }
3658     }}
3659 
3660     //a_bins.bins_Sw_range(bmin,bmax,false);
3661 
3662     //modeling_profile could override errors_visible.
3663     bool errors_visible = a_errors_style.visible;
3664 
3665     if(a_data_style.visible) {
3666 
3667       painting_policy painting = a_data_style.painting;
3668       if(painting==painting_by_value) {
3669         m_bins_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_data_style.color_mapping);
3670       } else if( (painting==painting_grey_scale) ||
3671                  (painting==painting_grey_scale_inverse) ||
3672                  (painting==painting_violet_to_red) ){
3673        {float dbins = bmax-bmin;
3674         if(dbins!=0.0F) {
3675           for(size_t index=0;index<xnbin;index++) bins[index].m_ratio = (a_bins.bin_Sw(int(index))-bmin)/dbins;
3676         }}
3677         if(painting==painting_grey_scale) {
3678           m_bins_cmaps[a_index] = new grey_scale_colormap(bmin,bmax,50);
3679         } else if(painting==painting_grey_scale_inverse) {
3680           m_bins_cmaps[a_index] = new grey_scale_inverse_colormap(bmin,bmax,50);
3681         } else if(painting==painting_violet_to_red) {
3682           m_bins_cmaps[a_index] = new violet_to_red_colormap(bmin,bmax,50);
3683         }
3684       } else {
3685         m_bins_cmaps[a_index] = new const_colormap(a_data_style.color);
3686       }
3687 
3688       if(a_bins.is_profile()) {
3689         // enforce with a_data_style, a bins rep with :
3690         //  rep_bins1D_xy_points
3691         // AND :
3692         //  rep_errors_plus for bins rep.
3693         // NOTE : a_data_style.modeling not used for the moment.
3694         //printf("debug : bins is profile : modeling %s\n",a_data_style.modeling.value().c_str());
3695 
3696         style data_style = a_data_style;
3697         data_style.modeling = modeling_markers();
3698         rep_bins1D_xy_points(a_out,data_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz);
3699 
3700         std::vector<float> bars(xnbin);
3701         for(size_t ibin=0;ibin<xnbin;ibin++) bars[ibin] = a_bins.bin_error(int(ibin));
3702 
3703         rep_errors_plus_xy(a_out,a_data_style,bins,a_box_x,a_box_y,bars,a_zz+_zerrors());
3704         errors_visible = false;
3705 
3706       } else {
3707 
3708         const std::string& modeling = a_data_style.modeling;
3709 
3710         //bool one_node = false;
3711         //bool oneNode = false;
3712        //{int nlimit = aGraphicStyle.multiNodeLimit.value();
3713         //if(nlimit!=NoLimit) {
3714         //  oneNode = (xnbin>nlimit?true:false);
3715         //}}
3716 
3717         bool _bar_chart = false;
3718 
3719         //char sid_bin[128];
3720         //::sprintf(sid_bin,"SbBin1D/0x%lx",(unsigned long)&a_bins);
3721 
3722         if((modeling==modeling_points())||(modeling==modeling_markers())){
3723           //if(oneNode) {
3724           //  rep_bins1D_xy_points_one(binsNode,aGraphicStyle,
3725           //                       bins,a_box_x,a_box_y,a_zz,std::string(sid));
3726           //} else {
3727             rep_bins1D_xy_points(a_out,a_data_style,
3728                                  *(m_bins_cmaps[a_index]),
3729                                  bins,a_box_x,a_box_y,a_zz);
3730           //}
3731         } else if(modeling==modeling_boxes()) {
3732           //if(oneNode) {
3733           //  rep_bins1D_xy_boxes_one(binsNode,aGraphicStyle,
3734           //                      bins,a_box_x,a_box_y,a_zz,std::string(sid));
3735           //} else {
3736             rep_bins1D_xy_boxes(a_data_style,
3737                                 *(m_bins_cmaps[a_index]),
3738                                 bins,a_box_x,a_box_y,a_zz //,std::string(sid_bin)
3739                                 );
3740           //}
3741 
3742         } else if(modeling==modeling_wire_boxes()) {
3743           //if(oneNode) {
3744           //  rep_bins1D_xy_wire_boxes_one(binsNode,aGraphicStyle,barChart,
3745           //                           bins,a_box_x,a_box_y,a_zz,std::string(sid));
3746           //} else {
3747             rep_bins1D_xy_wire_boxes(a_data_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz,false);
3748           //}
3749         } else if(modeling==modeling_bar_chart()) {
3750            _bar_chart = true;
3751           //if(oneNode) {
3752           //  rep_bins1D_xy_wire_boxes_one(binsNode,aGraphicStyle,barChart,
3753           //                           bins,a_box_x,a_box_y,a_zz,std::string(sid));
3754           //} else {
3755             rep_bins1D_xy_wire_boxes(a_data_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz,true);
3756           //}
3757 
3758         } else if(modeling==modeling_lines()){
3759           rep_bins1D_xy_lines_one(a_data_style,bins,a_box_x,a_box_y,a_zz/*,std::string(sid)*/);
3760         } else if(modeling==modeling_curve()){
3761           rep_bins1D_xy_curve_one(a_out,a_data_style,bins,a_box_x,a_box_y,a_zz/*,std::string(sid)*/);
3762 
3763         } else if(modeling==modeling_top_lines_boxes()) { //gopaw. pawex24, k_plus.
3764           style _style;_style.color = colorf_white();
3765           rep_bins1D_xy_boxes(_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz);
3766           rep_bins1D_xy_top_lines(a_data_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz+_zhatch());
3767 
3768         } else { //default modeling==modeling_top_lines()
3769           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)*/);
3770 
3771         }
3772 
3773         hatching_policy hatching = a_data_style.hatching.value();
3774         //::printf("debug : bins1D %d hatching : %d\n",a_index,hatching);
3775         if(hatching!=hatching_none) {
3776           // WARNING : must come AFTER rep_bins1_xy.
3777           if((hatching==hatching_right)||((hatching==hatching_left_and_right))) {
3778             //if(oneNode) {
3779               //repHatch1D_xy_one(binsNode,aRightHatchStyle,barChart,bins,a_box_x,a_box_y,a_zz+_zhatch(),std::string(sid));
3780             //} else {
3781               rep_hatch1D_xy(a_right_hatch_style,bins,a_box_x,a_box_y,a_zz+_zhatch(),_bar_chart);
3782             //}
3783           }
3784           if((hatching==hatching_left)||((hatching==hatching_left_and_right))) {
3785             //if(oneNode) {
3786               //repHatch1D_xy_one(binsNode,aLeftHatchStyle,barChart,bins,a_box_x,a_box_y,a_zz+_zhatch(),std::string(sid));
3787             //} else {
3788               rep_hatch1D_xy(a_left_hatch_style,bins,a_box_x,a_box_y,a_zz+_zhatch(),_bar_chart);
3789             //}
3790           }
3791         }
3792 
3793       } //end !is_profile.
3794     } //end data_style visible
3795 
3796     // Errors :
3797     if(errors_visible) {
3798       std::vector<float> bars(xnbin);
3799       for(size_t ibin=0;ibin<xnbin;ibin++) bars[ibin] = a_bins.bin_error(int(ibin));
3800       const std::string& modeling = a_errors_style.modeling;
3801       if(modeling==modeling_plus()) {
3802         rep_errors_plus_xy(a_out,a_errors_style,bins,a_box_x,a_box_y,bars,a_zz+_zerrors());
3803       } else { //modeling_I()
3804         rep_errors_I_xy(a_out,a_errors_style,bins,a_box_x,a_box_y,bars,a_zz+_zerrors());
3805       }
3806     }
3807 
3808   }
3809 
3810   static bool bins2D_to_func(const bins2D& a_bins,float a_X,float a_Y,float& a_value){
3811     unsigned int xn = a_bins.x_bins();
3812     float xmn = a_bins.x_axis_min();
3813     float xmx = a_bins.x_axis_max();
3814     unsigned int yn = a_bins.y_bins();
3815     float ymn = a_bins.y_axis_min();
3816     float ymx = a_bins.y_axis_max();
3817 
3818     float dx = (xmx-xmn)/xn;
3819     float dy = (ymx-ymn)/yn;
3820     int ibin = (int)((a_X-xmn)/dx);
3821     int jbin = (int)((a_Y-ymn)/dy);
3822 
3823     if((ibin<0)||(ibin>=int(xn))) {a_value=0;return false;}
3824     if((jbin<0)||(jbin>=int(yn))) {a_value=0;return false;}
3825 
3826     float xx_0 = a_bins.bin_lower_edge_x(ibin);
3827     //float xe_0 = a_bins.bin_upper_edge_x(ibin);
3828     float xx_1 = a_bins.bin_lower_edge_x(ibin+1);
3829     //float xe_1 = a_bins.bin_upper_edge_x(ibin+1);
3830 
3831     float yy_0 = a_bins.bin_lower_edge_y(jbin);
3832     //float ye_0 = a_bins.bin_upper_edge_y(jbin);
3833     float yy_1 = a_bins.bin_lower_edge_y(jbin+1);
3834     //float ye_1 = a_bins.bin_upper_edge_y(jbin+1);
3835 
3836     float val1 = a_bins.bin_Sw(ibin,jbin);
3837     float val2 = a_bins.bin_Sw(ibin+1,jbin);
3838     //float val3 = a_bins.getBinSumOfWeights(ibin+1,jbin+1);
3839     float val4 = a_bins.bin_Sw(ibin,jbin+1);
3840 
3841     // Interpolate :
3842     vec3f p1(xx_0,yy_0,val1);
3843     vec3f p2(xx_1,yy_0,val2);
3844     //vec3f p3(xx_1,yy_1,val3);
3845     vec3f p4(xx_0,yy_1,val4);
3846 
3847     //FIXME : case of (x,y) in (p2,p3,p4)
3848 
3849     plane<vec3f> _plane(p1,p2,p4);
3850     vec3f pt;
3851     line<vec3f> _line(vec3f(a_X,a_Y,0),vec3f(a_X,a_Y,10));
3852     _plane.intersect(_line,pt);
3853 
3854     a_value = pt[2];
3855     return true;
3856   }
3857 
3858   typedef struct {
3859     const func2D* m_func2D;
3860     const bins2D* m_bins2D;
3861     double m_limits[4];
3862     double m_limits_in[4];
3863     bool m_problem;
3864   } SbFunc;
3865 
3866   static double bins2D_to_contour(double a_X,double a_Y,void* aData) {
3867     SbFunc* func =(SbFunc*)aData;
3868     if( (a_X<func->m_limits_in[0])||
3869         (a_X>func->m_limits_in[1])||
3870         (a_Y<func->m_limits_in[2])||
3871         (a_Y>func->m_limits_in[3])
3872       ) return -FLT_MAX;
3873     float value;
3874     if(!bins2D_to_func(*(func->m_bins2D),(float)a_X,(float)a_Y,value)) func->m_problem = true;
3875     return value;
3876   }
3877 
3878   static double log_bins2D_to_contour(double a_X,double a_Y,void* aData) {
3879     SbFunc* func =(SbFunc*)aData;
3880     if( (a_X<func->m_limits_in[0])||
3881         (a_X>func->m_limits_in[1])||
3882         (a_Y<func->m_limits_in[2])||
3883         (a_Y>func->m_limits_in[3])
3884       ) return -FLT_MAX;
3885     float value;
3886     if(!bins2D_to_func(*(func->m_bins2D),(float)a_X,(float)a_Y,value)) func->m_problem = true;
3887     return take_log(value);
3888   }
3889 
3890   void update_bins2D_xy(std::ostream& a_out,
3891                         const bins2D& a_bins,
3892                         const style& a_data_style,
3893                         int a_index,
3894                         const rep_box& a_box_x,
3895                         const rep_box& a_box_y,
3896                         const rep_box& a_box_z,
3897                         float a_zz){
3898 
3899     //a_out << "tools::sg::update_bins2D_xy : begin :" << std::endl;
3900 
3901     if(!a_data_style.visible) return;
3902 
3903     //a_out << "tools::sg::update_bins2D_xy : visible :" << std::endl;
3904 
3905     unsigned int xnbin = a_bins.x_bins();
3906     unsigned int ynbin = a_bins.y_bins();
3907 
3908     const std::string& modeling = a_data_style.modeling;
3909 
3910     if( (modeling==modeling_curve()) || (modeling==modeling_filled_curve()) ){
3911 
3912       a_out << "tools::sg::update_bins2D_xy : modeling_curve :" << std::endl;
3913 
3914       painting_policy painting = a_data_style.painting;
3915 
3916       float zmin = a_box_z.m_pos;
3917       float dz = a_box_z.m_width;
3918       bool zlog = a_box_z.m_log;
3919 
3920       float xmn =  m_x_axis_data.min_value();
3921       float xmx =  m_x_axis_data.max_value();
3922       float ymn =  m_y_axis_data.min_value();
3923       float ymx =  m_y_axis_data.max_value();
3924 
3925       clist_contour list_contour;
3926       //int nFir = 32;
3927       int nFir = 128;
3928       list_contour.set_first_grid(nFir,nFir); //Default : 32,32
3929       //int nSec = 256;
3930       int nSec = 512; //slower than 256
3931       list_contour.set_secondary_grid(nSec,nSec); //Default : 256,256.
3932 
3933       double limits[4];
3934       // User limits :
3935       limits[0] = xmn;
3936       limits[1] = xmx;
3937       limits[2] = ymn;
3938       limits[3] = ymx;
3939 
3940       SbFunc sbFunc;
3941       sbFunc.m_func2D = 0;
3942       sbFunc.m_problem = false;
3943       sbFunc.m_bins2D = &a_bins;
3944       sbFunc.m_limits_in[0] = limits[0];
3945       sbFunc.m_limits_in[1] = limits[1];
3946       sbFunc.m_limits_in[2] = limits[2];
3947       sbFunc.m_limits_in[3] = limits[3];
3948 
3949       // Extend the grid to have some borders in order to close contours :
3950       int n = nSec - 2 * 10;
3951       double dx = (limits[1]-limits[0]) /n;
3952       double dy = (limits[3]-limits[2]) /n;
3953       limits[0] = limits[0] - 10 * dx;
3954       limits[1] = limits[1] + 10 * dx;
3955       limits[2] = limits[2] - 10 * dy;
3956       limits[3] = limits[3] + 10 * dy;
3957 
3958       sbFunc.m_limits[0] = limits[0];
3959       sbFunc.m_limits[1] = limits[1];
3960       sbFunc.m_limits[2] = limits[2];
3961       sbFunc.m_limits[3] = limits[3];
3962 
3963       list_contour.set_limits(limits);
3964 
3965       if(levels.size()) {
3966         size_t zn = levels.size();
3967         std::vector<double> zs(zn);
3968         for(size_t zi=0;zi<zn;zi++) zs[zi] = levels[zi];
3969         list_contour.set_planes(zs);
3970       } else {
3971         unsigned int zn = number_of_levels.value();
3972         if(zn<=0) zn = 1;
3973         std::vector<double> zs(zn+1);
3974         float zmax = zmin + dz;
3975         double zd = (zmax-zmin)/zn;
3976         for(unsigned int zi=0;zi<=zn;zi++) zs[zi] = zmin + zi * zd;
3977         list_contour.set_planes(zs);
3978       }
3979 
3980       if(zlog)
3981         list_contour.set_field_fcn(log_bins2D_to_contour,(void*)&sbFunc);
3982       else
3983         list_contour.set_field_fcn(bins2D_to_contour,(void*)&sbFunc);
3984 
3985 #ifdef INLIBS_SG_PLOTTER_TIMING
3986       atime _start = atime::now();
3987 #endif
3988       list_contour.ccontour::generate();
3989 #ifdef INLIBS_SG_PLOTTER_TIMING
3990       a_out << "tools::sg::update_bins2D_xy : contour generate elapsed " << atime::elapsed(_start) << "." << std::endl;
3991       _start = atime::now();
3992 #endif
3993 
3994       if(!list_contour.compact_strips ()) {
3995         a_out << "tools::sg::plotter::updateBins2D_XY : clist_contour::compact_strips () : failure." << std::endl;
3996       } else {
3997 #ifdef INLIBS_SG_PLOTTER_TIMING
3998         a_out << "tools::sg::update_bins2D_xy : contour compact strips elapsed " << atime::elapsed(_start) << "." << std::endl;
3999 #endif
4000         if( (painting==painting_by_level) || (painting==painting_by_value) ){
4001           m_bins_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_data_style.color_mapping);
4002           //bool zlog = a_box_z.m_log;
4003           if(zlog) m_bins_cmaps[a_index]->set_PAW_coloring();
4004         } else {
4005           m_bins_cmaps[a_index] = new const_colormap(a_data_style.color);
4006         }
4007 
4008         if(modeling==modeling_filled_curve()) {
4009           rep_contour_xy_filled(a_out,a_data_style,
4010                                 painting,*(m_bins_cmaps[a_index]),
4011                                 list_contour,a_box_x,a_box_y,a_box_z,a_zz /*,std::string(sid.c_str())*/);
4012         } else {
4013           rep_contour_xy(a_out,a_data_style,
4014                          painting,*(m_bins_cmaps[a_index]),
4015                          list_contour,a_box_x,a_box_y,a_box_z,a_zz /*,std::string(sid.c_str())*/);
4016         }
4017 
4018       }
4019 
4020       if(sbFunc.m_problem) {
4021         a_out << "tools::sg::plotter::updateFunction_XY(SbPlottableFunction2D) : "
4022               << "problem when getting some function value." << std::endl;
4023       }
4024 
4025     } else {
4026 
4027       bool hbe = a_bins.has_entries_per_bin();
4028 
4029       float bmin = 0;
4030       float bmax = 0;
4031 
4032       std::vector<rep_bin2D> bins;
4033      {bool first = true;
4034       for(int jbin=ynbin-1;jbin>=0;jbin--) {
4035         for(int ibin=xnbin-1;ibin>=0;ibin--) {
4036           if(hbe && (a_bins.bin_entries(ibin,jbin)<=0)) continue;
4037 
4038           float val = a_bins.bin_Sw(ibin,jbin);
4039 
4040           float xx = a_bins.bin_lower_edge_x(ibin);
4041           float xe = a_bins.bin_upper_edge_x(ibin);
4042           float yy = a_bins.bin_lower_edge_y(jbin);
4043           float ye = a_bins.bin_upper_edge_y(jbin);
4044 
4045           bins.push_back(rep_bin2D(xx,xe,yy,ye,val,ibin,jbin));
4046 
4047           if(first) {
4048             first = false;
4049             bmin = val;
4050             bmax = val;
4051           } else {
4052             bmin = mn<float>(bmin,val);
4053             bmax = mx<float>(bmax,val);
4054           }
4055         }
4056       }}
4057       size_t number = bins.size();
4058 
4059       //a_bins.bins_Sw_range(bmin,bmax,false);
4060 
4061       painting_policy painting = a_data_style.painting;
4062       if(painting==painting_by_value) {
4063         m_bins_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_data_style.color_mapping);
4064       } else if( (painting==painting_grey_scale) ||
4065                  (painting==painting_grey_scale_inverse) ||
4066                  (painting==painting_violet_to_red) ){
4067        {float dbins = bmax-bmin;
4068         if(dbins!=0.0F) {
4069           for(size_t index=0;index<number;index++) {
4070             bins[index].m_ratio = (bins[index].m_val-bmin)/dbins;
4071           }
4072         }}
4073         if(painting==painting_grey_scale) {
4074           m_bins_cmaps[a_index] = new grey_scale_colormap(bmin,bmax,50);
4075         } else if(painting==painting_grey_scale_inverse) {
4076           m_bins_cmaps[a_index] = new grey_scale_inverse_colormap(bmin,bmax,50);
4077         } else if(painting==painting_violet_to_red) {
4078           m_bins_cmaps[a_index] = new violet_to_red_colormap(bmin,bmax,50);
4079         }
4080       } else {
4081         m_bins_cmaps[a_index] = new const_colormap(a_data_style.color);
4082       }
4083 
4084       if(modeling==modeling_solid()) {
4085         //a_out << "tools::sg::update_bins2D_xy : modeling_solid :" << std::endl;
4086 
4087         rep_bins2D_xy_solid(a_data_style,*(m_bins_cmaps[a_index]),bins,a_box_x,a_box_y,a_zz);
4088 
4089       } else if(modeling==modeling_points()) {
4090         //a_out << "tools::sg::update_bins2D_xy : modeling_points :" << std::endl;
4091         rep_bins2D_xy_random_one(a_data_style,bins,a_box_x,a_box_y,bmin,bmax,a_zz/*,std::string(sid)*/);
4092 
4093       } else if(modeling==modeling_wire_boxes()) {
4094         //a_out << "tools::sg::update_bins2D_xy : modeling_wire_boxes :" << std::endl;
4095 
4096         // one node decision :
4097       /*bool oneNode = false;
4098        {int nlimit = aGraphicStyle.multiNodeLimit.value();
4099         if(nlimit!=NoLimit) {
4100           oneNode = (number>nlimit?true:false);
4101         }}*/
4102 
4103       /*if(oneNode) {
4104           rep_bins2D_xy_wire_box_one(a_data_style,bins,a_box_x,a_box_y,bmin,bmax,std::string(sid));
4105         } else {*/
4106           rep_bins2D_xy_wire_box(a_data_style,bins,a_box_x,a_box_y,bmin,bmax,a_zz/*,std::string(sid_bin)*/);
4107         //}
4108 
4109       } else if(modeling==modeling_texts()) {
4110         //a_out << "tools::sg::update_bins2D_xy : modeling_wire_texts :" << std::endl;
4111 
4112         // one node decision :
4113       //bool oneNode = false;
4114      //{int nlimit = aGraphicStyle.multiNodeLimit.value();
4115       // if(nlimit!=NoLimit) {
4116       //   oneNode = (number>nlimit?true:false);
4117       //}}
4118 
4119         //if(oneNode) {
4120         //  rep_bins2D_xy_text_one(binsNode,
4121         //                        aGraphicStyle,
4122         //                        bins,a_box_x,a_box_y,std::string(sid));
4123         //} else {
4124           rep_bins2D_xy_text(a_data_style,bins,a_box_x,a_box_y/*,std::string(sid_bin)*/);
4125        //}
4126 
4127       } else { //default rep modeling==modeling_boxes()
4128         //a_out << "tools::sg::update_bins2D_xy : modeling_<else> :" << std::endl;
4129 
4130         rep_bins2D_xy_box(a_data_style,bins,a_box_x,a_box_y,bmin,bmax,a_zz);
4131 
4132       }
4133 
4134 
4135     } //end if modeling
4136 
4137   }
4138 
4139   void update_func1D_xy(std::ostream& a_out,const func1D& a_func,
4140                         const style& a_style,const rep_box& a_box_x,const rep_box& a_box_y,float a_zz){
4141 
4142     //a_out << "debug : tools::sg::plotter::update_func1D_xy : modeling " << a_style.modeling.value() << " :" << std::endl;
4143 
4144     if(!a_style.visible) return;
4145 
4146     float xmn = m_x_axis_data.min_value();
4147     float xmx = m_x_axis_data.max_value();
4148 
4149     unsigned int nstp = a_func.x_steps();
4150     nstp = nstp <=0 ? curve_number_of_points.value() : nstp;
4151 
4152     float df = (xmx - xmn)/nstp;
4153 
4154     bool problem = false;
4155     std::vector<vec3f> points(nstp+1);
4156     for(unsigned int ibin=0;ibin<=nstp;ibin++) {
4157       float xx = xmn + ibin * df;
4158       float val;
4159       if(!a_func.value(xx,val)) problem = true;
4160       points[ibin].set_value(xx,val,a_zz);
4161     }
4162     if(problem) {
4163       a_out << "tools::sg::plotter::update_func1D_xy :"
4164             << " problem when getting some function value."
4165             << std::endl;
4166     }
4167 
4168     const std::string& modeling = a_style.modeling;
4169 
4170     if(modeling==modeling_points()){
4171       vertices* vtxs = new vertices;
4172       std::vector<float>& pts = vtxs->xyzs.values(); //npt*3
4173       clip_points_2D(points,a_box_x,a_box_y,pts);
4174       if(pts.size()) {
4175         //a_out << "debug : tools::sg::plotter::update_func1D_xy :"
4176         //      << " ptn " << pts.size()
4177         //      << std::endl;
4178 
4179         separator* sep = new separator;
4180         m_func_sep.add(sep);
4181 
4182         rgba* mat = new rgba();
4183         mat->color = a_style.color;
4184         sep->add(mat);
4185 
4186         draw_style* ds = new draw_style;
4187         ds->style = draw_points;
4188         ds->point_size = a_style.point_size;
4189         sep->add(ds);
4190 
4191         vtxs->mode = gl::points();
4192         sep->add(vtxs);
4193       } else {
4194         delete vtxs;
4195       }
4196 
4197     } else if(modeling==modeling_markers()){
4198       markers* _marks = new markers;
4199       std::vector<float>& pts = _marks->xyzs.values(); //npt*3
4200       clip_points_2D(points,a_box_x,a_box_y,pts);
4201       if(pts.size()) {
4202         //a_out << "debug : tools::sg::plotter::update_func1D_xy :"
4203         //      << " ptn " << pts.size()
4204         //      << std::endl;
4205 
4206         separator* sep = new separator;
4207         m_func_sep.add(sep);
4208 
4209         rgba* mat = new rgba();
4210         mat->color = a_style.color;
4211         sep->add(mat);
4212 
4213         _marks->size = a_style.marker_size;
4214         _marks->style = a_style.marker_style;
4215         sep->add(_marks);
4216       } else {
4217         delete _marks;
4218       }
4219 
4220     } else {
4221 
4222       vertices* vtxs = new vertices;
4223       std::vector<float>& pts = vtxs->xyzs.values(); //npt*3
4224 
4225       clip_polyline_2D(points,a_box_x,a_box_y,pts);
4226       if(pts.size()) {
4227         //a_out << "debug : tools::sg::plotter::update_func1D_xy : ptn " << pts.size() << std::endl;
4228 
4229         separator* sep = new separator;
4230         m_func_sep.add(sep);
4231 
4232         rgba* mat = new rgba();
4233         mat->color = a_style.color;
4234         sep->add(mat);
4235 
4236         draw_style* ds = new draw_style;
4237         ds->style = draw_lines;
4238         ds->line_pattern = a_style.line_pattern;
4239         ds->line_width = a_style.line_width;
4240         sep->add(ds);
4241 
4242         vtxs->mode = gl::line_strip();
4243         sep->add(vtxs);
4244       } else {
4245         delete vtxs;
4246       }
4247     }
4248   }
4249 
4250   static double function_to_contour(double a_X,double a_Y,void* aData) {
4251     SbFunc* func = (SbFunc*)aData;
4252     if( (a_X<func->m_limits_in[0])||
4253         (a_X>func->m_limits_in[1])||
4254         (a_Y<func->m_limits_in[2])||
4255         (a_Y>func->m_limits_in[3])
4256       ) return -FLT_MAX;
4257     float value;
4258     if(!func->m_func2D->value((float)a_X,(float)a_Y,value)) func->m_problem = true;
4259     return double(value);
4260   }
4261   static double log_function_to_contour(double a_X,double a_Y,void* aData) {
4262     SbFunc* func =(SbFunc*)aData;
4263     if( (a_X<func->m_limits_in[0])||
4264         (a_X>func->m_limits_in[1])||
4265         (a_Y<func->m_limits_in[2])||
4266         (a_Y>func->m_limits_in[3])
4267       ) return -FLT_MAX;
4268     float value;
4269     if(!func->m_func2D->value((float)a_X,(float)a_Y,value)) func->m_problem = true;
4270     return take_log(value);
4271   }
4272 
4273   void update_func2D_xy(std::ostream& a_out,const func2D& a_func,int a_index,style& a_data_style,
4274                         const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z,float a_zz){
4275     //a_out << "debug : tools::sg::plotter::update_func2D_xy(Function2D) : begin :" << std::endl;
4276     if(!a_data_style.visible.value()) return;
4277 
4278   //  std::string sid;
4279   // {std::string sp;
4280   //  if(!p2sx(&a_func,sp)){}
4281   //  sid = "SbFunction2D/"+sp;}
4282 
4283     const std::string& modeling = a_data_style.modeling.getValue();
4284     painting_policy painting = a_data_style.painting;
4285 
4286     if( (modeling==modeling_curve()) || (modeling==modeling_filled_curve()) ) {
4287 
4288       //a_out << "debug : tools::sg::plotter::update_func2D_xy(Function2D) : curve." << std::endl;
4289 
4290       float zmin = a_box_z.m_pos;
4291       float dz = a_box_z.m_width;
4292       bool zlog = a_box_z.m_log;
4293 
4294       float xmn = m_x_axis_data.min_value();
4295       float xmx = m_x_axis_data.max_value();
4296       float ymn = m_y_axis_data.min_value();
4297       float ymx = m_y_axis_data.max_value();
4298 
4299       clist_contour list_contour;
4300       //int nFir = 32;
4301       int nFir = 128;
4302       list_contour.set_first_grid(nFir,nFir); //Default : 32,32
4303       //int nSec = 256;
4304       int nSec = 512; //slower than 256
4305       list_contour.set_secondary_grid(nSec,nSec); //Default : 256,256.
4306 
4307       double limits[4];
4308       // User limits :
4309       limits[0] = xmn;
4310       limits[1] = xmx;
4311       limits[2] = ymn;
4312       limits[3] = ymx;
4313 
4314       SbFunc sbFunc;
4315       sbFunc.m_func2D = &a_func;
4316       sbFunc.m_problem = false;
4317       sbFunc.m_bins2D = 0;
4318       sbFunc.m_limits_in[0] = limits[0];
4319       sbFunc.m_limits_in[1] = limits[1];
4320       sbFunc.m_limits_in[2] = limits[2];
4321       sbFunc.m_limits_in[3] = limits[3];
4322 
4323       // Extend the grid to have some borders in order to close contours :
4324       int n = nSec - 2 * 10;
4325       double dx = (limits[1]-limits[0]) /n;
4326       double dy = (limits[3]-limits[2]) /n;
4327       limits[0] = limits[0] - 10 * dx;
4328       limits[1] = limits[1] + 10 * dx;
4329       limits[2] = limits[2] - 10 * dy;
4330       limits[3] = limits[3] + 10 * dy;
4331 
4332       sbFunc.m_limits[0] = limits[0];
4333       sbFunc.m_limits[1] = limits[1];
4334       sbFunc.m_limits[2] = limits[2];
4335       sbFunc.m_limits[3] = limits[3];
4336 
4337       list_contour.set_limits(limits);
4338 
4339       if(levels.getNum()) {
4340         size_t zn = levels.size();
4341         std::vector<double> zs(zn);
4342         for(size_t zi=0;zi<zn;zi++) zs[zi] = levels[zi];
4343         list_contour.set_planes(zs);
4344       } else {
4345         unsigned int zn = number_of_levels;
4346         if(zn<=0) zn = 1;
4347         std::vector<double> zs(zn+1);
4348         float zmax = zmin + dz;
4349         double zd = (zmax-zmin)/zn;
4350         for(unsigned int zi=0;zi<=zn;zi++) zs[zi] = zmin + zi * zd;
4351         list_contour.set_planes(zs);
4352       }
4353 
4354       if(zlog) {
4355         list_contour.set_field_fcn(log_function_to_contour,(void*)&sbFunc);
4356       } else {
4357         list_contour.set_field_fcn(function_to_contour,(void*)&sbFunc);
4358       }
4359 
4360 #ifdef INLIBS_SG_PLOTTER_TIMING
4361       atime _start = atime::now();
4362 #endif
4363       list_contour.ccontour::generate();
4364 
4365 #ifdef INLIBS_SG_PLOTTER_TIMING
4366       a_out << "tools::sg::update_func2D_xy : contour generate elapsed " << atime::elapsed(_start) << "." << std::endl;
4367       _start = atime::now();
4368 #endif
4369 
4370       if(!list_contour.compact_strips ()) {
4371         a_out << "tools::sg::plotter::update_func2D_xy : clist_contour::compact_strips () : failure." << std::endl;
4372       } else {
4373 #ifdef INLIBS_SG_PLOTTER_TIMING
4374         a_out << "tools::sg::update_func2D_xy : contour compact strips elapsed " << atime::elapsed(_start) << "." << std::endl;
4375 #endif
4376         if( (painting==painting_by_level) || (painting==painting_by_value) ){
4377           m_func_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_data_style.color_mapping.value());
4378           //bool zlog = a_box_z.m_log;
4379           if(zlog) m_func_cmaps[a_index]->set_PAW_coloring();
4380         } else {
4381           m_func_cmaps[a_index] = new const_colormap(a_data_style.color.value());
4382         }
4383 
4384         if(modeling==modeling_filled_curve()) {
4385           rep_contour_xy_filled(a_out,a_data_style,
4386                                 painting,*(m_func_cmaps[a_index]),
4387                                 list_contour,a_box_x,a_box_y,a_box_z,a_zz /*,std::string(sid.c_str())*/);
4388         } else {
4389           rep_contour_xy(a_out,a_data_style,
4390                          painting,*(m_func_cmaps[a_index]),
4391                          list_contour,a_box_x,a_box_y,a_box_z,a_zz /*,std::string(sid.c_str())*/);
4392         }
4393       }
4394 
4395       if(sbFunc.m_problem) {
4396         a_out << "tools::sg::plotter::update_func2D_xy : problem when getting some function value." << std::endl;
4397       }
4398 
4399   /*
4400     } else if(modeling==SbModeling_polygon) {
4401 
4402       int npoint = a_func.getNumberOfPoints();
4403       if(npoint) {
4404 
4405       std::vector<vec3f> points(npoint);
4406       std::vector<int> controls;
4407       for(int count=0;count<npoint;count++) {
4408         float xx,yy;
4409         bool isControl;
4410         a_func.getIthPoint(count,xx,yy,isControl);
4411         points[count] = vec3f(xx,yy,a_zz);
4412         if(isControl) controls.push_back(count);
4413       }
4414       //check closure :
4415       if((points.size()>=2) && (points[points.size()-1]!=points[0]) ) {
4416         points.push_back(points[0]);
4417       }
4418 
4419       project2D(points,a_box_x,a_box_y);
4420 
4421       bool editable = a_data_style.editable.getValue();
4422       if(!editable) {
4423         clip<float> clipper;
4424        {size_t ptn = points.size();
4425         for(size_t index=0;index<ptn;index++) clipper.add(points[index]);}
4426 
4427         plane<vec3f> plane_xy_bot(vec3f(0, 1,0),vec3f(0,0,0));
4428         plane<vec3f> plane_xy_top(vec3f(0,-1,0),vec3f(0,1,0));
4429         plane<vec3f> plane_yz_left (vec3f( 1, 0,0),vec3f(0,0,0));
4430         plane<vec3f> plane_yz_right(vec3f(-1, 0,0),vec3f(1,0,0));
4431 
4432         clipper.execute(plane_xy_bot);
4433         clipper.execute(plane_xy_top);
4434         clipper.execute(plane_yz_left);
4435         clipper.execute(plane_yz_right);
4436 
4437        {int n = clipper.getNumVertices();
4438         points.resize(n);
4439         for(int index=0;index<n;index++) {
4440           clipper.getVertex(index,points[index]);
4441         }}
4442         if((points.size()>=2) && (points[points.size()-1]!=points[0]) ) {
4443           points.push_back(points[0]);
4444         }
4445       }
4446 
4447       int ptn = points.size();
4448       if(ptn) {
4449       vec3f* pts = &(points[0]);
4450 
4451       SoSceneGraph* separator = new SoSceneGraph();
4452       separator->setString(sid.c_str());
4453       functionNode->addChild(separator);
4454 
4455       SoSeparator* sep = new SoSeparator;
4456       separator->addChild(sep);
4457 
4458       sep->addChild(fStyleCache->getFilled());
4459       sep->addChild(fStyleCache->getNormalBindingOverall());
4460       sep->addChild(fStyleCache->getNormalZ());
4461       sep->addChild(fStyleCache->getMaterial(a_data_style.color.getValue(),a_data_style.transparency.getValue()));
4462 
4463       SoCoordinate3* coordinate3 = new SoCoordinate3;
4464       coordinate3->point.setValues(0,ptn,pts);
4465       sep->addChild(coordinate3);
4466 
4467       SoFaceSet* faceSet = new SoFaceSet;
4468       faceSet->numVertices.set1Value(0,ptn);
4469       sep->addChild(faceSet);
4470 
4471       sep->addChild(fStyleCache->getLineStyle(SbLinePattern_solid,1));
4472       sep->addChild(fStyleCache->getMaterial(SbColor_black,0));
4473 
4474       //NOTE : we could simply add faceSet again !
4475       SoLineSet* lineSet = new SoLineSet;
4476       lineSet->numVertices.set1Value(0,ptn);
4477       sep->addChild(lineSet);
4478 
4479       if(editable) {
4480         SoSeparator* sep = new SoSeparator;
4481         separator->addChild(sep);
4482 
4483         float scale = 0.05F;
4484 
4485         for(int index=0;index<controls.size();index++) {
4486           int icontrol = controls[index];
4487           const vec3f& pt = pts[icontrol];
4488 
4489           SoSeparator* sp = new SoSeparator;
4490           sep->addChild(sp);
4491 
4492           SoTransform* tsf = new SoTransform();
4493           tsf->translation.setValue(pt);
4494           tsf->scaleFactor.setValue(scale,scale,scale);
4495           sp->addChild(tsf);
4496 
4497           SoPlotter_dragger* dragger =
4498             new SoPlotter_dragger(*coordinate3,icontrol,scale,*this,const_cast<SbPlottableFunction2D&>(a_func),a_box_x,a_box_y,a_zz);
4499           SoTools_setDraggerColor(*dragger,SbColor_red);
4500           sp->addChild(dragger);
4501         }
4502       }
4503 
4504       } //ptn
4505       } //npoint
4506 
4507   */
4508     } else {
4509       a_out << "tools::sg::plotter::update_func2D_xy :"
4510             << " modeling " << modeling
4511           << " does not apply on Functi  on2D in XY. Valid modelings ared curve, filled_curve and polygon."
4512           << std::endl;
4513     }
4514 
4515   }
4516 
4517   void update_points2D_xy(std::ostream& a_out,const points2D& a_points,const style& a_style,
4518                           const rep_box& a_box_x,const rep_box& a_box_y,float a_zz) {
4519 
4520     //a_out << "debug : tools::sg::plotter::update_points2D_xy : modeling " << a_style.modeling.value() << std::endl;
4521 
4522     if(!a_style.visible) return;
4523 
4524     size_t number = a_points.points();
4525     if(!number) return;
4526 
4527     const std::string& modeling = a_style.modeling;
4528 
4529     if(modeling==modeling_lines()) {
4530       rep_points2D_xy_lines(a_style,a_points,a_box_x,a_box_y,a_zz);
4531     } else if(modeling==modeling_curve()) {
4532       rep_points2D_xy_curve(a_out,a_style,a_points,a_box_x,a_box_y,a_zz);
4533     } else {
4534       rep_points2D_xy_points(a_out,a_style,a_points,a_box_x,a_box_y,a_zz);
4535     }
4536   }
4537 
4538   void update_points3D_xyz(std::ostream& a_out,const points3D& a_points,const style& a_style,
4539                            const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z) {
4540 
4541     //a_out << "debug : tools::sg::plotter::update_points3D_xyz : modeling " << a_style.modeling.value() << std::endl;
4542 
4543     if(!a_style.visible) return;
4544 
4545     size_t number = a_points.points();
4546     if(!number) return;
4547 
4548     rep_points3D_xyz_points(a_out,a_style,a_points,a_box_x,a_box_y,a_box_z);
4549   }
4550 
4551   void get_title(std::string& a_s){
4552     a_s.clear();
4553     bins1D* b1;
4554     bins2D* b2;
4555     func1D* f1;
4556     func2D* f2;
4557     points2D* p2;
4558     points3D* p3;
4559     if(first_bins(b1,b2)) {
4560       if(b1) {
4561         a_s = b1->title();
4562       } else if(b2) {
4563         a_s = b2->title();
4564       }
4565     } else if(first_points(p2,p3)) {
4566       if(p2) {
4567         a_s = p2->title();
4568       } else if(p3) {
4569         a_s = p3->title();
4570       }
4571     } else if(first_func(f1,f2)) {
4572       if(f1) {
4573         a_s = f1->title();
4574       } if(f2) {
4575         a_s = f2->title();
4576       }
4577     }
4578   }
4579 
4580   void update_bins2D_xyz(std::ostream& a_out,const bins2D& a_bins,unsigned int a_index,const style& a_style,
4581                          const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z){
4582     //a_out << "tools::sg::update_bins2D_xyz : begin :" << std::endl;
4583 
4584     if(!a_style.visible) return;
4585 
4586     //a_out << "tools::sg::update_bins2D_xyz : visible :" << std::endl;
4587 
4588     unsigned int xnbin = a_bins.x_bins();
4589     unsigned int ynbin = a_bins.y_bins();
4590     if(!xnbin || !ynbin) return;
4591 
4592     const std::string& modeling = a_style.modeling;
4593 
4594     if(modeling==modeling_boxes()) {
4595 
4596       bool hbe = a_bins.has_entries_per_bin();
4597 
4598       float bmin = 0;
4599       float bmax = 0;
4600 
4601       std::vector<rep_bin2D> bins;
4602      {bool first = true;
4603       for(int jbin=ynbin-1;jbin>=0;jbin--) {
4604         for(int ibin=xnbin-1;ibin>=0;ibin--) {
4605           if(hbe && (a_bins.bin_entries(ibin,jbin)<=0)) continue;
4606 
4607           float val = a_bins.bin_Sw(ibin,jbin);
4608 
4609           float xx = a_bins.bin_lower_edge_x(ibin);
4610           float xe = a_bins.bin_upper_edge_x(ibin);
4611           float yy = a_bins.bin_lower_edge_y(jbin);
4612           float ye = a_bins.bin_upper_edge_y(jbin);
4613 
4614           bins.push_back(rep_bin2D(xx,xe,yy,ye,val,ibin,jbin));
4615 
4616           if(first) {
4617             first = false;
4618             bmin = val;
4619             bmax = val;
4620           } else {
4621             bmin = mn<float>(bmin,val);
4622             bmax = mx<float>(bmax,val);
4623           }
4624         }
4625       }}
4626       size_t number = bins.size();
4627 
4628       //a_bins.bins_Sw_range(bmin,bmax,false);
4629 
4630       painting_policy painting = a_style.painting;
4631       if(painting==painting_by_value) {
4632         m_bins_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_style.color_mapping);
4633       } else if( (painting==painting_grey_scale) ||
4634                  (painting==painting_grey_scale_inverse) ||
4635                  (painting==painting_violet_to_red) ){
4636        {float dbins = bmax-bmin;
4637         if(dbins!=0.0F) {
4638           for(size_t index=0;index<number;index++) {
4639             bins[index].m_ratio = (bins[index].m_val-bmin)/dbins;
4640           }
4641         }}
4642         if(painting==painting_grey_scale) {
4643           m_bins_cmaps[a_index] = new grey_scale_colormap(bmin,bmax,50);
4644         } else if(painting==painting_grey_scale_inverse) {
4645           m_bins_cmaps[a_index] = new grey_scale_inverse_colormap(bmin,bmax,50);
4646         } else if(painting==painting_violet_to_red) {
4647           m_bins_cmaps[a_index] = new violet_to_red_colormap(bmin,bmax,50);
4648         }
4649       } else {
4650         m_bins_cmaps[a_index] = new const_colormap(a_style.color);
4651       }
4652 
4653       rep_bins2D_xyz_box(a_style,*m_bins_cmaps[a_index],bins,a_box_x,a_box_y,a_box_z,bmin,bmax);
4654 
4655     } else if(modeling==modeling_curve()){ //gopaw
4656 
4657       float bmin = 0;
4658       float bmax = 0;
4659 
4660       std::vector<rep_top_face2D> faces((xnbin-1)*(ynbin-1));
4661      {bool first = true;
4662       size_t facei = 0;
4663       unsigned int xnbin_1 = xnbin-1;
4664       unsigned int ynbin_1 = ynbin-1;
4665       for(unsigned int jbin=0;jbin<ynbin_1;jbin++) {
4666         for(unsigned int ibin=0;ibin<xnbin_1;ibin++) {
4667 
4668           float xx_0 = a_bins.bin_lower_edge_x(ibin);
4669           float xe_0 = a_bins.bin_upper_edge_x(ibin);
4670           float xx_1 = a_bins.bin_lower_edge_x(ibin+1);
4671           float xe_1 = a_bins.bin_upper_edge_x(ibin+1);
4672 
4673           float yy_0 = a_bins.bin_lower_edge_y(jbin);
4674           float ye_0 = a_bins.bin_upper_edge_y(jbin);
4675           float yy_1 = a_bins.bin_lower_edge_y(jbin+1);
4676           float ye_1 = a_bins.bin_upper_edge_y(jbin+1);
4677 
4678           float xx = (xx_0+xe_0)/2;
4679           float xe = (xx_1+xe_1)/2;
4680           float yy = (yy_0+ye_0)/2;
4681           float ye = (yy_1+ye_1)/2;
4682 
4683           float val1 = a_bins.bin_Sw(ibin,jbin);
4684           float val2 = a_bins.bin_Sw(ibin+1,jbin);
4685           float val3 = a_bins.bin_Sw(ibin+1,jbin+1);
4686           float val4 = a_bins.bin_Sw(ibin,jbin+1);
4687 
4688           faces[facei] = rep_top_face2D(xx,xe,yy,ye,val1,val2,val3,val4);
4689 
4690           if(first) {
4691             first = false;
4692             bmin = val1;
4693             bmax = val1;
4694           } else {
4695             bmin = mn<float>(bmin,val1);
4696             bmax = mx<float>(bmax,val1);
4697           }
4698 
4699           facei++;
4700         }
4701       }}
4702 
4703       //a_bins.bins_Sw_range(bmin,bmax,false);
4704 
4705       painting_policy painting = a_style.painting;
4706       if((painting==painting_by_value)||(painting==painting_by_level)) {
4707         m_bins_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_style.color_mapping);
4708       } else {
4709         m_bins_cmaps[a_index] = new const_colormap(a_style.color);
4710       }
4711 
4712       if(painting==painting_by_level) { //gopaw
4713         rep_top_face2D_xyz_by_level(a_style,painting,*(m_bins_cmaps[a_index]),
4714                                     faces,a_box_x,a_box_y,a_box_z,
4715                                     bmin,bmax/*,SbString(sid.c_str())*/);
4716         //if(a_style.area_style.value()==area_edged) {
4717         //  style gs;
4718         //  gs.light_model = light_model_base_color();
4719         //  gs.line_width = 1;
4720         //  rep_top_face2D_xyz_line(gs,faces,a_box_x,a_box_y,a_box_z);
4721         //}
4722 
4723       } else {
4724 
4725         //bool oneNode = false;
4726        //{int nlimit = aGraphicStyle.multiNodeLimit.getValue();
4727         //if(nlimit!=NoLimit) {
4728         //oneNode = ((int)faces.size()>nlimit?true:false);
4729         //}}
4730 
4731         //if(oneNode) {
4732         //repTopFaces2D_xyz_one(binsNode,aGraphicStyle,faces,a_box_x,a_box_y,a_box_z,SbString(sid.c_str()));
4733         //} else {
4734         bool zlog = a_box_z.m_log;
4735         if(zlog) m_func_cmaps[a_index]->set_PAW_coloring();
4736         rep_top_face2D_xyz(m_bins_sep,a_style,*(m_bins_cmaps[a_index]),faces,a_box_x,a_box_y,a_box_z);
4737 
4738         if(a_style.area_style.value()==area_edged) {
4739           style gs;
4740           gs.light_model = light_model_base_color();
4741           gs.line_width = 1;
4742           rep_top_face2D_xyz_line(gs,faces,a_box_x,a_box_y,a_box_z/*,SbString(sid.c_str())*/);
4743         }
4744 
4745         if(painting==painting_uniform) { //gopaw SURF3 (s_SURF_CONT).
4746 
4747           base_colormap* cmap = new by_value_colormap(a_out,m_cmaps,a_style.color_mapping);
4748           if(cmap->colorn()<=0) {
4749             //a_out << "tools::sg::update_bins2D_xyz : bypass rep_contour_xy_filled." << std::endl;
4750             delete cmap;
4751           } else {
4752             //updateBins2D_XY(a_bins,aIndex,*gs,a_box_x,a_box_y,boxZ,1.1F);
4753 
4754             float zmin = a_box_z.m_pos;
4755             float dz = a_box_z.m_width;
4756             //bool zlog = a_box_z.m_log;
4757 
4758             float xmn =  m_x_axis_data.min_value();
4759             float xmx =  m_x_axis_data.max_value();
4760             float ymn =  m_y_axis_data.min_value();
4761             float ymx =  m_y_axis_data.max_value();
4762 
4763             clist_contour list_contour;
4764             //int nFir = 32;
4765             int nFir = 128;
4766             list_contour.set_first_grid(nFir,nFir); //Default : 32,32
4767             //int nSec = 256;
4768             int nSec = 512;
4769             list_contour.set_secondary_grid(nSec,nSec); //Default : 256,256.
4770 
4771             double limits[4];
4772             // User limits :
4773             limits[0] = xmn;
4774             limits[1] = xmx;
4775             limits[2] = ymn;
4776             limits[3] = ymx;
4777 
4778             SbFunc sbFunc;
4779             sbFunc.m_func2D = 0;
4780             sbFunc.m_problem = false;
4781             sbFunc.m_bins2D = &a_bins;
4782             sbFunc.m_limits_in[0] = limits[0];
4783             sbFunc.m_limits_in[1] = limits[1];
4784             sbFunc.m_limits_in[2] = limits[2];
4785             sbFunc.m_limits_in[3] = limits[3];
4786 
4787             // Extend the grid to have some borders in order to close contours :
4788             int n = nSec - 2 * 10;
4789             double dx = (limits[1]-limits[0]) /n;
4790             double dy = (limits[3]-limits[2]) /n;
4791             limits[0] = limits[0] - 10 * dx;
4792             limits[1] = limits[1] + 10 * dx;
4793             limits[2] = limits[2] - 10 * dy;
4794             limits[3] = limits[3] + 10 * dy;
4795 
4796             sbFunc.m_limits[0] = limits[0];
4797             sbFunc.m_limits[1] = limits[1];
4798             sbFunc.m_limits[2] = limits[2];
4799             sbFunc.m_limits[3] = limits[3];
4800 
4801             list_contour.set_limits(limits);
4802 
4803             //int zn = numberOfLevels.getValue();
4804             size_t zn = cmap->colorn();
4805             if(zn<=0) zn = 1;
4806 
4807             std::vector<double> zs(zn+1);
4808             float zmax = zmin + dz;
4809             double zd = (zmax-zmin)/zn;
4810             for(size_t zi=0;zi<=zn;zi++) zs[zi] = zmin + zi * zd;
4811             list_contour.set_planes(zs);
4812 
4813             if(zlog) list_contour.set_field_fcn(log_bins2D_to_contour,(void*)&sbFunc);
4814             else     list_contour.set_field_fcn(bins2D_to_contour,(void*)&sbFunc);
4815 
4816             list_contour.ccontour::generate();
4817             if(!list_contour.compact_strips ()) {
4818               a_out << "tools::sg::plotter::update_bins2D_xyz : clist_contour::compact_strips () : failure." << std::endl;
4819               delete cmap;
4820             } else {
4821               delete m_bins_cmaps[a_index];
4822               m_bins_cmaps[a_index] = cmap; //to visualize the cmap.
4823 
4824               matrix* transf = new matrix;
4825               //contour back is at ZZ - 0.01F;
4826               transf->set_translate(0,0,1.02F);
4827               transf->mul_scale(1,1,0.01F); //applied first.
4828               m_bins_sep.add(transf);
4829 
4830               style gs;
4831               gs.light_model = light_model_base_color();
4832               //FIXME gs.transparency = 0.3F;
4833 
4834               float ZZ = 0.0F;
4835 
4836               rep_contour_xy_filled(a_out,gs,painting_by_level,*cmap,list_contour,
4837                                     a_box_x,a_box_y,a_box_z,ZZ/*,SbString(sid.c_str())*/);
4838             }
4839           }
4840 
4841         } //uniform
4842 
4843       }
4844 
4845     } //end if modeling
4846 
4847   }
4848 
4849   void update_func2D_xyz(std::ostream& a_out,
4850                          const func2D& a_func,
4851                          unsigned int a_index,
4852                          const style& a_style,
4853                          const rep_box& a_box_x,
4854                          const rep_box& a_box_y,
4855                          const rep_box& a_box_z){
4856     //a_out << "tools::sg::plotter::update_func2D_xyz : begin :" << std::endl;
4857     if(!a_style.visible) return;
4858 
4859     //a_out << "tools::sg::plotter::update_func2D_xyz : visible :" << std::endl;
4860 
4861     float xmn = m_x_axis_data.min_value();
4862     float xmx = m_x_axis_data.max_value();
4863 
4864     unsigned int nx = a_func.x_steps();
4865     nx = !nx?20:nx;
4866 
4867     float ymn = m_y_axis_data.min_value();
4868     float ymx = m_y_axis_data.max_value();
4869 
4870     unsigned int ny = a_func.y_steps();
4871     ny = !ny?20:ny;
4872 
4873     float dfx = (xmx - xmn)/nx;
4874     float dfy = (ymx - ymn)/ny;
4875 
4876     //printf("debug : nx %d ny %d\n",nx,ny);
4877 
4878     std::vector<rep_top_face2D> faces(nx*ny);
4879    {bool problem = false;
4880     unsigned int facei = 0;
4881     float* vprev = new float[2*nx];
4882     for(int jbin=ny-1;jbin>=0;jbin--) {
4883       float o1 = 0;
4884       float o4 = 0;
4885       for(int ibin=nx-1;ibin>=0;ibin--) {
4886 
4887         float xx = xmn + ibin * dfx;
4888         float yy = ymn + jbin * dfy;
4889         float xe = xx + dfx;
4890         float ye = yy + dfy;
4891 
4892         // Values at the corner :
4893         float val1;
4894         if(!a_func.value(xx,yy,val1)) problem = true;
4895         float val2;
4896         if(ibin==int(nx-1)) {
4897           if(!a_func.value(xe,yy,val2)) problem = true;
4898         } else {
4899           val2 = o1;
4900         }
4901         float val3,val4;
4902         if(jbin==int(ny-1)) {
4903           if(ibin==int(nx-1)) {
4904             if(!a_func.value(xe,ye,val3)) problem = true;
4905           } else {
4906             val3 = o4;
4907           }
4908           if(!a_func.value(xx,ye,val4)) problem = true;
4909         } else {
4910           val3 = vprev[2*ibin+1];
4911           val4 = vprev[2*ibin];
4912         }
4913         //printf("debug : %d %d : %g %g %g %g\n",
4914         //   ibin,jbin,
4915         //   val1,val2,val3,val4);
4916         vprev[2*ibin] = val1;
4917         vprev[2*ibin+1] = val2;
4918         o4 = val4;
4919         o1 = val1;
4920 
4921         faces[facei] = rep_top_face2D(xx,xe,yy,ye,val1,val2,val3,val4);
4922         facei++;
4923       }
4924     }
4925     delete [] vprev;
4926     if(problem) {
4927       a_out << "tools::sg::plotter::update_func2D_xyz :"
4928             << " problem when getting some function value."
4929             << std::endl;
4930     }}
4931 
4932     painting_policy painting = a_style.painting;
4933 
4934     if(painting==painting_by_value) {
4935       m_func_cmaps[a_index] = new by_value_colormap(a_out,m_cmaps,a_style.color_mapping);
4936 
4937     } else if( (painting==painting_grey_scale) ||
4938                (painting==painting_grey_scale_inverse) ||
4939                (painting==painting_violet_to_red) ){
4940       float vmin = faces[0].m_v1;
4941       float vmax = faces[0].m_v1;
4942       size_t number = faces.size();
4943       for(size_t index=0;index<number;index++) {
4944         float vmean  = faces[index].m_v1;
4945         vmean += faces[index].m_v2;
4946         vmean += faces[index].m_v3;
4947         vmean += faces[index].m_v4;
4948         vmean /= 4.0f;
4949 
4950         vmin = mn<float>(vmin,vmean);
4951         vmax = mx<float>(vmax,vmean);
4952 
4953         faces[index].m_ratio = vmean;
4954       }
4955 
4956      {float dbins = vmax-vmin;
4957       if(dbins!=0.0F) {
4958         for(size_t index=0;index<number;index++) {
4959           faces[index].m_ratio = (faces[index].m_ratio-vmin)/dbins;
4960         }
4961       }}
4962 
4963       if(painting==painting_grey_scale) {
4964         m_func_cmaps[a_index] = new grey_scale_colormap(vmin,vmax,50);
4965       } else if(painting==painting_grey_scale_inverse) {
4966         m_func_cmaps[a_index] = new grey_scale_inverse_colormap(vmin,vmax,50);
4967       } else if(painting==painting_violet_to_red) {
4968         m_func_cmaps[a_index] = new violet_to_red_colormap(vmin,vmax,50);
4969       }
4970 
4971     } else {
4972       m_func_cmaps[a_index] = new const_colormap(a_style.color);
4973     }
4974 
4975   // bool oneNode = false;
4976   //{int nlimit = a_data_style.multiNodeLimit.getValue();
4977   // if(nlimit!=NoLimit) {
4978   //   oneNode = ((int)faces.size()>nlimit?true:false);
4979   //}}
4980 
4981   //char sid[128];
4982   //::sprintf(sid,"SbFunction2D/0x%lx",(unsigned long)&a_func);
4983 
4984   //if(oneNode) {
4985   //  repTopFaces2D_xyz_one(functionNode,a_data_style,
4986   //                        faces,a_box_x,a_box_y,a_box_z,std::string(sid));
4987   //} else
4988     {
4989       bool zlog = a_box_z.m_log;
4990       if(zlog) m_func_cmaps[a_index]->set_PAW_coloring();
4991       rep_top_face2D_xyz(m_func_sep,a_style,*(m_func_cmaps[a_index]),faces,a_box_x,a_box_y,a_box_z);
4992     }
4993 
4994     float xmin = a_box_x.m_pos;
4995     float dx = a_box_x.m_width;
4996     bool xlog = a_box_x.m_log;
4997 
4998     float ymin = a_box_y.m_pos;
4999     float dy = a_box_y.m_width;
5000     bool ylog = a_box_y.m_log;
5001 
5002     float zmin = a_box_z.m_pos;
5003     float dz = a_box_z.m_width;
5004     bool zlog = a_box_z.m_log;
5005 
5006    if(func2D_borders_visible.value()) {
5007    // border X (Y=0)
5008 
5009    {separator* sep = new separator;
5010    {normal* nm = new normal;
5011     nm->vec = vec3f(0,-1,0);
5012     sep->add(nm);}
5013    {rgba* mat = new rgba();
5014     mat->color = colorf(0.6f,0.2f,0.2f); //brown
5015     sep->add(mat);}
5016 
5017     vertices* vtxs = new vertices;
5018     vtxs->mode = gl::triangle_fan();
5019     sep->add(vtxs);
5020 
5021     bool empty = true;
5022     bool problem = false;
5023 
5024    {float xx = xmn;
5025     float yy = ymn;
5026     xx = verify_log(xx,xmin,dx,xlog);
5027     yy = verify_log(yy,ymin,dy,ylog);
5028     vtxs->add(xx,yy,0);}
5029 
5030    {float xx = xmx;
5031     float yy = ymn;
5032     xx = verify_log(xx,xmin,dx,xlog);
5033     yy = verify_log(yy,ymin,dy,ylog);
5034     vtxs->add(xx,yy,0);}
5035 
5036    {float val;
5037    {if(!a_func.value(xmx,ymn,val)) problem = true;
5038     val = verify_log(val,zmin,dz,zlog);
5039     if(val<0) val = 0;
5040     if(val>1) val = 1;}
5041    {float xx = xmx;
5042     float yy = ymn;
5043     xx = verify_log(xx,xmin,dx,xlog);
5044     yy = verify_log(yy,ymin,dy,ylog);
5045     vtxs->add(xx,yy,val);}}
5046 
5047     for(int ibin=nx-1;ibin>=0;ibin--) {
5048 
5049       float xx = xmn + ibin * dfx;
5050       //float xe = xx + dfx;
5051       float yy = ymn;
5052 
5053       float val;
5054      {if(!a_func.value(xx,yy,val)) problem = true;
5055       val = verify_log(val,zmin,dz,zlog);
5056       if(val<0) val = 0;
5057       if(val>1) val = 1;}
5058 
5059       xx = verify_log(xx,xmin,dx,xlog);
5060       yy = verify_log(yy,ymin,dy,ylog);
5061 
5062       if((xx>=0)&&(xx<=1) && (yy>=0)&&(yy<=1) ) {
5063 
5064         vtxs->add(xx,yy,val);
5065 
5066         empty = false;
5067       }
5068     }
5069     if(empty) {
5070       delete sep;
5071     } else {
5072       m_func_sep.add(sep);
5073     }
5074     if(problem) {
5075       a_out << "tools::sg::plotter::update_func2D_xyz :"
5076             << " problem when getting some function value."
5077             << std::endl;
5078     }}
5079 
5080     // border Y (X=0)
5081    {separator* sep = new separator;
5082    {normal* nm = new normal;
5083     nm->vec = vec3f(-1,0,0);
5084     sep->add(nm);}
5085    {rgba* mat = new rgba();
5086     mat->color = colorf(0.6f,0.2f,0.2f); //brown
5087     sep->add(mat);}
5088 
5089     vertices* vtxs = new vertices;
5090     vtxs->mode = gl::triangle_fan();
5091     sep->add(vtxs);
5092 
5093    {float xx = xmn;
5094     float yy = ymx;
5095     xx = verify_log(xx,xmin,dx,xlog);
5096     yy = verify_log(yy,ymin,dy,ylog);
5097     vtxs->add(xx,yy,0);}
5098 
5099    {float xx = xmn;
5100     float yy = ymn;
5101     xx = verify_log(xx,xmin,dx,xlog);
5102     yy = verify_log(yy,ymin,dy,ylog);
5103     vtxs->add(xx,yy,0);}
5104 
5105     bool empty = true;
5106     bool problem = false;
5107 
5108     for(unsigned int jbin=0;jbin<ny;jbin++) {
5109 
5110       float xx = xmn;
5111       float yy = ymn + jbin * dfy;
5112 
5113       float val;
5114      {if(!a_func.value(xx,yy,val)) problem = true;
5115       val = verify_log(val,zmin,dz,zlog);
5116       if(val<0) val = 0;
5117       if(val>1) val = 1;}
5118 
5119       xx = verify_log(xx,xmin,dx,xlog);
5120       yy = verify_log(yy,ymin,dy,ylog);
5121 
5122       if((xx>=0)&&(xx<=1)   &&
5123          (yy>=0)&&(yy<=1)   ){
5124 
5125         vtxs->add(xx,yy,val);
5126 
5127         empty = false;
5128 
5129       }
5130     }
5131 
5132    {float val;
5133    {if(!a_func.value(xmn,ymx,val)) problem = true;
5134     val = verify_log(val,zmin,dz,zlog);
5135     if(val<0) val = 0;
5136     if(val>1) val = 1;}
5137    {float xx = xmn;
5138     float yy = ymx;
5139     xx = verify_log(xx,xmin,dx,xlog);
5140     yy = verify_log(yy,ymin,dy,ylog);
5141     vtxs->add(xx,yy,val);}}
5142     if(empty) {
5143       delete sep;
5144     } else {
5145       m_func_sep.add(sep);
5146     }
5147     if(problem) {
5148       a_out << "tools::sg::plotter::update_func2D_xyz :"
5149             << " problem when getting some function value."
5150             << std::endl;
5151     }}
5152 
5153 
5154     } //func2D_borders_visible
5155 
5156   }
5157 
5158   void update_title(){
5159     if(!m_title_style.visible) return;
5160 
5161     if(m_shape==xyz) return;
5162 
5163     if(title.value().empty()) return;
5164 
5165     // Use the XY layout transform to position the title.
5166     // (Else we would have to compensate the 3D rotation
5167     //  in order to bring the title at the right position
5168     //  without rotation).
5169     //titleNode->addChild(layout);
5170 
5171     rgba* mat = new rgba();
5172     mat->color = m_title_style.color;
5173     m_title_sep.add(mat);
5174 
5175     float text_size = title_height * m_title_style.scale;
5176 
5177     std::string font = m_title_style.font.value();
5178 
5179     if(font==font_hershey()) {
5180       draw_style* ds = new draw_style;
5181       ds->style = draw_lines;
5182       ds->line_pattern = m_title_style.line_pattern;
5183       ds->line_width = m_title_style.line_width;
5184       m_title_sep.add(ds);
5185     } else {
5186       m_title_sep.add(new normal);
5187     }
5188 
5189     float XSIZ = width;
5190     float XMGL = left_margin;
5191     float XMGR = right_margin;
5192     float wData = XSIZ-XMGL-XMGR;
5193 
5194     float YSIZ = height;
5195     float YMGL = bottom_margin;
5196     float YMGU = top_margin;
5197     float hData = YSIZ-YMGL-YMGU;
5198 
5199     float xx = wData/2;
5200     float yy = hData + title_to_axis;
5201 
5202     float zz = _zinfos();
5203 
5204     vjust vjust = bottom;
5205     if(!title_up) {
5206       yy = -title_to_axis;
5207       vjust = top;
5208     }
5209 
5210     //::printf("debug : %lu : %g %g : text_size : %g : %s\n",
5211     //  this,xx,yy,text_size,title.value().c_str());
5212 
5213     vec3f TX(1,0,0);
5214     vec3f TY(0,1,0);
5215     add_string(m_title_sep,
5216                        font,
5217                        m_title_style.font_modeling.value(),
5218                        m_title_style.encoding.value(),
5219                        m_title_style.smoothing,
5220                        title.value(),
5221                        xx,yy,zz, //vec
5222                        TX,TY,
5223                        text_size,
5224                        title_hjust,vjust,
5225                        m_ttf);
5226   }
5227 
5228   void update_title_box(){
5229     if(!m_title_box_style.visible) return;
5230     if(title.value().empty()) return;
5231 
5232     // same plane than infos, then in front of data and grid.
5233     float zz = _zinfos();
5234     if(m_shape==xyz) zz = depth*0.5f;
5235 
5236     float wbox = width*title_box_width;
5237     float hbox = height*title_box_height;
5238 
5239     float xmargin = width*title_box_x_margin;  //from left border
5240     float ymargin = height*title_box_y_margin; //from top border
5241 
5242     matrix* _tsf = new matrix;
5243    {float xx = -width*0.5f+wbox*0.5f+xmargin; //at left.
5244     float yy = height*0.5f-hbox*0.5F-ymargin; //at top.
5245     _tsf->set_translate(xx,yy,zz);
5246     _tsf->mul_scale(1,1,_zscale_text());}
5247     m_title_box_sep.add(_tsf);
5248 
5249     sg::text* title_box = new sg::text(m_ttf);
5250     title_box->width = wbox;
5251     title_box->height = hbox;
5252     title_box->back_area::color = m_title_box_style.back_color;
5253     title_box->color = m_title_box_style.color;
5254     title_box->font = m_title_box_style.font;
5255     title_box->font_modeling = m_title_box_style.font_modeling;
5256     title_box->encoding = m_title_box_style.encoding;
5257     title_box->line_width = m_title_box_style.line_width;
5258   //title_box->front_face = m_title_box_style.front_face;
5259     title_box->confine = true;
5260     title_box->back_area::shadow = m_title_box_style.back_shadow;
5261 
5262     title_box->strings.add(title.value());
5263 
5264     m_title_box_sep.add(title_box);
5265   }
5266 
5267   void get_infos(std::string& a_s){
5268     // return "[<key>\n<value>]\n".
5269     a_s.clear();
5270     const std::string&  opts = infos_what.value();
5271    {bins1D* b1;
5272     bins2D* b2;
5273     func1D* f1;
5274     func2D* f2;
5275     points2D* p2;
5276     points3D* p3;
5277     if(first_bins(b1,b2)) {
5278       if(b1) {
5279         b1->infos(opts,a_s);
5280       } else if(b2) {
5281         b2->infos(opts,a_s);
5282       }
5283     } else if(first_points(p2,p3)) {
5284       if(p2) {
5285         p2->infos(opts,a_s);
5286       } else if(p3) {
5287         p3->infos(opts,a_s);
5288       }
5289     } else if(first_func(f1,f2)) {
5290       if(f1) {
5291         f1->infos(opts,a_s);
5292       } if(f2) {
5293         f2->infos(opts,a_s);
5294       }
5295     }}
5296     //look for fit infos :
5297    {tools_vforcit(plottable*,m_plottables,it) {
5298       plottable* object = *it;
5299       if(!object) continue;
5300       if(object->cast(s_tools_sg_fit2plot())) {
5301         if(a_s.size()) a_s += "\n";
5302         std::string _s;
5303         object->infos(opts,_s);
5304         a_s += _s;
5305       }
5306     }}
5307   }
5308 
5309   matrix* get_infos_matrix() {
5310     if(m_infos_sep.empty()) return 0;
5311     return (matrix*)m_infos_sep[0]; //WARNING.
5312   }
5313   sg::infos_box* get_infos_node() {
5314     if(m_infos_sep.empty()) return 0;
5315     return (sg::infos_box*)m_infos_sep[1]; //WARNING.
5316   }
5317 
5318   void update_infos(std::ostream&){
5319     if(!m_infos_style.visible) return;
5320 
5321     std::string sinfos;
5322     get_infos(sinfos);
5323     std::vector<std::string> ws;
5324     words(sinfos,"\n",false,ws);
5325     size_t linen = ws.size()/2;
5326 
5327     float zz = _zinfos(); //xy
5328     if(m_shape==xyz) zz = depth*0.5f;
5329 
5330     float _height = height;
5331     if(m_shape==xyz) _height = depth;
5332 
5333     float wbox = width*infos_width;
5334 
5335     matrix* infos_title_tsf = 0;
5336     sg::text* infos_title_text = 0;
5337 
5338     std::string infos_title;
5339     if(m_infos_style.modeling==infos_modeling_ROOT()) {
5340       std::vector<std::string> _ws; //to rm "Name".
5341       for(size_t index=0;index<linen;index++) {
5342         const std::string& name = ws[2*index];
5343         const std::string& value = ws[2*index+1];
5344         if(name=="Name") {
5345           infos_title = value;
5346         } else {
5347           _ws.push_back(name);
5348           _ws.push_back(value);
5349         }
5350       }
5351       ws = _ws;
5352       linen = ws.size()/2;
5353     }
5354 
5355     if(infos_title.size()) {
5356       float hbox = _height*0.05f;
5357 
5358       matrix* _tsf = new matrix;
5359      {float xx = width*0.5f  - wbox*0.5f -  width*infos_x_margin;
5360       float yy = _height*0.5f - hbox*0.5F - _height*infos_y_margin;
5361       _tsf->mul_translate(xx,yy,zz);
5362       _tsf->mul_scale(1,1,_zscale_text());}
5363       //in case of having infos, the tsf is refined below.
5364       m_infos_title_sep.add(_tsf);
5365 
5366       // same params as title_box.
5367       sg::text* txt = new sg::text(m_ttf);
5368       txt->width = wbox;
5369       txt->height = hbox;
5370       txt->back_area::color = m_infos_style.back_color;
5371       txt->color = m_infos_style.color;
5372       txt->font = m_infos_style.font;
5373       txt->font_modeling = m_infos_style.font_modeling;
5374       txt->encoding = m_infos_style.encoding;
5375       txt->line_width = m_infos_style.line_width;
5376     //txt->front_face = m_infos_style.front_face;
5377       txt->confine = true;
5378       txt->back_area::shadow = m_infos_style.back_shadow;
5379 
5380       txt->hjust = center;
5381 
5382       txt->strings.add(infos_title);
5383       m_infos_title_sep.add(txt);
5384 
5385       // to refine height below.
5386       infos_title_tsf = _tsf;
5387       infos_title_text = txt;
5388     }
5389 
5390     if(sinfos.empty()) return;
5391     if(!linen) return;
5392 
5393     matrix* _tsf = new matrix;
5394     m_infos_sep.add(_tsf);
5395 
5396     sg::infos_box* infos = new sg::infos_box(m_ttf);
5397     infos->width = wbox;
5398     //infos->height is an output field, see below.
5399     infos->back_area::color = m_infos_style.back_color;
5400     infos->color = m_infos_style.color;
5401     infos->font = m_infos_style.font;
5402     infos->encoding = m_infos_style.encoding;
5403     infos->font_modeling = m_infos_style.font_modeling;
5404     infos->line_width = m_infos_style.line_width;
5405   //infos->front_face = m_infos_style.front_face;
5406     infos->back_area::shadow = m_infos_style.back_shadow;
5407     infos->border_line_width = m_infos_style.line_width;
5408 
5409    {for(size_t index=0;index<linen;index++) {
5410       const std::string& name = ws[2*index];
5411       const std::string& value = ws[2*index+1];
5412       infos->lstrings.add(name);
5413       infos->rstrings.add(value);
5414       //a_out << "debug : name " << sout(name)
5415       //      << " value " << sout(value) << std::endl;
5416     }}
5417 
5418     // enforce an infos::update_sg to get infos::height
5419     // to place the box.
5420     infos->update_sg();
5421 
5422     // if any, set infos_title height :
5423     float title_hbox = 0;
5424     if(infos_title_tsf && infos_title_text) {
5425       title_hbox = infos->height/linen;
5426       float xx = width*0.5f  - wbox*0.5f       - width*infos_x_margin;
5427       float yy = _height*0.5f - title_hbox*0.5F - _height*infos_y_margin;
5428       infos_title_tsf->set_identity();
5429       infos_title_tsf->mul_translate(xx,yy,zz);
5430       infos_title_tsf->mul_scale(1,1,_zscale_text());
5431 
5432       infos_title_text->height = title_hbox;
5433     }
5434 
5435     float hbox = infos->height;
5436    {float xx = width*0.5f  -wbox*0.5f -width*infos_x_margin;
5437     float yy = _height*0.5f -hbox*0.5F - _height*infos_y_margin;
5438     yy -= title_hbox;
5439     _tsf->set_translate(xx,yy,zz);
5440     _tsf->mul_scale(1,1,_zscale_text());}
5441 
5442     m_infos_sep.add(infos);
5443   }
5444 
5445 /*
5446   void update_legends(std::ostream& a_out){
5447     if(!legends_visible) return;
5448 
5449     if(m_legend_strings.empty()) return;
5450     if(m_legend_colors.size()!=m_legend_strings.size()) return;
5451 
5452     //m_legend_sep contains :
5453     //   one global mtx
5454     //   one sep per legend.
5455 
5456    {matrix* _tsf = new matrix;
5457     m_legend_sep.add(_tsf);
5458 
5459     float zz = _zinfos();
5460 
5461     //set legends layout :
5462     if(legends_attached_to_infos) {
5463       _tsf->set_translate(0,0,zz);
5464     } else {
5465       if(legends_origin_unit==unit_axis) {
5466 
5467         // legends_origin is in axes coordinates.
5468         float x = legends_origin.value()[0];
5469         float y = legends_origin.value()[1];
5470 
5471         vec3f pos;
5472         if(!axis_2_vp(vec3f(x,y,0),pos)) {
5473           //SoDebugError::postInfo("SoPlotterRegion::updateChildren",
5474             //                       "failed for %g %g.",x,y);
5475         } else {
5476           //pos is in NDC of [0,width][0,height].
5477 
5478           float xx = width  * (-0.5f+pos[0]);
5479           float yy = height * (-0.5f+pos[1]);
5480 
5481           _tsf->set_translate(xx,yy,zz);
5482 
5483         }
5484 
5485       } else { //unit_percent
5486         // legends_origin is
5487         // the UR corner of legend region relative
5488         // to UR of plotter region.
5489         float xur = legends_origin.value()[0];
5490         float yur = legends_origin.value()[1];
5491 
5492         vec2f ur(1-xur,1-yur);
5493 
5494         float w = legends_size.value()[0];
5495         float h = legends_size.value()[1];
5496 
5497         float x = ur[0]-w;
5498         float y = ur[1]-h;
5499 
5500         float xx = width  * (x-0.5f);
5501         float yy = height * (y-0.5f);
5502 
5503         _tsf->set_translate(xx,yy,zz);
5504 
5505       }
5506     }}
5507 
5508     size_t number = m_legend_strings.size();
5509     for(size_t index=0;index<number;index++) {
5510 
5511       separator* sep = new separator;
5512       m_legend_sep.add(sep);
5513 
5514       matrix* _tsf = new matrix;
5515       sep->add(_tsf);
5516 
5517       //sg::text* text = new sg::text;
5518       legend* text = new legend(m_ttf);
5519       //text->confine = true;
5520       text->strings.add(m_legend_strings[index]);
5521       sep->add(text);
5522       text->color = m_legend_colors[index];
5523 
5524       if(legends_attached_to_infos) {
5525         // global tsf should be the identity.
5526 
5527         // legend box geometry and placement is relative
5528         // to the infos box placement and geometry :
5529         if(m_infos_style.visible) {
5530           sg::infos_box* inode = get_infos_node();
5531           if(!inode) {delete sep;return;}
5532           matrix* imtx = get_infos_matrix();
5533           if(!imtx) {delete sep;return;}
5534 
5535           float wbox = inode->width;
5536           float hbox = inode->height/number;
5537 
5538           text->width = wbox;
5539           text->height = hbox;
5540 
5541           _tsf->mtx = imtx->mtx;
5542 
5543           float xx = width*0.5f-wbox*0.5f;
5544 
5545           float yy = height*0.5f-inode->height-hbox*0.5f-hbox*index;
5546 
5547           _tsf->set_translate(xx,yy,0);
5548 
5549         } else {
5550           float wbox = width  * legends_size.value()[0];
5551           float hbox = (height * legends_size.value()[1])/number;
5552 
5553           text->width = wbox;
5554           text->height = hbox;
5555 
5556           float xx = width*0.5f-wbox*0.5f - width*infos_x_margin;
5557           float yy = height*0.5f-hbox*0.5F - height*infos_y_margin;
5558 
5559           yy -= hbox*index;
5560 
5561           _tsf->set_translate(xx,yy,0);
5562         }
5563 
5564       } else {
5565 
5566         //legends_size is in NDC of [0,width][0,height].
5567         float w = width  * legends_size.value()[0];
5568         float h = height * legends_size.value()[1];
5569 
5570         text->width = w;
5571         text->height = h/number;
5572 
5573         float xx = w * 0.5f;
5574         float yy = text->height * 0.5f;
5575         yy += text->height*(number-index-1);
5576 
5577         _tsf->set_translate(xx,yy,0);
5578 
5579       }
5580       _tsf->mul_scale(1,1,_zscale_text());
5581 
5582     }
5583   }
5584 */
5585 
5586   void update_legends(std::ostream& a_out) {
5587     //::printf("debug : update_legends : begin\n");
5588     if(m_legend_strings.empty()) return;
5589     if(m_legend_strings.size()!=legends_origin.size()) return;
5590     if(legends_size.size()!=legends_origin.size()) return;
5591     if(legends_origin_unit.size()!=legends_origin.size()) return;
5592 
5593     float zz = _zinfos();
5594 
5595    {matrix* _tsf = new matrix;
5596     _tsf->mul_scale(1,1,_zscale_text());
5597     m_legend_sep.add(_tsf);}
5598 
5599     size_t number = m_legend_strings.size();
5600     //::printf("debug : update_legends : 001 %lu\n",number);
5601     for(size_t index=0;index<number;index++) {
5602       const style& _style = legend_style(index);
5603       if(!_style.visible) continue;
5604       //::printf("debug : update_legends : 002 %lu |%s|\n",index,m_legend_strings[index].c_str());
5605 
5606       separator* sep = new separator;
5607       m_legend_sep.add(sep);
5608 
5609       matrix* _tsf = new matrix;
5610       sep->add(_tsf);
5611 
5612       //sg::text* text = new sg::text;
5613       legend* text = new legend(m_ttf);
5614       text->font = _style.font;
5615       text->font_modeling = _style.font_modeling;
5616       text->encoding = _style.encoding;
5617       text->strings.add(m_legend_strings[index]);
5618       text->color = _style.color;
5619       text->marker_style = _style.marker_style;
5620       text->marker_size = _style.marker_size;
5621       text->back_visible = false;
5622       sep->add(text);
5623 
5624       //legends_size is in NDC of [0,width][0,height].
5625       float w = width  * legends_size[index][0];
5626       float h = height * legends_size[index][1];
5627       text->width = w;
5628       text->height = h;
5629 
5630       float xxx = w * 0.5f;
5631       float yyy = h * 0.5f;
5632 
5633       if(legends_origin_unit[index]==unit_axis) {
5634 
5635         // legends_origin is in axes coordinates.
5636         float x = legends_origin[index][0];
5637         float y = legends_origin[index][1];
5638 
5639         vec3f pos;
5640         if(!axis_2_vp(vec3f(x,y,0),pos)) {
5641           a_out << "tools::sg::plotter::update_legends : axis_2_vp() failed for x=" << x << ", y=" << y << "." << std::endl;
5642         } else {
5643           //pos is in NDC of [0,width][0,height].
5644           float xx = width  * (-0.5f+pos[0]);
5645           float yy = height * (-0.5f+pos[1]);
5646           _tsf->set_translate(xx,yy,zz);
5647         }
5648 
5649       } else { //unit_percent
5650         // legends_origin is
5651         // the UR corner of legend region relative
5652         // to UR of plotter region.
5653         float xur = legends_origin[index][0];
5654         float yur = legends_origin[index][1];
5655 
5656         vec2f ur(1-xur,1-yur);
5657 
5658         float x =  width*ur[0] - w;
5659         float y = height*ur[1] - h;
5660 
5661         float xx =  -width*0.5f + x;
5662         float yy = -height*0.5f + y;
5663 
5664         _tsf->set_translate(xx,yy,zz);
5665       }
5666 
5667       _tsf->mul_translate(xxx,yyy,0); //applied first.
5668 
5669     }
5670   }
5671 
5672   void update_background(){
5673     m_background_sep.clear();
5674     if(!m_background_style.visible) return;
5675 
5676     matrix* _tsf = new matrix;
5677     m_background_sep.add(_tsf);
5678 
5679     float w2 = width*0.5F;
5680     float h2 = height*0.5F;
5681 
5682     float zz = 0; //in xy, then before first data plane at _zoffset()
5683     if(m_shape==xyz) zz = -depth*0.5f;
5684 
5685    {rgba* mat = new rgba();
5686     if(m_background_style.line_width) { //there is a border.
5687       mat->color = m_background_style.color; //then border color !
5688     } else {
5689       mat->color = m_background_style.back_color;
5690     }
5691     m_background_sep.add(mat);
5692 
5693     m_background_sep.add(new normal);
5694 
5695     vertices* vtxs = new vertices;
5696     vtxs->mode = gl::triangle_fan();
5697     m_background_sep.add(vtxs);
5698 
5699     vtxs->add(-w2,-h2,zz);
5700     vtxs->add( w2,-h2,zz);
5701     vtxs->add( w2, h2,zz);
5702     vtxs->add(-w2, h2,zz);}
5703 
5704     if(m_background_style.line_width) { //border
5705       //WARNING : line_width should be in percent of width.
5706 
5707       //NOTE : border is done by drawing a front smaller polygon.
5708 
5709       rgba* mat = new rgba();
5710       mat->color = m_background_style.back_color; //yes,yes !
5711       m_background_sep.add(mat);
5712 
5713       vertices* vtxs = new vertices;
5714       vtxs->mode = gl::triangle_fan();
5715       m_background_sep.add(vtxs);
5716 
5717       //float d = width*0.005;
5718       float d = width*m_background_style.line_width;
5719 
5720       zz += _zoffset()*0.5f;
5721 
5722       vtxs->add(-w2+d,-h2+d,zz);
5723       vtxs->add( w2-d,-h2+d,zz);
5724       vtxs->add( w2-d, h2-d,zz);
5725       vtxs->add(-w2+d, h2-d,zz);
5726     }
5727 
5728   }
5729 
5730   void update_inner_frame_XY(){
5731     if(!m_inner_frame_style.visible) return;
5732 
5733     rgba* mat = new rgba();
5734     mat->color = m_inner_frame_style.color;
5735     m_inner_frame_sep.add(mat);
5736 
5737     draw_style* ds = new draw_style;
5738     ds->style = draw_lines;
5739     ds->line_pattern = m_inner_frame_style.line_pattern;
5740     ds->line_width = m_inner_frame_style.line_width;
5741     m_inner_frame_sep.add(ds);
5742 
5743     vertices* vtxs = new vertices;
5744     vtxs->mode = gl::line_strip();
5745     m_inner_frame_sep.add(vtxs);
5746 
5747     float zz = _zgrid();
5748 
5749     vtxs->add(0,0,zz);
5750     vtxs->add(1,0,zz);
5751     vtxs->add(1,1,zz);
5752     vtxs->add(0,1,zz);
5753     vtxs->add(0,0,zz);
5754   }
5755 
5756   void update_inner_frame_XYZ(){
5757     if(!m_inner_frame_style.visible) return;
5758 
5759     rgba* mat = new rgba();
5760     mat->color = m_inner_frame_style.color;
5761     m_inner_frame_sep.add(mat);
5762 
5763     draw_style* ds = new draw_style;
5764     ds->style = draw_lines;
5765     ds->line_pattern = m_inner_frame_style.line_pattern;
5766     ds->line_width = m_inner_frame_style.line_width;
5767     m_inner_frame_sep.add(ds);
5768 
5769     vertices* ls = new vertices;
5770     ls->mode = gl::lines();
5771     m_inner_frame_sep.add(ls);
5772 
5773     // z bottom :
5774     ls->add(0,0,0);ls->add(1,0,0);
5775     ls->add(1,0,0);ls->add(1,1,0);
5776     ls->add(1,1,0);ls->add(0,1,0);
5777     ls->add(0,1,0);ls->add(0,0,0);
5778 
5779     // z top :
5780     ls->add(0,0,1);ls->add(1,0,1);
5781     ls->add(1,0,1);ls->add(1,1,1);
5782     ls->add(1,1,1);ls->add(0,1,1);
5783     ls->add(0,1,1);ls->add(0,0,1);
5784 
5785     // sides along z :
5786     ls->add(0,0,0);ls->add(0,0,1);
5787     ls->add(1,0,0);ls->add(1,0,1);
5788     ls->add(1,1,0);ls->add(1,1,1);
5789     ls->add(0,1,0);ls->add(0,1,1);
5790   }
5791 
5792   void update_grid_XY(){
5793     if(!m_grid_style.visible) return;
5794 
5795     unsigned int number = m_x_axis.tick_number + m_y_axis.tick_number;
5796     if(number<=0) return;
5797 
5798     bool draw_vertical = true;
5799     bool draw_horizontal = true;
5800     if(m_grid_style.options.value()=="vertical") draw_horizontal = false;
5801     if(m_grid_style.options.value()=="horizontal") draw_vertical = false;
5802 
5803     rgba* mat = new rgba();
5804     mat->color = m_grid_style.color;
5805     m_grid_sep.add(mat);
5806 
5807     draw_style* ds = new draw_style;
5808     ds->style = draw_lines;
5809     ds->line_pattern = line_solid;
5810     ds->line_width = m_grid_style.line_width;
5811     m_grid_sep.add(ds);
5812 
5813     float zz = _zgrid();
5814 
5815     vertices* vtxs = new vertices;
5816     vtxs->mode = gl::lines();
5817     m_grid_sep.add(vtxs);
5818 
5819     std::vector<float>& pts = vtxs->xyzs.values();
5820 
5821     bool is_solid = m_grid_style.line_pattern.value()==line_solid;
5822 
5823     if(draw_vertical) {
5824       float _width = m_y_axis.width;
5825       float xx;
5826      {size_t _number = m_x_axis.coords.size();
5827       if(is_solid) {
5828         pts.reserve(_number*6);
5829         for(size_t count=0;count<_number;count++) {
5830           xx = m_x_axis.coords[count];
5831           vtxs->add(xx, 0    ,zz);
5832           vtxs->add(xx, _width,zz);
5833         }
5834       } else {
5835         pts.reserve(_number*100*6);
5836         for(size_t count=0;count<_number;count++) {
5837           xx = m_x_axis.coords[count];
5838           vtxs->add_dashed_line(xx,0,zz,xx,_width,zz,100);
5839         }
5840       }}
5841       if(m_x_axis.is_log) {
5842         size_t _number = m_x_axis.sub_coords.size();
5843         if(is_solid) {
5844           pts.reserve(_number*6);
5845           for(size_t count=0;count<_number;count++) {
5846             xx = m_x_axis.sub_coords[count];
5847             vtxs->add(xx, 0    ,zz);
5848             vtxs->add(xx,_width,zz);
5849           }
5850         } else {
5851           pts.reserve(_number*100*6);
5852           for(size_t count=0;count<_number;count++) {
5853             xx = m_x_axis.sub_coords[count];
5854             vtxs->add_dashed_line(xx,0,zz,xx,_width,zz,100);
5855           }
5856         }
5857       }
5858     }
5859 
5860     if(draw_horizontal) {
5861       float _width = m_x_axis.width;
5862       float yy;
5863      {size_t _number = m_y_axis.coords.size();
5864       if(is_solid) {
5865         pts.reserve(_number*6);
5866         for(size_t count=0;count<_number;count++) {
5867           yy = m_y_axis.coords[count];
5868           vtxs->add(0,yy    ,zz);
5869           vtxs->add(_width,yy,zz);
5870         }
5871       } else {
5872         pts.reserve(_number*100*6);
5873         for(size_t count=0;count<_number;count++) {
5874           yy = m_y_axis.coords[count];
5875           vtxs->add_dashed_line(0,yy,zz,_width,yy,zz,100);
5876         }
5877       }}
5878       if(m_y_axis.is_log) {
5879         size_t _number = m_y_axis.sub_coords.size();
5880         if(is_solid) {
5881           pts.reserve(_number*6);
5882           for(size_t count=0;count<_number;count++) {
5883             yy = m_y_axis.sub_coords[count];
5884             vtxs->add(0,yy,    zz);
5885             vtxs->add(_width,yy,zz);
5886           }
5887         } else {
5888           pts.reserve(_number*100*6);
5889           for(size_t count=0;count<_number;count++) {
5890             yy = m_y_axis.sub_coords[count];
5891             vtxs->add_dashed_line(0,yy,zz,_width,yy,zz,100);
5892           }
5893         }
5894       }
5895     }
5896 
5897   }
5898 
5899   void update_grid_XYZ(){
5900     if(!m_grid_style.visible) return;
5901 
5902     rgba* mat = new rgba();
5903     mat->color = m_grid_style.color;
5904     m_grid_sep.add(mat);
5905 
5906     draw_style* ds = new draw_style;
5907     ds->style = draw_lines;
5908     ds->line_pattern = m_grid_style.line_pattern;
5909     ds->line_width = m_grid_style.line_width;
5910     m_grid_sep.add(ds);
5911 
5912 /*
5913     vertices* vtxs = new vertices;
5914     vtxs->mode = gl::line_strip();
5915     m_grid_sep.add(vtxs);
5916 
5917     float z = 0.5F;
5918 
5919     vtxs->add(0,0,z);
5920     vtxs->add(1,0,z);
5921     vtxs->add(1,1,z);
5922     vtxs->add(0,1,z);
5923     vtxs->add(0,0,z);
5924 */
5925 /*
5926   int ntick = m_z_axis.tickNumber;
5927   if(ntick<=0) return;
5928 
5929   SoSeparator* sep = (SoSeparator*)gridSeparator.value();
5930 
5931   sep->addChild(fStyleCache->getMaterial
5932                (style->color.value(),
5933                 style->transparency.value()));
5934 
5935   sep->addChild(getLineStyle(*style));
5936 
5937   vec3f* points = new vec3f[4 * ntick];
5938   int pos = 0;
5939   for(int count=0;count<ntick;count++) {
5940     float xe = m_x_axis.width.value();
5941     float ye = m_y_axis.width.value();
5942     float zz = m_z_axis.coords[count];
5943     LIST_SET(points,pos,0 ,ye,zz);pos++;
5944     LIST_SET(points,pos,xe,ye,zz);pos++;
5945     LIST_SET(points,pos,xe,ye,zz);pos++;
5946     LIST_SET(points,pos,xe,0 ,zz);pos++;
5947   }
5948   if(pos>0) {
5949     SoCoordinate3* coordinate3 = new SoCoordinate3;
5950     int32_t pointn = pos;
5951     coordinate3->point.setValues(0,pointn,points);
5952     sep->addChild(coordinate3);
5953 
5954     SoLineSet* lineSet = new SoLineSet;
5955     int segmentn = pointn/2;
5956     int32_t* vertices = new int32_t[segmentn];
5957     for (int count=0;count<segmentn;count++) vertices[count] = 2;
5958     lineSet->numVertices.setValues(0,segmentn,vertices);
5959     delete [] vertices;
5960     sep->addChild(lineSet);
5961   }
5962 
5963   delete [] points;
5964 */
5965   }
5966 
5967 protected: //rep
5968   ////////////////////////////////////////////////////////////////////////////
5969   // reps xy /////////////////////////////////////////////////////////////////
5970   ////////////////////////////////////////////////////////////////////////////
5971   void rep_bins1D_xy_top_lines(const style& a_style,
5972                                const base_colormap& a_cmap,
5973                                const std::vector<rep_bin1D>& a_bins,
5974                                const rep_box& a_box_x,
5975                                const rep_box& a_box_y,
5976                                float a_zz/*,
5977                                const std::string& aID*/){
5978     painting_policy painting = a_style.painting;
5979 
5980     float xmin = a_box_x.m_pos;
5981     float dx = a_box_x.m_width;
5982     bool xlog = a_box_x.m_log;
5983 
5984     float ymin = a_box_y.m_pos;
5985     float dy = a_box_y.m_width;
5986     bool ylog = a_box_y.m_log;
5987 
5988     float y0 = 0;
5989     y0 = verify_log(y0,ymin,dy,ylog);
5990     if(y0<0) y0 = 0;
5991     if(y0>1) y0 = 1;
5992 
5993     separator* _sep = new separator();
5994 
5995     draw_style* ds = new draw_style;
5996     ds->style = draw_lines;
5997     ds->line_pattern = a_style.line_pattern;
5998     ds->line_width = a_style.line_width;
5999     _sep->add(ds);
6000 
6001     bool empty = true;
6002     colorf clr;
6003 
6004     float yp = 0;
6005     size_t xnbin = a_bins.size();
6006     for(size_t index=0;index<xnbin;index++) {
6007       float xx = a_bins[index].m_x_min;
6008       float xe = a_bins[index].m_x_max;
6009       float y = a_bins[index].m_val;
6010 
6011       float val = a_bins[index].m_val;
6012 
6013       xx = verify_log(xx,xmin,dx,xlog);
6014       xe = verify_log(xe,xmin,dx,xlog);
6015       y = verify_log(y,ymin,dy,ylog);
6016 
6017       // Clipping :
6018       if(xe<0) continue;
6019       if(xx>1) continue;
6020       if(xx<0) xx = 0;
6021       if(xe>1) xe = 1;
6022       if(y<0) y = 0;
6023       if(y>1) y = 1;
6024 
6025       separator* sep = new separator();
6026       _sep->add(sep);
6027 
6028     /*uuu
6029       a_bins[index].fSeparator = sep;
6030 
6031      {char s[128];
6032       //::sprintf(s,"%d",index);
6033       sep->setInfos(s);
6034       //::sprintf(s,"/0x%lx",(unsigned long)sep->getInfos());
6035       std::string sid = aID;
6036       sid += std::string(s);
6037       sep->setString(sid);}*/
6038 
6039       if(painting==painting_by_value) {
6040         a_cmap.get_color(val,clr);
6041       } else if( (painting==painting_grey_scale) ||
6042                  (painting==painting_grey_scale_inverse) ||
6043                  (painting==painting_violet_to_red) ){
6044         a_cmap.get_color(a_bins[index].m_ratio,clr);
6045       } else {
6046         clr = a_style.color;
6047       }
6048 
6049       rgba* mat = new rgba();
6050       mat->color = clr;
6051       sep->add(mat);
6052 
6053       vertices* vtxs = new vertices;
6054       vtxs->mode = gl::line_strip();
6055       sep->add(vtxs);
6056 
6057       vtxs->add(xx,yp,a_zz);
6058       vtxs->add(xx,y,a_zz);
6059       vtxs->add(xe,y,a_zz);
6060       if(index==xnbin-1){
6061         vtxs->add(xe,y0,a_zz);
6062       }
6063 
6064       empty = false;
6065       yp = y;
6066     }
6067 
6068     if(empty) {
6069       delete _sep;
6070     } else {
6071       m_bins_sep.add(_sep);
6072     }
6073   }
6074 
6075   void rep_bins1D_xy_points(std::ostream& a_out,
6076                             const style& a_style,
6077                             const base_colormap& a_cmap,
6078                             const std::vector<rep_bin1D>& a_bins,
6079                             const rep_box& a_box_x,
6080                             const rep_box& a_box_y,
6081                             float a_zz/*,
6082                             const std::string& aID*/){
6083     //::printf("debug : tools::sg::plotter::rep_bins1D_xy_points : begin\n");
6084     float xmin = a_box_x.m_pos;
6085     float dx = a_box_x.m_width;
6086     bool xlog = a_box_x.m_log;
6087 
6088     float ymin = a_box_y.m_pos;
6089     float dy = a_box_y.m_width;
6090     bool ylog = a_box_y.m_log;
6091 
6092     painting_policy painting = a_style.painting;
6093 
6094     separator* _sep = new separator();
6095 
6096     if(a_style.modeling==modeling_points()) {
6097       draw_style* ds = new draw_style;
6098       ds->style = draw_points;
6099       ds->point_size = a_style.point_size;
6100       _sep->add(ds);
6101     }
6102 
6103     bool empty = true;
6104     colorf clr;
6105     size_t xnbin = a_bins.size();
6106     for(size_t index=0;index<xnbin;index++) {
6107       float x = (a_bins[index].m_x_min + a_bins[index].m_x_max)/2;
6108       float y = a_bins[index].m_val;
6109       float val = a_bins[index].m_val;
6110 
6111       x = verify_log(x,xmin,dx,xlog);
6112       y = verify_log(y,ymin,dy,ylog);
6113 
6114       if((x<0)||(x>1)||(y<0)||(y>1)) continue;
6115 
6116       //::printf("debug : tools::sg::plotter::rep_bins1D_xy_points : x %g, y %g, val %g\n",x,y,val);
6117 
6118       separator* sep = new separator();
6119       _sep->add(sep);
6120 
6121       //a_bins[index].fSeparator = sep;
6122 
6123      //{char s[128];
6124      // ::sprintf(s,"%d",index);
6125      // sep->setInfos(s);
6126      // ::sprintf(s,"/0x%lx",(unsigned long)sep->getInfos());
6127      // std::string sid = aID;
6128      // sid += std::string(s);
6129      // sep->setString(sid);}
6130 
6131       if(painting==painting_by_value) {
6132         a_cmap.get_color(val,clr);
6133       } else if( (painting==painting_grey_scale) ||
6134                  (painting==painting_grey_scale_inverse) ||
6135                  (painting==painting_violet_to_red) ){
6136         a_cmap.get_color(a_bins[index].m_ratio,clr);
6137       } else {
6138         clr = a_style.color;
6139       }
6140 
6141       rgba* mat = new rgba();
6142       mat->color = clr;
6143       sep->add(mat);
6144 
6145       if(a_style.modeling==modeling_points()) {
6146         vertices* vtxs = new vertices;
6147         vtxs->mode = gl::points();
6148         vtxs->add(x,y,a_zz);
6149         sep->add(vtxs);
6150       } else if(a_style.modeling==modeling_markers()) {
6151         markers* _marks = new markers;
6152         _marks->size = a_style.marker_size;
6153         _marks->style = a_style.marker_style;
6154         _marks->add(x,y,a_zz);
6155         sep->add(_marks);
6156       } else {
6157         a_out << "tools::sg::plotter::rep_bins1D_xy_points :"
6158               << " bad modeling style " << tools::sout(a_style.modeling) << std::endl;
6159         delete _sep;
6160         return;
6161       }
6162 
6163       empty = false;
6164     }
6165 
6166     if(empty) {
6167       delete _sep;
6168     } else {
6169       m_bins_sep.add(_sep);
6170     }
6171   }
6172 
6173   void rep_bins1D_xy_boxes(const style& a_style,
6174                            const base_colormap& a_cmap,
6175                            const std::vector<rep_bin1D>& a_bins,
6176                            const rep_box& a_box_x,
6177                            const rep_box& a_box_y,
6178                            float a_zz //,const std::string& aID
6179                                ){
6180     painting_policy painting = a_style.painting;
6181 
6182     float xmin = a_box_x.m_pos;
6183     float dx = a_box_x.m_width;
6184     bool xlog = a_box_x.m_log;
6185 
6186     float ymin = a_box_y.m_pos;
6187     float dy = a_box_y.m_width;
6188     bool ylog = a_box_y.m_log;
6189 
6190     separator* _sep = new separator();
6191 
6192     _sep->add(new normal);
6193 
6194     bool empty = true;
6195     colorf clr;
6196 
6197     tools_vforcit(rep_bin1D,a_bins,it) {
6198       const rep_bin1D& rbin = *it;
6199 
6200       float xx = rbin.m_x_min;
6201       float xe = rbin.m_x_max;
6202       float yy = rbin.m_v_min;
6203       float ye = rbin.m_val;
6204       if(ye<yy) {
6205         yy = rbin.m_val;
6206         ye = rbin.m_v_min;
6207       }
6208 
6209       float val = rbin.m_val;
6210 
6211       xx = verify_log(xx,xmin,dx,xlog);
6212       xe = verify_log(xe,xmin,dx,xlog);
6213       yy = verify_log(yy,ymin,dy,ylog);
6214       ye = verify_log(ye,ymin,dy,ylog);
6215 
6216       // Clipping :
6217       if(xx>1) continue;
6218       if(xe<0) continue;
6219       if(xx<0) xx = 0;
6220       if(xe>1) xe = 1;
6221       if(yy>1) continue;
6222       if(ye<0) continue;
6223       if(yy<0) yy = 0;
6224       if(ye>1) ye = 1;
6225 
6226       //FIXME if(ye<=yy) continue; //Else we shall have a tessellation error.
6227 
6228       separator* sep = new separator();
6229       _sep->add(sep);
6230 
6231     //a_bins[index].fSeparator = sep;
6232     //{char s[128];
6233     //::sprintf(s,"%d",index);
6234     //sep->setInfos(s);
6235     //::sprintf(s,"/0x%lx",(unsigned long)sep->getInfos());
6236     //std::string sid = aID;
6237     //sid += std::string(s);
6238     //sep->setString(sid);}
6239 
6240       if(painting==painting_by_value) {
6241         a_cmap.get_color(val,clr);
6242       } else if( (painting==painting_grey_scale) ||
6243                  (painting==painting_grey_scale_inverse) ||
6244                  (painting==painting_violet_to_red) ){
6245         a_cmap.get_color(rbin.m_ratio,clr);
6246       } else {
6247         clr = a_style.color;
6248       }
6249 
6250       rgba* mat = new rgba();
6251       mat->color = clr;
6252       sep->add(mat);
6253 
6254       vertices* vtxs = new vertices;
6255       vtxs->mode = gl::triangle_fan();
6256       sep->add(vtxs);
6257 
6258       vtxs->add(xx,yy,a_zz);
6259       vtxs->add(xe,yy,a_zz);
6260       vtxs->add(xe,ye,a_zz);
6261       vtxs->add(xx,ye,a_zz);
6262 
6263       empty = false;
6264     }
6265 
6266     if(empty) {
6267       delete _sep;
6268     } else {
6269       m_bins_sep.add(_sep);
6270     }
6271   }
6272 
6273   void rep_bins1D_xy_wire_boxes(const style& a_style,
6274                                 const base_colormap& a_cmap,
6275                                 const std::vector<rep_bin1D>& a_bins,
6276                                 const rep_box& a_box_x,const rep_box& a_box_y,
6277                                 float a_zz,
6278                                 bool a_bar_chart/*,
6279                                 const std::string& aID*/){
6280 
6281     painting_policy painting = a_style.painting;
6282 
6283     float xmin = a_box_x.m_pos;
6284     float dx = a_box_x.m_width;
6285     bool xlog = a_box_x.m_log;
6286 
6287     float ymin = a_box_y.m_pos;
6288     float dy = a_box_y.m_width;
6289     bool ylog = a_box_y.m_log;
6290 
6291     separator* _sep = new separator();
6292 
6293     bool empty = true;
6294     colorf clr;
6295 
6296     tools_vforcit(rep_bin1D,a_bins,it) {
6297       const rep_bin1D& rbin = *it;
6298 
6299       float xx = rbin.m_x_min;
6300       float xe = rbin.m_x_max;
6301       float yy = rbin.m_v_min;
6302       float ye = rbin.m_val;
6303       if(ye<yy) {
6304         yy = rbin.m_val;
6305         ye = rbin.m_v_min;
6306       }
6307 
6308       float val = rbin.m_val;
6309 
6310       if(a_bar_chart) {
6311         bar_chart(a_style.bar_offset.value(),
6312                   a_style.bar_width.value(),xx,xe);
6313       }
6314 
6315       xx = verify_log(xx,xmin,dx,xlog);
6316       xe = verify_log(xe,xmin,dx,xlog);
6317       yy = verify_log(yy,ymin,dy,ylog);
6318       ye = verify_log(ye,ymin,dy,ylog);
6319 
6320       // Clipping :
6321       if(xx>1) continue;
6322       if(xe<0) continue;
6323       if(xx<0) xx = 0;
6324       if(xe>1) xe = 1;
6325       if(yy>1) continue;
6326       if(ye<0) continue;
6327       if(yy<0) yy = 0;
6328       if(ye>1) ye = 1;
6329 
6330       separator* sep = new separator();
6331       _sep->add(sep);
6332 
6333    //{char s[128];
6334     //::sprintf(s,"%d",index);
6335     //sep->setInfos(s);
6336     //::sprintf(s,"/0x%lx",(unsigned long)sep->getInfos());
6337     //std::string sid = aID;
6338     //sid += std::string(s);
6339     //sep->setString(sid);}
6340 
6341       if(painting==painting_by_value) {
6342         a_cmap.get_color(val,clr);
6343       } else if( (painting==painting_grey_scale) ||
6344                  (painting==painting_grey_scale_inverse) ||
6345                  (painting==painting_violet_to_red) ){
6346         a_cmap.get_color(rbin.m_ratio,clr);
6347       } else {
6348         clr = a_style.color;
6349       }
6350 
6351       rgba* mat = new rgba();
6352       mat->color = clr;
6353       sep->add(mat);
6354 
6355       vertices* vtxs = new vertices;
6356       vtxs->mode = gl::line_strip();
6357       sep->add(vtxs);
6358 
6359       vtxs->add(xx,yy,a_zz);
6360       vtxs->add(xe,yy,a_zz);
6361       vtxs->add(xe,ye,a_zz);
6362       vtxs->add(xx,ye,a_zz);
6363       vtxs->add(xx,yy,a_zz);
6364 
6365       empty = false;
6366     }
6367 
6368     if(empty) {
6369       delete _sep;
6370     } else {
6371       m_bins_sep.add(_sep);
6372     }
6373   }
6374 
6375   void rep_bins1D_xy_lines_one(const style& a_style,const std::vector<rep_bin1D>& a_bins,
6376                                const rep_box& a_box_x,const rep_box& a_box_y,float a_zz/*,const SbString& aID*/) {
6377     // Draw lines connecting top middle of bins.
6378 
6379     //::printf("debug : rep_bins2D_lines_one\n");
6380 
6381     size_t xnbin = a_bins.size();
6382     std::vector<vec3f> points(xnbin);
6383     for(size_t index=0;index<xnbin;index++) {
6384       float x = (a_bins[index].m_x_min + a_bins[index].m_x_max)/2;
6385       float y = a_bins[index].m_val;
6386       points[index] = vec3f(x,y,a_zz);
6387     }
6388 
6389     vertices* vtxs = new vertices;
6390     std::vector<float>& pts = vtxs->xyzs.values(); //npt*3
6391 
6392     clip_polyline_2D(points,a_box_x,a_box_y,pts);
6393     if(pts.size()) {
6394       sg::separator* separator = new sg::separator;
6395       //separator->setString(aID);
6396 
6397       rgba* mat = new rgba();
6398       mat->color = a_style.color;
6399       separator->add(mat);
6400 
6401       draw_style* ds = new draw_style;
6402       ds->style = draw_lines;
6403       ds->line_pattern = a_style.line_pattern;
6404       ds->line_width = a_style.line_width;
6405       separator->add(ds);
6406 
6407       vtxs->mode = gl::line_strip();
6408       separator->add(vtxs);
6409 
6410       m_bins_sep.add(separator);
6411     } else {
6412       delete vtxs;
6413     }
6414   }
6415 
6416   void rep_bins1D_xy_curve_one(std::ostream& a_out,const style& a_style,const std::vector<rep_bin1D>& a_bins,
6417                                const rep_box& a_box_x,const rep_box& a_box_y,float a_zz/*,const SbString& aID*/){
6418     //::printf("debug : rep_bins1D_curve_one\n");
6419 
6420     size_t number = a_bins.size();
6421     if(!number) return;
6422 
6423     double* xs = new double[number];
6424     double* ys = new double[number];
6425     float x,y;
6426     for(size_t index=0;index<number;index++) {
6427       x = (a_bins[index].m_x_min + a_bins[index].m_x_max)/2;
6428       y = a_bins[index].m_val;
6429       xs[index] = x;ys[index] = y;
6430     }
6431     spline::cubic _spline(a_out,number,xs,ys);
6432   //spline::quintic _spline(a_out,number,xs,ys);
6433     delete [] xs;delete [] ys;
6434 
6435     float xmn = m_x_axis_data.min_value();
6436     float xmx = m_x_axis_data.max_value();
6437     unsigned int nstp = curve_number_of_points;
6438     float step = (xmx - xmn)/nstp;
6439     std::vector<vec3f> points(nstp+1);
6440     for(unsigned int ibin=0;ibin<=nstp;ibin++) {
6441       float xx = xmn + ibin * step;
6442       double val = _spline.eval(xx);
6443       points[ibin].set_value(xx,float(val),a_zz);
6444     }
6445 
6446     vertices* vtxs = new vertices;
6447     std::vector<float>& pts = vtxs->xyzs.values(); //npt*3
6448 
6449     clip_polyline_2D(points,a_box_x,a_box_y,pts);
6450     if(pts.size()) {
6451       sg::separator* separator = new sg::separator;
6452       //separator->setString(aID);
6453 
6454       rgba* mat = new rgba();
6455       mat->color = a_style.color;
6456       separator->add(mat);
6457 
6458       draw_style* ds = new draw_style;
6459       ds->style = draw_lines;
6460       ds->line_pattern = a_style.line_pattern;
6461       ds->line_width = a_style.line_width;
6462       separator->add(ds);
6463 
6464       vtxs->mode = gl::line_strip();
6465       separator->add(vtxs);
6466 
6467       m_bins_sep.add(separator);
6468     } else {
6469       delete vtxs;
6470     }
6471 
6472   }
6473 
6474 
6475   void rep_bins2D_xy_box(const style& a_style,const std::vector<rep_bin2D>& a_bins,
6476                          const rep_box& a_box_x,const rep_box& a_box_y,float a_bmin,float a_bmax,float a_zz) {
6477     // Draw box of size proportionnal to bin value.
6478 
6479     //std::cout << "debug : tools::sg::plotter::rep_bins2D_xy_box" << std::endl;
6480 
6481     separator* _sep = new separator();
6482 
6483     _sep->add(new normal);
6484 
6485     rgba* mat = new rgba();
6486     mat->color = a_style.color;
6487     _sep->add(mat);
6488 
6489     float xmin = a_box_x.m_pos;
6490     float dx = a_box_x.m_width;
6491     bool xlog = a_box_x.m_log;
6492 
6493     float ymin = a_box_y.m_pos;
6494     float dy = a_box_y.m_width;
6495     bool ylog = a_box_y.m_log;
6496 
6497     bool empty = true;
6498     float range = a_bmax - a_bmin;
6499 
6500     tools_vforcit(rep_bin2D,a_bins,it) {
6501       const rep_bin2D& rbin = *it;
6502 
6503       float xx = rbin.m_x_min;
6504       float xe = rbin.m_x_max;
6505       float yy = rbin.m_y_min;
6506       float ye = rbin.m_y_max;
6507       float val = rbin.m_val;
6508 
6509       float xsize,ysize;
6510       if(range>0) {
6511         // If val = bmax, the box maps the cell.
6512         xsize = (val - a_bmin) * (xe - xx) / range;
6513         ysize = (val - a_bmin) * (ye - yy) / range;
6514       } else {
6515         //If range is 0. ; then all bins that have
6516         // entries have same values. Draw box xdbin * ydbin.
6517         xsize = xe - xx;
6518         ysize = ye - yy;
6519       }
6520 
6521       xx = xx + ((xe-xx) - xsize)/2;
6522       xe = xx + xsize;
6523       yy = yy + ((ye-yy) - ysize)/2;
6524       ye = yy + ysize;
6525 
6526       xx = verify_log(xx ,xmin,dx  ,xlog);
6527       xe = verify_log(xe ,xmin,dx  ,xlog);
6528       yy = verify_log(yy ,ymin,dy  ,ylog);
6529       ye = verify_log(ye ,ymin,dy  ,ylog);
6530 
6531       // Clipping :
6532       if(xx>1) continue;
6533       if(xe<0) continue;
6534       if(xx<0) xx = 0;
6535       if(xe>1) xe = 1;
6536       if(yy>1) continue;
6537       if(ye<0) continue;
6538       if(yy<0) yy = 0;
6539       if(ye>1) ye = 1;
6540 
6541       //sg::separator* sep = new separator();
6542       //_sep->add(sep);
6543 
6544    /*{char s[128];
6545       //::sprintf(s,"%d %d",rbin.fI,rbin.fJ);
6546       sep->setInfos(s);
6547       //::sprintf(s,"/0x%lx",(unsigned long)sep->getInfos());
6548       std::string sid = aID;
6549       sid += std::string(s);
6550       sep->setString(sid);}*/
6551 
6552       vertices* vtxs = new vertices;
6553       vtxs->mode = gl::triangle_fan();
6554       //sep->add(vtxs);
6555       _sep->add(vtxs);
6556 
6557       vtxs->add(xx,yy,a_zz);
6558       vtxs->add(xe,yy,a_zz);
6559       vtxs->add(xe,ye,a_zz);
6560       vtxs->add(xx,ye,a_zz);
6561 
6562       empty = false;
6563     }
6564 
6565     if(empty) {
6566       delete _sep;
6567     } else {
6568       m_bins_sep.add(_sep);
6569     }
6570   }
6571 
6572   void rep_bins2D_xy_wire_box(const style& a_style,
6573                               const std::vector<rep_bin2D>& a_bins,
6574                               const rep_box& a_box_x,const rep_box& a_box_y,
6575                               float a_bmin,float a_bmax,float a_zz
6576                               /*,const SbString& aID*/){
6577     // Draw box of size proportionnal to bin value.
6578 
6579     sg::separator* separator = new sg::separator;
6580 
6581     rgba* mat = new rgba();
6582     mat->color = a_style.color;
6583     separator->add(mat);
6584 
6585     draw_style* ds = new draw_style;
6586     ds->style = draw_lines;
6587     ds->line_pattern = a_style.line_pattern;
6588     ds->line_width = a_style.line_width;
6589     separator->add(ds);
6590 
6591     vertices* vtxs = new vertices;
6592     vtxs->mode = gl::lines();
6593     separator->add(vtxs);
6594 
6595     bool empty = true;
6596 
6597     float xmin = a_box_x.m_pos;
6598     float dx = a_box_x.m_width;
6599     bool xlog = a_box_x.m_log;
6600 
6601     float ymin = a_box_y.m_pos;
6602     float dy = a_box_y.m_width;
6603     bool ylog = a_box_y.m_log;
6604 
6605     float range = a_bmax - a_bmin;
6606     size_t number = a_bins.size();
6607     for(size_t index=0;index<number;index++) {
6608 
6609       float xx = a_bins[index].m_x_min;
6610       float xe = a_bins[index].m_x_max;
6611       float yy = a_bins[index].m_y_min;
6612       float ye = a_bins[index].m_y_max;
6613       float val = a_bins[index].m_val;
6614 
6615       float xsize,ysize;
6616       if(range>0) {
6617         // If val = bmax, the box maps the cell.
6618         xsize = (val - a_bmin) * (xe - xx) / range;
6619         ysize = (val - a_bmin) * (ye - yy) / range;
6620       } else {
6621         //If range is 0. ; then all bins that have
6622         // entries have same values. Draw box xdbin * ydbin.
6623         xsize = xe - xx;
6624         ysize = ye - yy;
6625       }
6626 
6627       xx = xx + ((xe-xx) - xsize)/2;
6628       xe = xx + xsize;
6629       yy = yy + ((ye-yy) - ysize)/2;
6630       ye = yy + ysize;
6631 
6632       xx = verify_log(xx ,xmin,dx  ,xlog);
6633       xe = verify_log(xe ,xmin,dx  ,xlog);
6634       yy = verify_log(yy ,ymin,dy  ,ylog);
6635       ye = verify_log(ye ,ymin,dy  ,ylog);
6636 
6637       // Clipping :
6638       if(xx>1) continue;
6639       if(xe<0) continue;
6640       if(xx<0) xx = 0;
6641       if(xe>1) xe = 1;
6642       if(yy>1) continue;
6643       if(ye<0) continue;
6644       if(yy<0) yy = 0;
6645       if(ye>1) ye = 1;
6646 
6647       //::printf("debug : zzzzuu : %g %g %g %g\n",xx,xe,yy,ye);
6648 
6649      //{char s[128];
6650      // ::sprintf(s,"%d %d",a_bins[index].fI,a_bins[index].fJ);
6651      // sep->setInfos(s);}
6652      //{std::string sp;
6653      // if(!p2sx(sep->getInfos(),sp)){}
6654      // std::string sid(aID.getString());
6655      // sid += "/"+sp;
6656      // sep->setString(sid.c_str());}
6657 
6658     //vertices* vtxs = new vertices;
6659     //vtxs->mode = gl::line_strip();
6660     //separator->add(vtxs);
6661     //vtxs->add(xx,yy,a_zz);
6662     //vtxs->add(xe,yy,a_zz);
6663     //vtxs->add(xe,ye,a_zz);
6664     //vtxs->add(xx,ye,a_zz);
6665     //vtxs->add(xx,yy,a_zz);
6666 
6667       vtxs->add(xx,yy,a_zz);
6668       vtxs->add(xe,yy,a_zz);
6669 
6670       vtxs->add(xe,yy,a_zz);
6671       vtxs->add(xe,ye,a_zz);
6672 
6673       vtxs->add(xe,ye,a_zz);
6674       vtxs->add(xx,ye,a_zz);
6675 
6676       vtxs->add(xx,ye,a_zz);
6677       vtxs->add(xx,yy,a_zz);
6678 
6679       empty = false;
6680     }
6681 
6682     if(empty) {
6683       delete separator;
6684     } else {
6685       m_bins_sep.add(separator);
6686     }
6687   }
6688 
6689   void rep_bins2D_xy_solid(const style& a_style,const base_colormap& a_cmap,const std::vector<rep_bin2D>& a_bins,
6690                            const rep_box& a_box_x,const rep_box& a_box_y,float a_zz) {
6691     painting_policy painting = a_style.painting;
6692 
6693     separator* _sep = new separator();
6694 
6695     _sep->add(new normal);
6696 
6697     float xmin = a_box_x.m_pos;
6698     float dx = a_box_x.m_width;
6699     bool xlog = a_box_x.m_log;
6700 
6701     float ymin = a_box_y.m_pos;
6702     float dy = a_box_y.m_width;
6703     bool ylog = a_box_y.m_log;
6704 
6705     bool empty = true;
6706     colorf clr;
6707 
6708     tools_vforcit(rep_bin2D,a_bins,it) {
6709       const rep_bin2D& rbin = *it;
6710 
6711       float xx = rbin.m_x_min;
6712       float xe = rbin.m_x_max;
6713       float yy = rbin.m_y_min;
6714       float ye = rbin.m_y_max;
6715       float val = rbin.m_val;
6716 
6717       xx = verify_log(xx ,xmin,dx  ,xlog);
6718       xe = verify_log(xe ,xmin,dx  ,xlog);
6719       yy = verify_log(yy ,ymin,dy  ,ylog);
6720       ye = verify_log(ye ,ymin,dy  ,ylog);
6721 
6722       // Clipping :
6723       if(xx>1) continue;
6724       if(xe<0) continue;
6725       if(xx<0) xx = 0;
6726       if(xe>1) xe = 1;
6727       if(yy>1) continue;
6728       if(ye<0) continue;
6729       if(yy<0) yy = 0;
6730       if(ye>1) ye = 1;
6731 
6732       if(painting==painting_by_value) {
6733         a_cmap.get_color(val,clr);
6734       } else if( (painting==painting_grey_scale) ||
6735                  (painting==painting_grey_scale_inverse) ||
6736                  (painting==painting_violet_to_red) ){
6737         a_cmap.get_color(rbin.m_ratio,clr);
6738       } else {
6739         clr = a_style.color;
6740       }
6741 
6742       rgba* mat = new rgba();
6743       mat->color = clr;
6744       _sep->add(mat);
6745 
6746       vertices* vtxs = new vertices;
6747       vtxs->mode = gl::triangle_fan();
6748       //sep->add(vtxs);
6749       _sep->add(vtxs);
6750 
6751       vtxs->add(xx,yy,a_zz);
6752       vtxs->add(xe,yy,a_zz);
6753       vtxs->add(xe,ye,a_zz);
6754       vtxs->add(xx,ye,a_zz);
6755 
6756       empty = false;
6757     }
6758 
6759     if(empty) {
6760       delete _sep;
6761     } else {
6762       m_bins_sep.add(_sep);
6763     }
6764   }
6765 
6766   void rep_bins2D_xy_random_one(const style& a_style,const std::vector<rep_bin2D>& a_bins,
6767                                 const rep_box& a_box_x,const rep_box& a_box_y,float a_bmin,float a_bmax,float a_zz
6768                                 /*,const SbString& aID*/){
6769     //::printf("debug : rep_bins2D_xy_random_one\n");
6770 
6771     sg::separator* separator = new sg::separator;
6772 
6773     rgba* mat = new rgba();
6774     mat->color = a_style.color;
6775     separator->add(mat);
6776 
6777     draw_style* ds = new draw_style;
6778     ds->style = draw_points;
6779     ds->point_size = a_style.point_size;
6780     separator->add(ds);
6781 
6782     float xmin = a_box_x.m_pos;
6783     float dx = a_box_x.m_width;
6784     bool xlog = a_box_x.m_log;
6785 
6786     float ymin = a_box_y.m_pos;
6787     float dy = a_box_y.m_width;
6788     bool ylog = a_box_y.m_log;
6789 
6790     //  Draw for each bins a number of random
6791     // points proportiannal to bins range.
6792 
6793     float range = a_bmax - a_bmin;
6794 
6795     bool empty = true;
6796 
6797     size_t number = a_bins.size();
6798     for(size_t index=0;index<number;index++) {
6799 
6800       float xx = a_bins[index].m_x_min;
6801       float xe = a_bins[index].m_x_max;
6802       float yy = a_bins[index].m_y_min;
6803       float ye = a_bins[index].m_y_max;
6804       float val = a_bins[index].m_val;
6805 
6806       // If range is 0. ; then all bins that have entries
6807       // have same values. Draw one point.
6808 
6809       int nmin = 1;
6810       int nmax = 50;
6811       int npt = range>0. ? (int)((val - a_bmin)*(nmax-nmin)/range + nmin):1;
6812       if(npt>0) {
6813         vertices* vtxs = new vertices;
6814         vtxs->mode = gl::points();
6815         separator->add(vtxs);
6816 
6817         float xdbin = xe - xx;
6818         float ydbin = ye - yy;
6819         for(int count=0;count<npt;count++) {
6820           float xxx = xx + xdbin * m_rtausmef.shoot();
6821           float yyy = yy + ydbin * m_rtausmef.shoot();
6822           xxx = verify_log(xxx ,xmin,dx  ,xlog);
6823           yyy = verify_log(yyy ,ymin,dy  ,ylog);
6824           if((xxx>=0)&&(xxx<=1)  &&
6825              (yyy>=0)&&(yyy<=1)  ) {
6826             vtxs->add(xxx,yyy,a_zz);
6827             empty = false;
6828           }
6829         }
6830       }
6831 
6832     }//end for
6833 
6834     if(empty) {
6835       delete separator;
6836     } else {
6837       m_bins_sep.add(separator);
6838     }
6839   }
6840 
6841   void rep_bins2D_xy_text(
6842    const style& //a_style
6843   ,const std::vector<rep_bin2D>& //a_bins
6844   ,const rep_box& //a_box_x
6845   ,const rep_box& //a_box_y
6846   //,const SbString& aID
6847   ){
6848     //Draw box and text for number of entries.
6849     ::printf("debug : rep_bins2D_xy_text : dummy\n");
6850 
6851   /*
6852     sg::separator* separator = new sg::separator;
6853 
6854     //bool drawWireBoxe = false;
6855 
6856     bool empty = true;
6857 
6858     float xmin = a_box_x.m_pos;
6859     float dx = a_box_x.m_width;
6860     bool xlog = a_box_x.m_log;
6861 
6862     float ymin = a_box_y.m_pos;
6863     float dy = a_box_y.m_width;
6864     bool ylog = a_box_y.m_log;
6865 
6866     vec3f points[5];
6867 
6868     for(unsigned int index=0;index<a_bins.size();index++) {
6869 
6870       float xx = a_bins[index].m_x_min;
6871       float xe = a_bins[index].m_x_max;
6872       float yy = a_bins[index].m_y_min;
6873       float ye = a_bins[index].m_y_max;
6874       float val = a_bins[index].m_val;
6875 
6876       int ival = (int)val;
6877       if(ival==0) continue;
6878 
6879       xx = VerifyLog(xx ,xmin,dx  ,xlog);
6880       xe = VerifyLog(xe ,xmin,dx  ,xlog);
6881       yy = VerifyLog(yy ,ymin,dy  ,ylog);
6882       ye = VerifyLog(ye ,ymin,dy  ,ylog);
6883 
6884       // Clipping :
6885       if(xx>1) continue;
6886       if(xe<0) continue;
6887       if(xx<0) xx = 0;
6888       if(xe>1) xe = 1;
6889       if(yy>1) continue;
6890       if(ye<0) continue;
6891       if(yy<0) yy = 0;
6892       if(ye>1) ye = 1;
6893 
6894       char sval[32];
6895       //::sprintf (sval,"%d",ival);
6896       SbString sbval(sval);
6897       int charn = sbval.getLength();
6898       if(charn<=0) continue;
6899 
6900       SoSceneGraph* sep = new SoSceneGraph;
6901       separator->addChild(sep);
6902 
6903      {char s[128];
6904       //::sprintf(s,"%d %d",a_bins[index].fI,a_bins[index].fJ);
6905       sep->setInfos(s);}
6906      {std::string sp;
6907       if(!p2sx(sep->getInfos(),sp)){}
6908       std::string sid(aID.getString());
6909       sid += "/"+sp;
6910       sep->setString(sid.c_str());}
6911 
6912       SoMaterial* material =
6913         fStyleCache->getMaterial(a_style.color.getValue(),
6914                                  a_style.transparency.getValue());
6915       sep->addChild(material);
6916 
6917       sep->addChild(getLineStyle(a_style));
6918 
6919       float dx = xe-xx;
6920       float dy = ye-yy;
6921 
6922       if(drawWireBoxe) {
6923         LIST_SET(points,0,xx,yy,0);
6924         LIST_SET(points,1,xe,yy,0);
6925         LIST_SET(points,2,xe,ye,0);
6926         LIST_SET(points,3,xx,ye,0);
6927         LIST_SET(points,4,xx,yy,0);
6928         coordIndex[0] = icoord + 0;
6929         coordIndex[1] = icoord + 1;
6930         coordIndex[2] = icoord + 2;
6931         coordIndex[3] = icoord + 3;
6932         coordIndex[4] = icoord + 4;
6933         coordIndex[5] = SO_END_LINE_INDEX;
6934 
6935         coordinate3->point.setValues(icoord,5,points);
6936         icoord += 5;
6937 
6938         SoIndexedLineSet* lineSet = new SoIndexedLineSet;
6939         lineSet->coordIndex.setValues(0,6,coordIndex);
6940         sep->addChild(lineSet);
6941       }
6942 
6943       float x = xx + 0.1F * dx;
6944       float y = yy + 0.1F * dy;
6945       float z = 0;
6946       float w = dx * 0.5F;
6947       float h = dy * 0.5F;
6948 
6949       SoTransform* transform = new SoTransform;
6950       transform->scaleFactor.setValue(vec3f(w/charn,h,1));
6951       transform->translation.setValue(x,y,z);
6952       sep->addChild(transform);
6953 
6954       SoTextHershey* text = new SoTextHershey;
6955       text->string.setValue(sbval);
6956       sep->addChild (text);
6957 
6958       empty = false;
6959     }
6960 
6961     if(empty) {
6962       delete separator;
6963     } else {
6964       m_bins_sep.add(separator);
6965     }
6966   */
6967   }
6968 
6969   void rep_contour_xy(std::ostream& a_out,const style& a_style,painting_policy a_painting,
6970                       const base_colormap& a_cmap,clist_contour& a_contour,
6971                       const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z,float a_zz
6972                       /*,const std::string& aID*/){
6973     //a_out << "debug : rep_contour_xy :" << std::endl;
6974 
6975     float xmin = a_box_x.m_pos;
6976     float dx = a_box_x.m_width;
6977     bool xlog = a_box_x.m_log;
6978 
6979     float ymin = a_box_y.m_pos;
6980     float dy = a_box_y.m_width;
6981     bool ylog = a_box_y.m_log;
6982 
6983     float zmin = a_box_z.m_pos;
6984     float dz = a_box_z.m_width;
6985     //bool zlog = a_box_z.m_log;
6986 
6987     sg::separator* separator = new sg::separator;
6988     //separator->setString(aID);
6989 
6990     draw_style* ds = new draw_style;
6991     ds->style.value(draw_lines);
6992     ds->line_pattern.value(a_style.line_pattern);
6993     ds->line_width.value(a_style.line_width);
6994     separator->add(ds);
6995 
6996     atb_vertices* vtxs = new atb_vertices;
6997     vtxs->mode = gl::lines(); //segments
6998     separator->add(vtxs);
6999 
7000     bool empty = true;
7001 
7002     for (unsigned int i=0;i<a_contour.get_number_of_planes();i++)  {
7003       cline_strip_list* pStripList = a_contour.get_lines(i);
7004       if(!pStripList) {
7005         a_out << "tools::sg;:plotter::rep_contour_xy : problem with contour." << std::endl;
7006         delete separator;
7007         return;
7008       }
7009 
7010       //If zlog true, zz is already in log.
7011       float val = (float)a_contour.get_plane(i);
7012       float zz = val;
7013 
7014       zz = verify_log(zz,zmin,dz,false);
7015       if(zz>1) continue;
7016       if(zz<0) continue;
7017 
7018       colorf _color;
7019       if(a_painting==painting_by_value) {
7020         a_cmap.get_color(val,_color);
7021       } else if(a_painting==painting_by_level) {
7022         size_t icol = a_cmap.colorn() ? (i % a_cmap.colorn()) :0;
7023         _color = a_cmap.color(icol);
7024       } else {
7025         _color = a_style.color;
7026       }
7027 
7028       tools_lforcit(cline_strip*,*pStripList,pos) {
7029         cline_strip* pStrip = (*pos);
7030         if(!pStrip) {
7031           a_out << "tools::sg;:plotter::rep_contour_xy : problem with contour." << std::endl;
7032           delete separator;
7033           return;
7034         }
7035         if (pStrip->empty()) continue;
7036 
7037         //// putting point at start and end of strip
7038         //// retreiving index
7039         //unsigned int index=pStrip->front();
7040         //double xb=a_contour.get_xi(index);
7041         //double yb=a_contour.get_yi(index);
7042         //// retreiving index
7043         ////glColor4f(0,0,1,.8f);
7044         //index=pStrip->back();
7045         //double xe=a_contour.get_xi(index);
7046         //double ye=a_contour.get_yi(index);
7047 
7048         bool first = true;
7049         float xprev = 0;
7050         float yprev = 0;
7051         float xx,yy;
7052 
7053         tools_lforcit(unsigned int,*pStrip,pos2) {
7054           xx = (float)a_contour.get_xi(*pos2);
7055           yy = (float)a_contour.get_yi(*pos2);
7056           xx = verify_log(xx,xmin,dx,xlog);
7057           yy = verify_log(yy,ymin,dy,ylog);
7058           if(
7059               (xx<0) || (xx>1) ||
7060               (yy<0) || (yy>1)
7061             ) {
7062             // Throw away this strip :
7063           }
7064           if(first) {
7065             first = false;
7066           } else {
7067             vtxs->add(xprev,yprev,a_zz+zz);
7068             vtxs->add(xx,yy,a_zz+zz);
7069             vtxs->add_color(_color);
7070             vtxs->add_color(_color);
7071           }
7072           xprev = xx;
7073           yprev = yy;
7074 
7075           empty = false;
7076       }
7077     }
7078 
7079     }
7080 
7081     if(empty) {
7082       delete separator;
7083     } else {
7084       m_bins_sep.add(separator);
7085     }
7086   }
7087 
7088   void rep_contour_xy_filled(std::ostream& a_out,const style& a_style,painting_policy a_painting,
7089                              const base_colormap& a_cmap,clist_contour& a_contour,
7090                              const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z,float a_zz
7091                              /*,const std::string& aID*/){
7092     //a_out << "debug : rep_contour_xy_filled :" << std::endl;
7093 
7094     float xmin = a_box_x.m_pos;
7095     float dx = a_box_x.m_width;
7096     bool xlog = a_box_x.m_log;
7097 
7098     float ymin = a_box_y.m_pos;
7099     float dy = a_box_y.m_width;
7100     bool ylog = a_box_y.m_log;
7101 
7102     float zmin = a_box_z.m_pos;
7103     float dz = a_box_z.m_width;
7104     //bool zlog = a_box_z.m_log;
7105 
7106     sg::separator* separator = new sg::separator;
7107     //separator->setString(aID);
7108 
7109     vec3f AB,BC,vcross;
7110 
7111     {// Draw background :
7112       sg::separator* sep = new sg::separator;
7113       separator->add(sep);
7114 
7115       float zz = a_zz - 0.01F;
7116 
7117       colorf _color;
7118       if(a_cmap.colorn()) {
7119         _color = a_cmap.color(0);
7120       } else {
7121         _color = a_style.color;
7122       }
7123 
7124       rgba* mat = new rgba();
7125       mat->color = _color;
7126       sep->add(mat);
7127 
7128       float xx = xmin;
7129       float xe = xmin+dx;
7130       float yy = ymin;
7131       float ye = ymin+dy;
7132 
7133       xx = verify_log(xx,xmin,dx,xlog);
7134       xe = verify_log(xe,xmin,dx,xlog);
7135       yy = verify_log(yy,ymin,dy,ylog);
7136       ye = verify_log(ye,ymin,dy,ylog);
7137 
7138       vertices* vtxs = new vertices;
7139       vtxs->mode = gl::triangle_fan();
7140       vtxs->add(xx,yy,zz);
7141       vtxs->add(xe,yy,zz);
7142       vtxs->add(xe,ye,zz);
7143       vtxs->add(xx,ye,zz);
7144       sep->add(vtxs);
7145 
7146     } // End background.
7147 
7148     bool empty = true;
7149 
7150     for (unsigned int i=0;i<a_contour.get_number_of_planes();i++)  {
7151 
7152       cline_strip_list* pStripList = a_contour.get_lines(i);
7153       if(!pStripList) {
7154         a_out << "tools::sg;:plotter::rep_contour_xy_filled : problem with contour." << std::endl;
7155         delete separator;
7156         return;
7157       }
7158 
7159       sg::separator* sep = new sg::separator;
7160       separator->add(sep);
7161 
7162       //If zlog true, zz is already in log.
7163       float val = (float)a_contour.get_plane(i);
7164       float zz = val;
7165 
7166       zz = verify_log(zz,zmin,dz,false);
7167       if(zz>1) continue;
7168       if(zz<0) continue;
7169 
7170       std::vector< std::vector<vec3f> > contourVector;
7171 
7172       tools_lforcit(cline_strip*,*pStripList,pos) {
7173         cline_strip* pStrip = (*pos);
7174         if(pStrip->size() >2) {
7175           std::vector<vec3f> v;
7176           for (cline_strip::iterator pos2=pStrip->begin();pos2 != pStrip->end();pos2++) {
7177             unsigned int index=(*pos2);
7178             float xx = (float)a_contour.get_xi(index);
7179             float yy = (float)a_contour.get_yi(index);
7180             xx = verify_log(xx,xmin,dx,xlog);
7181             yy = verify_log(yy,ymin,dy,ylog);
7182             v.push_back(vec3f(xx,yy,a_zz+zz));
7183           }
7184           contourVector.push_back(v);
7185         }
7186       }
7187 
7188       std::vector<tess_triangle> tris;
7189       tess_contour tessContour(a_out,tris); //we pass a ref to tris.
7190       tessContour.getFilledArea(contourVector);
7191       if(!tris.size()) continue;
7192 
7193       colorf _color;
7194       if(a_painting==painting_by_value) {
7195         a_cmap.get_color(val,_color);
7196       } else if(a_painting==painting_by_level) {
7197         int icol = a_cmap.colorn() ? (i % a_cmap.colorn()) :0;
7198         _color = a_cmap.color(icol);
7199       } else {
7200         _color = a_style.color;
7201       }
7202 
7203       atb_vertices* vtxs = new atb_vertices; //PAW_C/color.kumac. It needs back face.
7204       vtxs->mode = gl::triangles();
7205       sep->add(vtxs);
7206 
7207       for(size_t itri=0;itri<tris.size();itri++) {
7208         tess_triangle& tri = tris[itri];
7209         AB.set_value((float)(tri.pointB[0]-tri.pointA[0]),
7210                      (float)(tri.pointB[1]-tri.pointA[1]),
7211                      (float)(tri.pointB[2]-tri.pointA[2]));
7212         BC.set_value((float)(tri.pointC[0]-tri.pointB[0]),
7213                      (float)(tri.pointC[1]-tri.pointB[1]),
7214                      (float)(tri.pointC[2]-tri.pointB[2]));
7215         AB.cross(BC,vcross);
7216         if(vcross.z()>=0) {
7217           vtxs->add((float)tri.pointA[0],(float)tri.pointA[1],(float)tri.pointA[2]);
7218           vtxs->add((float)tri.pointB[0],(float)tri.pointB[1],(float)tri.pointB[2]);
7219           vtxs->add((float)tri.pointC[0],(float)tri.pointC[1],(float)tri.pointC[2]);
7220         } else {
7221           vtxs->add((float)tri.pointA[0],(float)tri.pointA[1],(float)tri.pointA[2]);
7222           vtxs->add((float)tri.pointC[0],(float)tri.pointC[1],(float)tri.pointC[2]);
7223           vtxs->add((float)tri.pointB[0],(float)tri.pointB[1],(float)tri.pointB[2]);
7224         }
7225         vtxs->add_color(_color);
7226         vtxs->add_color(_color);
7227         vtxs->add_color(_color);
7228       }
7229 
7230       empty = false;
7231 
7232     }
7233 
7234     if(empty) {
7235       delete separator;
7236     } else {
7237       m_bins_sep.add(separator);
7238     }
7239   }
7240 
7241   void rep_errors_plus_xy(std::ostream& /*a_out*/,const style& a_style,const std::vector<rep_bin1D>& a_bins,
7242                           const rep_box& a_box_x,const rep_box& a_box_y,const std::vector<float>& a_bars,float aZ) {
7243     //a_out << "debug : rep_erros_plus_xy : begin :" << std::endl;
7244     separator* _sep = new separator();
7245     //_sep->setString(aID);
7246 
7247     rgba* mat = new rgba();
7248     mat->color = a_style.color;
7249     _sep->add(mat);
7250 
7251     draw_style* ds = new draw_style;
7252     ds->style.value(draw_lines);
7253     ds->line_pattern.value(a_style.line_pattern);
7254     ds->line_width.value(a_style.line_width);
7255     _sep->add(ds);
7256 
7257     vertices* vtxs = new vertices;
7258     vtxs->mode = gl::lines();
7259     _sep->add(vtxs);
7260 
7261     float xmin = a_box_x.m_pos;
7262     float dx = a_box_x.m_width;
7263     bool xlog = a_box_x.m_log;
7264 
7265     float ymin = a_box_y.m_pos;
7266     float dy = a_box_y.m_width;
7267     bool ylog = a_box_y.m_log;
7268 
7269     size_t xnbin = a_bins.size();
7270 
7271     for(size_t index=0;index<xnbin;index++) {
7272 
7273       //Need all bins modeled for fitting.
7274 
7275       float val = a_bins[index].m_val;
7276       float bar_height = a_bars[index];
7277 
7278       float bar_min = val - bar_height/2;
7279       float bar_max = val + bar_height/2;
7280 
7281       float xx = a_bins[index].m_x_min;
7282       float xe = a_bins[index].m_x_max;
7283 
7284       xx = verify_log(xx,xmin,dx,xlog);
7285       xe = verify_log(xe,xmin,dx,xlog);
7286       val = verify_log(val,ymin,dy,ylog);
7287 
7288       bar_min = verify_log(bar_min,ymin,dy,ylog);
7289       bar_max = verify_log(bar_max,ymin,dy,ylog);
7290 
7291       if(xe<0) continue;
7292       if(xx>1) continue;
7293       if(xx<0) xx = 0;
7294       if(xe>1) xe = 1;
7295       //if(val<0) val = 0;
7296       //if(val>1) val = 1;
7297 
7298       float ex = (xe+xx)/2;
7299       //if( (ex >=0)&&(ex <=1) ) { //FIXME : have to clip
7300 
7301       float edx = 0.3F * (xe-xx);
7302 
7303       if((val>=0)&&(val<=1)) {
7304         vtxs->add(ex-edx,val,aZ);
7305         vtxs->add(ex+edx,val,aZ);
7306       }
7307 
7308       if(bar_min >1)  {
7309         // do nothing
7310       } else  if(bar_max <0)  {
7311         // do nothing
7312       } else  if(bar_min <0) {
7313         if(bar_max >1) {
7314           vtxs->add(ex,0,aZ);
7315           vtxs->add(ex,1,aZ);
7316         } else {
7317           vtxs->add(ex,0,aZ);
7318           vtxs->add(ex,bar_max,aZ);
7319         }
7320       } else  if(bar_max >1) {
7321         vtxs->add(ex,bar_min,aZ);
7322         vtxs->add(ex,1,aZ);
7323       } else {
7324         vtxs->add(ex    ,bar_min,aZ);
7325         vtxs->add(ex    ,bar_max,aZ);
7326       }
7327 
7328     }
7329 
7330     if(vtxs->number()) {
7331       m_errors_sep.add(_sep);
7332     } else {
7333       delete _sep;
7334     }
7335   }
7336 
7337   void rep_errors_I_xy(std::ostream& /*a_out*/,const style& a_style,const std::vector<rep_bin1D>& a_bins,
7338                        const rep_box& a_box_x,const rep_box& a_box_y,const std::vector<float>& a_bars,float aZ){
7339     //a_out << "debug : rep_erros_I_xy : begin :" << std::endl;
7340     separator* _sep = new separator();
7341     //_sep->setString(aID);
7342 
7343     rgba* mat = new rgba();
7344     mat->color = a_style.color;
7345     _sep->add(mat);
7346 
7347     draw_style* ds = new draw_style;
7348     ds->style.value(draw_lines);
7349     ds->line_pattern.value(a_style.line_pattern);
7350     ds->line_width.value(a_style.line_width);
7351     _sep->add(ds);
7352 
7353     vertices* vtxs = new vertices;
7354     vtxs->mode = gl::lines();
7355     _sep->add(vtxs);
7356 
7357     float xmin = a_box_x.m_pos;
7358     float dx = a_box_x.m_width;
7359     bool xlog = a_box_x.m_log;
7360 
7361     float ymin = a_box_y.m_pos;
7362     float dy = a_box_y.m_width;
7363     bool ylog = a_box_y.m_log;
7364 
7365     size_t xnbin = a_bins.size();
7366 
7367     for(size_t index=0;index<xnbin;index++) {
7368 
7369       //Need all bins modeled for fitting.
7370 
7371       float val = a_bins[index].m_val;
7372       float bar_height = a_bars[index];
7373 
7374       float bar_min = val - bar_height/2;
7375       float bar_max = val + bar_height/2;
7376 
7377       float xx = a_bins[index].m_x_min;
7378       float xe = a_bins[index].m_x_max;
7379 
7380       xx = verify_log(xx,xmin,dx,xlog);
7381       xe = verify_log(xe,xmin,dx,xlog);
7382       val = verify_log(val,ymin,dy,ylog);
7383 
7384       bar_min = verify_log(bar_min,ymin,dy,ylog);
7385       bar_max = verify_log(bar_max,ymin,dy,ylog);
7386 
7387       if(xe<0) continue;
7388       if(xx>1) continue;
7389       if(xx<0) xx = 0;
7390       if(xe>1) xe = 1;
7391       if(val<0) val = 0;
7392       if(val>1) val = 1;
7393 
7394       float ex = (xe+xx)/2;
7395       //if( (ex >=0)&&(ex <=1) ) { //FIXME : have to clip
7396 
7397       float edx = 0.3F * (xe-xx);
7398 
7399       if(bar_min >1)  {
7400         // do nothing
7401       } else  if(bar_max <0)  {
7402         // do nothing
7403       } else  if(bar_min <0) {
7404         if(bar_max >1) {
7405           vtxs->add(ex,0,aZ);
7406           vtxs->add(ex,1,aZ);
7407         } else {
7408           vtxs->add(ex,0,aZ);
7409           vtxs->add(ex,bar_max,aZ);
7410           vtxs->add(ex-edx,bar_max,aZ);
7411           vtxs->add(ex+edx,bar_max,aZ);
7412         }
7413       } else  if(bar_max >1) {
7414         vtxs->add(ex-edx,bar_min,aZ);
7415         vtxs->add(ex+edx,bar_min,aZ);
7416         vtxs->add(ex,bar_min,aZ);
7417         vtxs->add(ex,1,aZ);
7418       } else {
7419         vtxs->add(ex-edx,bar_min,aZ);
7420         vtxs->add(ex+edx,bar_min,aZ);
7421         vtxs->add(ex    ,bar_min,aZ);
7422         vtxs->add(ex    ,bar_max,aZ);
7423         vtxs->add(ex-edx,bar_max,aZ);
7424         vtxs->add(ex+edx,bar_max,aZ);
7425       }
7426 
7427     }
7428 
7429     if(vtxs->number()) {
7430       m_errors_sep.add(_sep);
7431     } else {
7432       delete _sep;
7433     }
7434   }
7435 
7436   void rep_hatch1D_xy(const style& a_style,
7437                       const std::vector<rep_bin1D>& a_bins,
7438                       const rep_box& a_box_x,const rep_box& a_box_y,float a_zz,
7439                       bool a_bar_chart){
7440     //printf("debug : tools::sg;:plotter::repHatch1D_xy : zz %g barchart %d sw %g\n",a_zz,aBarChart,a_style.stripWidth.getValue());
7441 
7442     separator* _sep = new separator;
7443 
7444     rgba* mat = new rgba();
7445     mat->color = a_style.color;
7446     _sep->add(mat);
7447 
7448     draw_style* ds = new draw_style;
7449     if(a_style.strip_width.value()==0) {
7450       ds->style = draw_lines;
7451       ds->line_pattern = line_solid;
7452       ds->line_width = a_style.line_width;
7453     } else {
7454       ds->style = draw_filled;
7455       //ds->cull_face = true;
7456     }
7457     _sep->add(ds);
7458 
7459     float xmin = a_box_x.m_pos;
7460     float dx = a_box_x.m_width;
7461     bool xlog = a_box_x.m_log;
7462 
7463     float ymin = a_box_y.m_pos;
7464     float dy = a_box_y.m_width;
7465     bool ylog = a_box_y.m_log;
7466 
7467     bool empty = true;
7468 
7469     vec3f points[5];
7470     size_t xnbin = a_bins.size();
7471     for(size_t index=0;index<xnbin;index++) {
7472       float xx = a_bins[index].m_x_min;
7473       float xe = a_bins[index].m_x_max;
7474       float yy = a_bins[index].m_v_min;
7475       float ye = a_bins[index].m_val;
7476       if(ye<yy) {
7477         yy = a_bins[index].m_val;
7478         ye = a_bins[index].m_v_min;
7479       }
7480 
7481       if(a_bar_chart) bar_chart(a_style.bar_offset.value(),a_style.bar_width.value(),xx,xe);
7482 
7483       xx = verify_log(xx,xmin,dx,xlog);
7484       xe = verify_log(xe,xmin,dx,xlog);
7485       yy = verify_log(yy,ymin,dy,ylog);
7486       ye = verify_log(ye,ymin,dy,ylog);
7487 
7488       // Clipping :
7489       if(xx>1) continue;
7490       if(xe<0) continue;
7491       if(xx<0) xx = 0;
7492       if(xe>1) xe = 1;
7493       if(yy>1) continue;
7494       if(ye<0) continue;
7495       if(yy<0) yy = 0;
7496       if(ye>1) ye = 1;
7497 
7498       points[0].set_value(xx,yy,a_zz);
7499       points[1].set_value(xe,yy,a_zz);
7500       points[2].set_value(xe,ye,a_zz);
7501       points[3].set_value(xx,ye,a_zz);
7502       points[4].set_value(xx,yy,a_zz);
7503 
7504       //FIXME : have picking a hatch picks also the bin.
7505 
7506       hatcher _hatcher;
7507       _hatcher.set_offset_point(vec3f(0,0,a_zz));
7508       _hatcher.set_angle(a_style.angle.value());
7509       _hatcher.set_spacing(a_style.spacing.value());
7510       if(!_hatcher.set_strip_width(a_style.strip_width.value())) {}
7511 
7512       bool res = _hatcher.check_polyline(points,4);
7513       if(res) res = _hatcher.compute_polyline(points,4);
7514 
7515       size_t numPoints = _hatcher.points().size();
7516       size_t numVertices = _hatcher.vertices().size();
7517       if((res) && numPoints && numVertices) {
7518 
7519           const std::vector<vec3f>& _points = _hatcher.points();
7520 
7521           if(a_style.strip_width.value()==0) {
7522 
7523             size_t ipt = 0;
7524             tools_vforcit(unsigned int,_hatcher.vertices(),itv) {
7525               vertices* vtxs = new vertices;
7526               vtxs->mode = gl::line_strip();
7527               for(size_t _index=0;_index<(*itv);_index++) {
7528                 vtxs->add(_points[ipt]);
7529                 ipt++;
7530               }
7531               _sep->add(vtxs);
7532               empty = false;
7533             }
7534 
7535           } else {
7536             size_t ipt = 0;
7537             tools_vforcit(unsigned int,_hatcher.vertices(),itv) {
7538               vertices* vtxs = new vertices;
7539               vtxs->mode = gl::triangle_fan();
7540               for(size_t _index=0;_index<(*itv);_index++) {
7541                 vtxs->add(_points[ipt]);
7542                 ipt++;
7543               }
7544               _sep->add(vtxs);
7545               empty = false;
7546             }
7547           }
7548 
7549       }
7550     }
7551     if(empty) {
7552       delete _sep;
7553     } else {
7554       m_bins_sep.add(_sep);
7555     }
7556   }
7557 
7558   void rep_points2D_xy_lines(const style& a_style,const points2D& a_points,
7559                              const rep_box& a_box_x,const rep_box& a_box_y,float a_zz){
7560     //::printf("debug : rep_points2D_xy_lines\n");
7561     float xmin = a_box_x.m_pos;
7562     float dx = a_box_x.m_width;
7563     bool xlog = a_box_x.m_log;
7564 
7565     float ymin = a_box_y.m_pos;
7566     float dy = a_box_y.m_width;
7567     bool ylog = a_box_y.m_log;
7568 
7569     separator* _sep = new separator();
7570 
7571     rgba* mat = new rgba();
7572     mat->color = a_style.color;
7573     _sep->add(mat);
7574 
7575     draw_style* ds = new draw_style;
7576     ds->style.value(draw_lines);
7577     ds->line_pattern.value(a_style.line_pattern);
7578     ds->line_width.value(a_style.line_width);
7579     _sep->add(ds);
7580 
7581     vertices* vtxs = new vertices;
7582     vtxs->mode = gl::line_strip();
7583     _sep->add(vtxs);
7584 
7585     bool empty = true;
7586 
7587     float x,y;
7588     unsigned int number = a_points.points();
7589     for(unsigned int index=0;index<number;index++) {
7590       a_points.ith_point(index,x,y);
7591       x = verify_log(x,xmin,dx,xlog);
7592       y = verify_log(y,ymin,dy,ylog);
7593       if((x<0)||(x>1)||(y<0)||(y>1)) continue;
7594       vtxs->add(x,y,a_zz);
7595       empty = false;
7596     }
7597 
7598     if(empty) {
7599       delete _sep;
7600     } else {
7601       m_points_sep.add(_sep);
7602     }
7603   }
7604 
7605   void rep_points2D_xy_curve(std::ostream& a_out,const style& a_style,const points2D& a_points,
7606                              const rep_box& a_box_x,const rep_box& a_box_y,float a_zz){
7607     //::printf("debug : rep_points2D_xy_curve\n");
7608     unsigned int number = a_points.points();
7609     if(!number) return;
7610 
7611     double* xs = new double[number];
7612     double* ys = new double[number];
7613     float x,y;
7614    {for(unsigned int index=0;index<number;index++) {
7615       a_points.ith_point(index,x,y);
7616       xs[index] = x;ys[index] = y;
7617     }}
7618     spline::cubic _spline(a_out,number,xs,ys);
7619   //spline::quintic _spline(a_out,number,xs,ys);
7620     delete [] xs;delete [] ys;
7621 
7622     float xmn = m_x_axis_data.min_value();
7623     float xmx = m_x_axis_data.max_value();
7624     unsigned int nstp = curve_number_of_points;
7625     float step = (xmx - xmn)/nstp;
7626     std::vector<vec3f> points(nstp+1);
7627     for(unsigned int ibin=0;ibin<=nstp;ibin++) {
7628       float xx = xmn + ibin * step;
7629       double val = _spline.eval(xx);
7630       points[ibin].set_value(xx,float(val),a_zz);
7631     }
7632 
7633     vertices* vtxs = new vertices;
7634     std::vector<float>& pts = vtxs->xyzs.values(); //npt*3
7635 
7636     clip_polyline_2D(points,a_box_x,a_box_y,pts);
7637     if(pts.size()) {
7638       sg::separator* separator = new sg::separator;
7639       //separator->setString(aID);
7640 
7641       rgba* mat = new rgba();
7642       mat->color = a_style.color;
7643       separator->add(mat);
7644 
7645       draw_style* ds = new draw_style;
7646       ds->style = draw_lines;
7647       ds->line_pattern = a_style.line_pattern;
7648       ds->line_width = a_style.line_width;
7649       separator->add(ds);
7650 
7651       vtxs->mode = gl::line_strip();
7652       separator->add(vtxs);
7653 
7654       m_points_sep.add(separator);
7655     } else {
7656       delete vtxs;
7657     }
7658 
7659   }
7660 
7661   void rep_points2D_xy_points(std::ostream& a_out,
7662                               const style& a_style,const points2D& a_points,
7663                               const rep_box& a_box_x,const rep_box& a_box_y,float a_zz) {
7664     float xmin = a_box_x.m_pos;
7665     float dx = a_box_x.m_width;
7666     bool xlog = a_box_x.m_log;
7667 
7668     float ymin = a_box_y.m_pos;
7669     float dy = a_box_y.m_width;
7670     bool ylog = a_box_y.m_log;
7671 
7672     separator* _sep = new separator();
7673 
7674     rgba* mat = new rgba();
7675     mat->color = a_style.color;
7676     _sep->add(mat);
7677 
7678     mf<float>* _xyzs = 0;
7679 
7680     if(a_style.modeling==modeling_markers()) {
7681       markers* _marks = new markers;
7682       _marks->size = a_style.marker_size;
7683       _marks->style = a_style.marker_style;
7684       _xyzs = &(_marks->xyzs);
7685       _sep->add(_marks);
7686 
7687     } else if(a_style.modeling==modeling_points()) {
7688       draw_style* ds = new draw_style;
7689       ds->style = draw_points;
7690       ds->point_size = a_style.point_size;
7691       _sep->add(ds);
7692 
7693       vertices* vtxs = new vertices;
7694       vtxs->mode = gl::points();
7695       _xyzs = &(vtxs->xyzs);
7696       _sep->add(vtxs);
7697     } else {
7698       a_out << "tools::sg::plotter::rep_points2D_xy_points :"
7699             << " bad modeling style " << tools::sout(a_style.modeling) << std::endl;
7700       delete _sep;
7701       return;
7702     }
7703 
7704     float x,y;
7705 
7706     // first round trip to get number of floats :
7707     size_t npts = 0;
7708    {unsigned int number = a_points.points();
7709     for(unsigned int index=0;index<number;index++) {
7710       a_points.ith_point(index,x,y);
7711       //float val = a_bins[index].m_val;
7712       x = verify_log(x,xmin,dx,xlog);
7713       y = verify_log(y,ymin,dy,ylog);
7714       if((x<0)||(x>1)||(y<0)||(y>1)) continue;
7715       npts += 3;
7716     }}
7717 
7718     _xyzs->values().resize(npts);
7719     size_t xyz_pos = 0;
7720 
7721     bool empty = true;
7722 
7723    {unsigned int number = a_points.points();
7724     for(unsigned int index=0;index<number;index++) {
7725       a_points.ith_point(index,x,y);
7726       //float val = a_bins[index].m_val;
7727       x = verify_log(x,xmin,dx,xlog);
7728       y = verify_log(y,ymin,dy,ylog);
7729       if((x<0)||(x>1)||(y<0)||(y>1)) continue;
7730       _xyzs->add_allocated(xyz_pos,x,y,a_zz);
7731       empty = false;
7732     }}
7733 
7734     if(empty) {
7735       delete _sep;
7736     } else {
7737       m_points_sep.add(_sep);
7738     }
7739   }
7740 
7741   void rep_points3D_xyz_points(std::ostream& a_out,
7742                                const style& a_style,const points3D& a_points,
7743                                const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z) {
7744     float xmin = a_box_x.m_pos;
7745     float dx = a_box_x.m_width;
7746     bool xlog = a_box_x.m_log;
7747 
7748     float ymin = a_box_y.m_pos;
7749     float dy = a_box_y.m_width;
7750     bool ylog = a_box_y.m_log;
7751 
7752     float zmin = a_box_z.m_pos;
7753     float dz = a_box_z.m_width;
7754     bool zlog = a_box_z.m_log;
7755 
7756     separator* _sep = new separator();
7757 
7758     rgba* mat = new rgba();
7759     mat->color = a_style.color;
7760     _sep->add(mat);
7761 
7762     mf<float>* _xyzs = 0;
7763 
7764     if(a_style.modeling==modeling_markers()) {
7765       markers* _marks = new markers;
7766       _marks->size = a_style.marker_size;
7767       _marks->style = a_style.marker_style;
7768       _xyzs = &(_marks->xyzs);
7769       _sep->add(_marks);
7770 
7771     } else if(a_style.modeling==modeling_points()) {
7772       draw_style* ds = new draw_style;
7773       ds->style = draw_points;
7774       ds->point_size = a_style.point_size;
7775       _sep->add(ds);
7776 
7777       vertices* vtxs = new vertices;
7778       vtxs->mode = gl::points();
7779       _xyzs = &(vtxs->xyzs);
7780       _sep->add(vtxs);
7781     } else {
7782       a_out << "tools::sg::plotter::rep_points3D_xy_points :"
7783             << " bad modeling style " << tools::sout(a_style.modeling) << std::endl;
7784       delete _sep;
7785       return;
7786     }
7787 
7788     float x,y,z;
7789 
7790     // first round trip to get number of floats :
7791     size_t npts = 0;
7792    {unsigned int number = a_points.points();
7793     for(unsigned int index=0;index<number;index++) {
7794       a_points.ith_point(index,x,y,z);
7795       //float val = a_bins[index].m_val;
7796       x = verify_log(x,xmin,dx,xlog);
7797       y = verify_log(y,ymin,dy,ylog);
7798       z = verify_log(z,zmin,dz,zlog);
7799       if((x<0)||(x>1)||(y<0)||(y>1)||(z<0)||(z>1)) continue;
7800       npts += 3;
7801     }}
7802 
7803     _xyzs->values().resize(npts);
7804     size_t xyz_pos = 0;
7805 
7806     bool empty = true;
7807 
7808    {unsigned int number = a_points.points();
7809     for(unsigned int index=0;index<number;index++) {
7810       a_points.ith_point(index,x,y,z);
7811       //float val = a_bins[index].m_val;
7812       x = verify_log(x,xmin,dx,xlog);
7813       y = verify_log(y,ymin,dy,ylog);
7814       z = verify_log(z,zmin,dz,zlog);
7815       if((x<0)||(x>1)||(y<0)||(y>1)||(z<0)||(z>1)) continue;
7816       _xyzs->add_allocated(xyz_pos,x,y,z);
7817       empty = false;
7818     }}
7819 
7820     if(empty) {
7821       delete _sep;
7822     } else {
7823       m_points_sep.add(_sep);
7824     }
7825   }
7826 
7827   void rep_bins2D_xyz_box(const style& a_style,const base_colormap& a_cmap,const std::vector<rep_bin2D>& a_bins,
7828                           const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z,float a_bmin,float /*a_bmax*/){
7829     float xmin = a_box_x.m_pos;
7830     float dx = a_box_x.m_width;
7831     bool xlog = a_box_x.m_log;
7832 
7833     float ymin = a_box_y.m_pos;
7834     float dy = a_box_y.m_width;
7835     bool ylog = a_box_y.m_log;
7836 
7837     float zmin = a_box_z.m_pos;
7838     float dz = a_box_z.m_width;
7839     bool zlog = a_box_z.m_log;
7840 
7841     painting_policy painting = a_style.painting;
7842 
7843     separator* _sep = new separator();
7844 
7845     bool empty = true;
7846     //float range = a_bmax - a_bmin;
7847     colorf clr;
7848 
7849     tools_vforcit(rep_bin2D,a_bins,it) {
7850       const rep_bin2D& rbin = *it;
7851 
7852       float xx = rbin.m_x_min;
7853       float xe = rbin.m_x_max;
7854       float yy = rbin.m_y_min;
7855       float ye = rbin.m_y_max;
7856       float val = rbin.m_val;
7857       float zz = a_bmin;
7858       float ze = val;
7859 
7860       xx = verify_log(xx ,xmin,dx  ,xlog);
7861       xe = verify_log(xe ,xmin,dx  ,xlog);
7862       yy = verify_log(yy ,ymin,dy  ,ylog);
7863       ye = verify_log(ye ,ymin,dy  ,ylog);
7864       zz = verify_log(zz ,zmin,dz  ,zlog);
7865       ze = verify_log(ze ,zmin,dz  ,zlog);
7866 
7867       // Clipping :
7868       if(xx>1) continue;
7869       if(xe<0) continue;
7870       if(xx<0) xx = 0;
7871       if(xe>1) xe = 1;
7872 
7873       if(yy>1) continue;
7874       if(ye<0) continue;
7875       if(yy<0) yy = 0;
7876       if(ye>1) ye = 1;
7877 
7878       if(zz>1) continue;
7879       if(ze<0) continue;
7880       if(zz<0) zz = 0;
7881       if(ze>1) ze = 1;
7882 
7883       if(yy>=ye) continue;
7884       if(xx>=xe) continue;
7885       if(zz>=ze) continue;
7886 
7887       separator* sep = new separator();
7888       _sep->add(sep);
7889 
7890       if(painting==painting_by_value) {
7891         a_cmap.get_color(val,clr);
7892       } else if( (painting==painting_grey_scale) ||
7893                  (painting==painting_grey_scale_inverse) ||
7894                  (painting==painting_violet_to_red) ){
7895         a_cmap.get_color(rbin.m_ratio,clr);
7896       } else {
7897         clr = a_style.color;
7898       }
7899 
7900       rgba* mat = new rgba();
7901       mat->color = clr;
7902       sep->add(mat);
7903 
7904    /*{char s[128];
7905       //::sprintf(s,"%d %d",rbin.fI,rbin.fJ);
7906       sep->setInfos(s);
7907       //::sprintf(s,"/0x%lx",(unsigned long)sep->getInfos());
7908       std::string sid = aID;
7909       sid += std::string(s);
7910       sep->setString(sid);}*/
7911 
7912       float sx = xe-xx;
7913       float sy = ye-yy;
7914       float sz = ze-zz;
7915 
7916       matrix* _tsf = new matrix;
7917       _tsf->set_translate(xx+sx/2,yy+sy/2,sz/2);
7918       sep->add(_tsf);
7919 
7920       cube* _cube = new cube;
7921       _cube->width = sx;
7922       _cube->height = sy;
7923       _cube->depth = sz;
7924       sep->add(_cube);
7925 
7926       empty = false;
7927     }
7928 
7929     if(empty) {
7930       delete _sep;
7931     } else {
7932       m_bins_sep.add(_sep);
7933     }
7934   }
7935 
7936   void rep_top_face2D_xyz(separator& a_sep,const style& a_style,const base_colormap& a_cmap,
7937                           const std::vector<rep_top_face2D>& a_faces,
7938                           const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z) {
7939     float xmin = a_box_x.m_pos;
7940     float dx = a_box_x.m_width;
7941     bool xlog = a_box_x.m_log;
7942 
7943     float ymin = a_box_y.m_pos;
7944     float dy = a_box_y.m_width;
7945     bool ylog = a_box_y.m_log;
7946 
7947     float zmin = a_box_z.m_pos;
7948     float dz = a_box_z.m_width;
7949     bool zlog = a_box_z.m_log;
7950 
7951     bool empty = true;
7952 
7953     painting_policy painting = a_style.painting;
7954 
7955     separator* _sep = new separator();
7956 
7957     //draw_style* ds = new draw_style;
7958     //ds->style = draw_filled;
7959     //ds->cull_face = true;
7960     //_sep->add(ds);
7961 
7962     atb_vertices* vtxs = new atb_vertices;
7963     vtxs->mode = gl::triangles();
7964     vtxs->do_back = true;
7965     vtxs->epsilon = 1e-6f;
7966     _sep->add(vtxs);
7967 
7968     colorf clr;
7969     vec3f nm;
7970 
7971     size_t number = a_faces.size();
7972     for(size_t index=0;index<number;index++) {
7973       float xx = a_faces[index].m_x_min;
7974       float xe = a_faces[index].m_x_max;
7975       float yy = a_faces[index].m_y_min;
7976       float ye = a_faces[index].m_y_max;
7977       float val1 = a_faces[index].m_v1;
7978       float val2 = a_faces[index].m_v2;
7979       float val3 = a_faces[index].m_v3;
7980       float val4 = a_faces[index].m_v4;
7981 
7982       float val = val1;
7983 
7984       val1 = verify_log(val1,zmin,dz,zlog);
7985       val2 = verify_log(val2,zmin,dz,zlog);
7986       val3 = verify_log(val3,zmin,dz,zlog);
7987       val4 = verify_log(val4,zmin,dz,zlog);
7988       xx = verify_log(xx,xmin,dx,xlog);
7989       xe = verify_log(xe,xmin,dx,xlog);
7990       yy = verify_log(yy,ymin,dy,ylog);
7991       ye = verify_log(ye,ymin,dy,ylog);
7992 
7993       if(val1<0) val1 = 0;
7994       if(val1>1) val1 = 1;
7995 
7996       if(val2<0) val2 = 0;
7997       if(val2>1) val2 = 1;
7998 
7999       if(val3<0) val3 = 0;
8000       if(val3>1) val3 = 1;
8001 
8002       if(val4<0) val4 = 0;
8003       if(val4>1) val4 = 1;
8004 
8005       if((xx>=0)&&(xx<=1)   &&
8006          (xe>=0)&&(xe<=1)   &&
8007          (yy>=0)&&(yy<=1)   &&
8008          (ye>=0)&&(ye<=1)  ) {
8009 
8010         if(painting==painting_by_value) {
8011           float v = (zlog?take_log(val):val);
8012           a_cmap.get_color(v,clr);
8013         } else if( (painting==painting_grey_scale) ||
8014                    (painting==painting_grey_scale_inverse) ||
8015                    (painting==painting_violet_to_red) ){
8016           a_cmap.get_color(a_faces[index].m_ratio,clr);
8017         } else {
8018           clr = a_style.color;
8019         }
8020 
8021         //if(a_style.area_style.getValue()==SoStyle::EDGED) { //OpenPAW.
8022         //}
8023 
8024         //////////////////////////////////////
8025         //////////////////////////////////////
8026         vtxs->add(xx,ye,val4);
8027         vtxs->add(xx,yy,val1);
8028         vtxs->add(xe,yy,val2);
8029 
8030         vtxs->add_color(clr);
8031         vtxs->add_color(clr);
8032         vtxs->add_color(clr);
8033 
8034         direction(xx,ye,val4,
8035                   xx,yy,val1,
8036                   xe,yy,val2,nm);
8037         nm.normalize();
8038         vtxs->add_normal(nm[0],nm[1],nm[2]);
8039         vtxs->add_normal(nm[0],nm[1],nm[2]);
8040         vtxs->add_normal(nm[0],nm[1],nm[2]);
8041 
8042         //////////////////////////////////////
8043         //////////////////////////////////////
8044         vtxs->add(xe,yy,val2);
8045         vtxs->add(xe,ye,val3);
8046         vtxs->add(xx,ye,val4);
8047 
8048         vtxs->add_rgba(clr[0],clr[1],clr[2],clr[3]);
8049         vtxs->add_rgba(clr[0],clr[1],clr[2],clr[3]);
8050         vtxs->add_rgba(clr[0],clr[1],clr[2],clr[3]);
8051 
8052         direction(xe,yy,val2,
8053                   xe,ye,val3,
8054                   xx,ye,val4,nm);
8055         nm.normalize();
8056         vtxs->add_normal(nm[0],nm[1],nm[2]);
8057         vtxs->add_normal(nm[0],nm[1],nm[2]);
8058         vtxs->add_normal(nm[0],nm[1],nm[2]);
8059 
8060         empty = false;
8061       }
8062     }
8063     if(empty) {
8064       delete _sep;
8065     } else {
8066       a_sep.add(_sep);
8067     }
8068   }
8069 
8070   void rep_top_face2D_xyz_line(const style& /*a_style*/,const std::vector<rep_top_face2D>& a_top_faces,
8071                                const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z/*,const SbString& aID*/){
8072     //::printf("debug : rep_top_face2D_xyz_line\n");
8073 
8074     float xmin = a_box_x.m_pos;
8075     float dx = a_box_x.m_width;
8076     bool xlog = a_box_x.m_log;
8077 
8078     float ymin = a_box_y.m_pos;
8079     float dy = a_box_y.m_width;
8080     bool ylog = a_box_y.m_log;
8081 
8082     float zmin = a_box_z.m_pos;
8083     float dz = a_box_z.m_width;
8084     bool zlog = a_box_z.m_log;
8085 
8086     sg::separator* separator = new sg::separator;
8087     bool empty = true;
8088 
8089     rgba* mat = new rgba();
8090     mat->color = colorf_black();
8091     separator->add(mat);
8092 
8093     draw_style* ds = new draw_style;
8094     ds->style = draw_lines;
8095     ds->line_pattern = line_solid;
8096     ds->line_width = 1;
8097     separator->add(ds);
8098 
8099     vertices* vtxs = new vertices;
8100     vtxs->mode = gl::lines();
8101     separator->add(vtxs);
8102 
8103     float zepsilon = 0.02f; //for pawex9.kumac top-left and bottom-right.
8104 
8105     size_t number = a_top_faces.size();
8106     for(size_t index=0;index<number;index++) {
8107       float xx = a_top_faces[index].m_x_min;
8108       float xe = a_top_faces[index].m_x_max;
8109       float yy = a_top_faces[index].m_y_min;
8110       float ye = a_top_faces[index].m_y_max;
8111       float val1 = a_top_faces[index].m_v1;
8112       float val2 = a_top_faces[index].m_v2;
8113       float val3 = a_top_faces[index].m_v3;
8114       float val4 = a_top_faces[index].m_v4;
8115 
8116       //float val = val1;
8117 
8118       val1 = verify_log(val1,zmin,dz,zlog);
8119       val2 = verify_log(val2,zmin,dz,zlog);
8120       val3 = verify_log(val3,zmin,dz,zlog);
8121       val4 = verify_log(val4,zmin,dz,zlog);
8122       xx = verify_log(xx,xmin,dx,xlog);
8123       xe = verify_log(xe,xmin,dx,xlog);
8124       yy = verify_log(yy,ymin,dy,ylog);
8125       ye = verify_log(ye,ymin,dy,ylog);
8126 
8127       if(val1<0) val1 = 0;
8128       if(val1>1) val1 = 1;
8129 
8130       if(val2<0) val2 = 0;
8131       if(val2>1) val2 = 1;
8132 
8133       if(val3<0) val3 = 0;
8134       if(val3>1) val3 = 1;
8135 
8136       if(val4<0) val4 = 0;
8137       if(val4>1) val4 = 1;
8138 
8139       if((xx>=0)&&(xx<=1)   &&
8140          (xe>=0)&&(xe<=1)   &&
8141          (yy>=0)&&(yy<=1)   &&
8142          (ye>=0)&&(ye<=1)  ) {
8143 
8144         vtxs->add(xx,ye,val4+zepsilon);
8145         vtxs->add(xx,yy,val1+zepsilon);
8146 
8147         vtxs->add(xx,yy,val1+zepsilon);
8148         vtxs->add(xe,yy,val2+zepsilon);
8149 
8150         vtxs->add(xe,yy,val2+zepsilon);
8151         vtxs->add(xe,ye,val3+zepsilon);
8152 
8153         vtxs->add(xe,ye,val3+zepsilon);
8154         vtxs->add(xx,ye,val4+zepsilon);
8155 
8156         empty = false;
8157 
8158       }
8159     }
8160     if(empty) {
8161       delete separator;
8162     } else {
8163       m_bins_sep.add(separator);
8164     }
8165   }
8166 
8167   void rep_top_face2D_xyz_by_level(const style& /*a_style*/,painting_policy /*a_painting*/,const base_colormap& a_cmap,
8168                                    const std::vector<rep_top_face2D>& a_top_faces,
8169                                    const rep_box& a_box_x,const rep_box& a_box_y,const rep_box& a_box_z,
8170                                    float a_bmin,float a_bmax/*,const SbString& aID*/){
8171     //::printf("debug : rep_top_face2D_xyz_by_level\n");
8172 
8173     size_t ncol = a_cmap.colorn();
8174     if(!ncol) return;
8175 
8176     float xmin = a_box_x.m_pos;
8177     float dx = a_box_x.m_width;
8178     bool xlog = a_box_x.m_log;
8179 
8180     float ymin = a_box_y.m_pos;
8181     float dy = a_box_y.m_width;
8182     bool ylog = a_box_y.m_log;
8183 
8184     float zmin = a_box_z.m_pos;
8185     float dz = a_box_z.m_width;
8186     bool zlog = a_box_z.m_log;
8187 
8188     float zz = a_bmin;
8189     zz = verify_log(zz,zmin,dz,zlog);
8190     float zmx = a_bmax;
8191     zmx = verify_log(zmx,zmin,dz,zlog);
8192 
8193     bool empty = true;
8194 
8195     sg::separator* separator = new sg::separator;
8196     //separator->setString(aID);
8197 
8198     atb_vertices* tris = new atb_vertices;
8199     tris->mode = gl::triangles();
8200     tris->do_back = true;
8201     tris->epsilon = 1e-6f;
8202     separator->add(tris);
8203 
8204     colorf _color;
8205     vec3f _point;
8206 
8207     float d_z = (zmx-zz)/ncol;
8208 
8209     size_t number = a_top_faces.size();
8210 
8211     for(size_t icol=0;icol<ncol;icol++) {
8212 
8213       //sg::separator* sep = new sg::separator;
8214       //bool sep_empty = true;
8215 
8216       _color = a_cmap.color(icol);
8217 
8218       for(size_t index=0;index<number;index++) {
8219         float xx = a_top_faces[index].m_x_min;
8220         float xe = a_top_faces[index].m_x_max;
8221         float yy = a_top_faces[index].m_y_min;
8222         float ye = a_top_faces[index].m_y_max;
8223         float val1 = a_top_faces[index].m_v1;
8224         float val2 = a_top_faces[index].m_v2;
8225         float val3 = a_top_faces[index].m_v3;
8226         float val4 = a_top_faces[index].m_v4;
8227 
8228         //float val = val1;
8229 
8230         val1 = verify_log(val1,zmin,dz,zlog);
8231         val2 = verify_log(val2,zmin,dz,zlog);
8232         val3 = verify_log(val3,zmin,dz,zlog);
8233         val4 = verify_log(val4,zmin,dz,zlog);
8234         xx = verify_log(xx,xmin,dx,xlog);
8235         xe = verify_log(xe,xmin,dx,xlog);
8236         yy = verify_log(yy,ymin,dy,ylog);
8237         ye = verify_log(ye,ymin,dy,ylog);
8238 
8239         if(val1<0) val1 = 0;
8240         if(val1>1) val1 = 1;
8241 
8242         if(val2<0) val2 = 0;
8243         if(val2>1) val2 = 1;
8244 
8245         if(val3<0) val3 = 0;
8246         if(val3>1) val3 = 1;
8247 
8248         if(val4<0) val4 = 0;
8249         if(val4>1) val4 = 1;
8250 
8251         if((xx>=0)&&(xx<=1)   &&
8252            (xe>=0)&&(xe<=1)   &&
8253            (yy>=0)&&(yy<=1)   &&
8254            (ye>=0)&&(ye<=1)  ) {
8255 
8256           //////////////////////////////////////
8257           //////////////////////////////////////
8258          {clip<vec3f> clipper;
8259           clipper.add(vec3f(xx,ye,val4));
8260           clipper.add(vec3f(xx,yy,val1));
8261           clipper.add(vec3f(xe,yy,val2));
8262           //val[n] had been z normalized.
8263           float z1 = zz+d_z*icol;
8264           float z2 = z1+d_z;
8265           plane<vec3f> plane_z_bot(vec3f(0,0,1),vec3f(0,0,z1));
8266           plane<vec3f> plane_z_top(vec3f(0,0,-1),vec3f(0,0,z2));
8267           clipper.execute(plane_z_bot);
8268           clipper.execute(plane_z_top);
8269 
8270           const std::vector<vec3f>& result = clipper.result();
8271           if(result.size()) {
8272             plane<vec3f> plane1(vec3f(xx,ye,val4),vec3f(xx,yy,val1),vec3f(xe,yy,val2));
8273             if(result.size()==3) {
8274               tools_vforcit(vec3f,result,it) {
8275                 tris->add(*it);
8276                 tris->add_color(_color);
8277                 tris->add_normal(plane1.normal());
8278               }
8279             } else {
8280               atb_vertices* vtxs = new atb_vertices; //FIXME : ouch! optimize.
8281               vtxs->mode = gl::triangle_fan();
8282               vtxs->do_back = true;
8283               vtxs->epsilon = 1e-6f;
8284               separator->add(vtxs);
8285               tools_vforcit(vec3f,result,it) {
8286                 vtxs->add(*it);
8287                 vtxs->add_color(_color);
8288                 vtxs->add_normal(plane1.normal());
8289               }
8290           }
8291             empty = false;
8292             //sep_empty = false;
8293           }}
8294 
8295           //////////////////////////////////////
8296           //////////////////////////////////////
8297          {clip<vec3f> clipper;
8298           clipper.add(vec3f(xe,yy,val2));
8299           clipper.add(vec3f(xe,ye,val3));
8300           clipper.add(vec3f(xx,ye,val4));
8301           //val[n] had been z normalized.
8302           float z1 = zz+d_z*icol;
8303           float z2 = z1+d_z;
8304           plane<vec3f> plane_z_bot(vec3f(0,0,1),vec3f(0,0,z1));
8305           plane<vec3f> plane_z_top(vec3f(0,0,-1),vec3f(0,0,z2));
8306           clipper.execute(plane_z_bot);
8307           clipper.execute(plane_z_top);
8308 
8309           const std::vector<vec3f>& result = clipper.result();
8310           if(result.size()) {
8311             plane<vec3f> plane2(vec3f(xe,yy,val2),vec3f(xe,ye,val3),vec3f(xx,ye,val4));
8312             if(result.size()==3) {
8313               tools_vforcit(vec3f,result,it) {
8314                 tris->add(*it);
8315                 tris->add_color(_color);
8316                 tris->add_normal(plane2.normal());
8317               }
8318             } else {
8319               atb_vertices* vtxs = new atb_vertices; //FIXME : ouch! optimize.
8320               vtxs->mode = gl::triangle_fan();
8321               vtxs->do_back = true;
8322               vtxs->epsilon = 1e-6f;
8323               separator->add(vtxs);
8324               tools_vforcit(vec3f,result,it) {
8325                 vtxs->add(*it);
8326                 vtxs->add_color(_color);
8327                 vtxs->add_normal(plane2.normal());
8328               }
8329             }
8330             empty = false;
8331             //sep_empty = false;
8332           }}
8333         }
8334 
8335       } //index faces
8336 
8337       //if(sep_empty) {
8338       //  delete sep;
8339       //} else {
8340       //  separator->add(sep);
8341       //}
8342 
8343     } //icol
8344 
8345     if(empty) {
8346       delete separator;
8347     } else {
8348       m_bins_sep.add(separator);
8349     }
8350   }
8351 
8352   // for OpenPAW /GRAPHICS/PRIMITIVES/TEXT
8353   // for OpenPAW /GRAPHICS/PRIMITIVES/ITX
8354   void update_primitive_text(const plottable_text& a_obj){
8355     if(a_obj.m_TEXT.empty()) return;
8356 
8357     float z = xy_depth.value()*1.1F;
8358 
8359     vec3f pos;
8360     axis_2_data_frame(vec3f(a_obj.m_X,a_obj.m_Y,z),pos); //FIXME return FALSE
8361     xx_2_yy(pos,pos);
8362 
8363     separator* sep = new separator;
8364 
8365     rgba* mat = new rgba();
8366     mat->color = a_obj.m_TXCI;
8367     sep->add(mat);
8368 
8369     matrix* _tsf = new matrix;
8370     _tsf->set_translate(pos);
8371     _tsf->mul_rotate(0,0,1,a_obj.m_ANGLE*fpi()/180.0f);
8372     _tsf->mul_scale(a_obj.m_SCALE,a_obj.m_SCALE,1);
8373     sep->add(_tsf);
8374 
8375     //SIZE is in page coordinate YSIZ.
8376     //float YSIZ = height.value();
8377     //if(YSIZ<=0) YSIZ = 1;
8378 
8379     //::printf("debug : tools::sg::plotter::update_primitive_text : %s : X %g Y %g : SCALE %g SIZE %g : pos %g %g %g\n",
8380     //    a_obj.m_TEXT.c_str(),a_obj.m_X,a_obj.m_Y,a_obj.m_SCALE,a_obj.m_SIZE,
8381     //    pos[0],pos[1],pos[2]);
8382 
8383     if(a_obj.m_text_mode==plottable_text::text_enforce_width) {  // not tested yet.
8384 
8385       vec3f pos2;
8386       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.
8387       xx_2_yy(pos2,pos2);
8388 
8389       float _width = pos2.x()-pos.x();
8390 
8391       text* _text = new text(m_ttf);
8392       _text->enforce_front_width = true;  //it will set _text->width, height.
8393       _text->front_width = _width;
8394       _text->back_visible = false;
8395 
8396       _text->encoding = encoding_PAW();
8397       _text->strings.add(a_obj.m_TEXT);
8398       _text->line_width = a_obj.m_line_width;
8399       _text->font = a_obj.m_FONT;
8400       _text->font_modeling = a_obj.m_font_modeling;
8401 
8402       if(a_obj.m_HJUST=='R') {
8403         _text->hjust = right;
8404       } else if(a_obj.m_HJUST=='C') {
8405         _text->hjust = center;
8406       } else {
8407         _text->hjust = left;
8408       }
8409       if(a_obj.m_VJUST=='T') {
8410         _text->vjust = top;
8411       } else if(a_obj.m_VJUST=='M') {
8412         _text->vjust = middle;
8413       } else {
8414         _text->vjust = bottom;
8415       }
8416 
8417       sep->add(_text);
8418 
8419     } else if(a_obj.m_text_mode==plottable_text::text_enforce_height) { // for EsbRootView neard, fard 2D plot.
8420 
8421       vec3f pos2;
8422       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.
8423       xx_2_yy(pos2,pos2);
8424 
8425       float _height = pos2.y()-pos.y();
8426 
8427       text* _text = new text(m_ttf);
8428       _text->enforce_front_height = true;  //it will set _text->width, height.
8429       _text->front_height = _height;
8430       _text->back_visible = false;  //if true, we should adapt back_area::width, height to inside text size.
8431 
8432       _text->encoding = encoding_PAW();
8433       _text->strings.add(a_obj.m_TEXT);
8434       _text->line_width = a_obj.m_line_width;
8435       _text->font = a_obj.m_FONT;
8436       _text->font_modeling = a_obj.m_font_modeling;
8437 
8438       if(a_obj.m_HJUST=='R') {
8439         _text->hjust = right;
8440       } else if(a_obj.m_HJUST=='C') {
8441         _text->hjust = center;
8442       } else {
8443         _text->hjust = left;
8444       }
8445       if(a_obj.m_VJUST=='T') {
8446         _text->vjust = top;
8447       } else if(a_obj.m_VJUST=='M') {
8448         _text->vjust = middle;
8449       } else {
8450         _text->vjust = bottom;
8451       }
8452 
8453       sep->add(_text);
8454 
8455     } else { //text_as_it (for gopaw/pagpri.cpp).
8456       _tsf->mul_scale(a_obj.m_SIZE,a_obj.m_SIZE,1);
8457 
8458       if(a_obj.m_FONT==font_hershey()) {
8459         //::printf("debug : tools::sg::plotter::update_primitive_text : hershey\n");
8460         draw_style* ds = new draw_style;
8461         ds->style = draw_lines;
8462         ds->line_pattern = line_solid;
8463         ds->line_width = a_obj.m_line_width;
8464         //ds->line_pattern = m_title_style.line_pattern;
8465         //ds->line_width = m_title_style.line_width;
8466         sep->add(ds);
8467 
8468         text_hershey* text = new text_hershey;
8469         text->encoding = encoding_PAW();
8470         text->strings.add(a_obj.m_TEXT);
8471         if(a_obj.m_HJUST=='R') {
8472           text->hjust = right;
8473         } else if(a_obj.m_HJUST=='C') {
8474           text->hjust = center;
8475         } else {
8476           text->hjust = left;
8477         }
8478         if(a_obj.m_VJUST=='T') {
8479           text->vjust = top;
8480         } else if(a_obj.m_VJUST=='M') {
8481           text->vjust = middle;
8482         } else {
8483           text->vjust = bottom;
8484         }
8485         sep->add(text);
8486 
8487       } else {
8488         //::printf("debug : tools::sg::plotter::update_primitive_text : freetype\n");
8489         base_freetype* text = base_freetype::create(m_ttf);
8490 
8491         text->font = a_obj.m_FONT;
8492         if(a_obj.m_HJUST=='R') {
8493           text->hjust = right;
8494         } else if(a_obj.m_HJUST=='C') {
8495           text->hjust = center;
8496         } else {
8497           text->hjust = left;
8498         }
8499         if(a_obj.m_VJUST=='T') {
8500           text->vjust = top;
8501         } else if(a_obj.m_VJUST=='M') {
8502           text->vjust = middle;
8503         } else {
8504           text->vjust = bottom;
8505         }
8506 
8507         text->modeling = a_obj.m_font_modeling;
8508 
8509         //text->encoding = encoding_PAW()
8510         //text->smooting = a_obj.m_SMOOTHING;
8511         //text->hinting = a_obj.m_HINTING;
8512         text->strings.add(a_obj.m_TEXT);
8513         //text->hjust.value(a_hjust);
8514         //text->vjust.value(a_vjust);
8515 
8516         sep->add(text);
8517       }
8518 
8519     } //text_mode.
8520 
8521     m_primitives_sep.add(sep);
8522   }
8523 
8524   // for OpenPAW /GRAPHICS/PRIMITIVES/BOX
8525   void PAW_hatch(int aHTYP,hatching_policy& a_policy,float& a_spacing,float& a_angle_right,float& a_angle_left) {
8526     // PAW hatching encoding (paw.pdf 1.14(1992) p 174) :
8527 
8528     a_policy = hatching_none;
8529     a_spacing = 0;
8530     a_angle_right = 0;
8531     a_angle_left = 0;
8532 
8533     int code = aHTYP;
8534     if(code==0) return;
8535 
8536     // From PAW FAQ web page.
8537     // special code from code [1,25]
8538     if(code==1) {
8539       a_policy = hatching_left_and_right;
8540       a_spacing = 0.04F;
8541       a_angle_right = 3.0F*fpi()/4.0F;
8542       a_angle_left = fpi()/4.0F;
8543       return;
8544     } else if(code==2) {
8545       a_policy = hatching_left_and_right;
8546       a_spacing = 0.08F;
8547       a_angle_right = 3.0F*fpi()/4.0F;
8548       a_angle_left = fpi()/4.0F;
8549       return;
8550     } else if(code==3) {
8551       a_policy = hatching_left_and_right;
8552       a_spacing = 1.6f*0.07F; //cooking
8553       a_angle_right = 3.0F*fpi()/4.0F;
8554       a_angle_left = fpi()/4.0F;
8555       return;
8556     } else if(code==4) {
8557       code = 354;
8558     } else if(code==5) {
8559       code = 345;
8560     } else if(code==6) {
8561       code = 359;
8562     } else if(code==7) {
8563       code = 350;
8564     } else if(code<=25) {
8565       //FIXME : seems to be done with patterns.
8566       a_policy = hatching_none;
8567       return;
8568     } else if(code<=99) {
8569       //FIXME
8570       a_policy = hatching_none;
8571       return;
8572     }
8573 
8574     //code >=100
8575 
8576     // code = ijk
8577 
8578     int i = code / 100;
8579     int j = (code - i * 100)/10;
8580     int k = code - i * 100 - j * 10;
8581 
8582     // j-hatching on rightHatchStyle :
8583     // k-hatching on leftHatchStyle :
8584 
8585     if((j==5)&&(k==5))
8586       a_policy = hatching_none;
8587     else if((j!=5)&&(k==5))
8588       a_policy = hatching_right;
8589     else if((j==5)&&(k!=5))
8590       a_policy = hatching_left;
8591     else if((j!=5)&&(k!=5))
8592       a_policy = hatching_left_and_right;
8593 
8594     unsigned int NY = 1;
8595 
8596     a_spacing = float(NY) * float(i) * 0.07F; //cooking
8597 
8598     if(j!=5) {
8599       float angle = float(j==4?45:j*10);
8600       angle = 180.0F - angle;
8601       angle *= fpi() / 180.0F;
8602 
8603       a_angle_right = angle;
8604     }
8605 
8606     if(k!=5) {
8607       float angle = float(k==4?45:k*10);
8608       angle *= fpi() / 180.0F;
8609       a_angle_left = angle;
8610     }
8611 
8612   }
8613 
8614   void rep_box_hatch(separator& a_parent,float a_spacing,float a_angle,float a_strip_width,
8615                      float xx,float yy,float xe,float ye,float a_zz){
8616 
8617     //printf("debug : SoPlotter::repHatch1D_xy : zz %g\n",a_zz);
8618     sg::separator* separator = new sg::separator;
8619 
8620     bool empty = true;
8621 
8622     vec3f points[5];
8623 
8624     points[0].set_value(xx,yy,a_zz);
8625     points[1].set_value(xe,yy,a_zz);
8626     points[2].set_value(xe,ye,a_zz);
8627     points[3].set_value(xx,ye,a_zz);
8628     points[4].set_value(xx,yy,a_zz);
8629 
8630     //We can have multiple hatching for a bins ; have a separator :
8631     hatcher _hatcher;
8632     _hatcher.set_offset_point(vec3f(0,0,a_zz));
8633     _hatcher.set_angle(a_angle);
8634     _hatcher.set_spacing(a_spacing);
8635     if(!_hatcher.set_strip_width(a_strip_width)) {}
8636 
8637     bool res = _hatcher.check_polyline(points,4);
8638     if(res) res = _hatcher.compute_polyline(points,4);
8639 
8640     size_t numPoints = _hatcher.points().size();
8641     size_t numVertices = _hatcher.vertices().size();
8642     if((res) && numPoints && numVertices) {
8643 
8644       const std::vector<vec3f>& _points = _hatcher.points();
8645 
8646       if(a_strip_width==0) {
8647         size_t ipt = 0;
8648         tools_vforcit(unsigned int,_hatcher.vertices(),itv) {
8649           vertices* vtxs = new vertices;
8650           vtxs->mode = gl::line_strip();
8651           for(size_t index=0;index<(*itv);index++) {
8652             vtxs->add(_points[ipt]);
8653             ipt++;
8654                 }
8655           separator->add(vtxs);
8656           empty = false;
8657         }
8658 
8659       } else {
8660         size_t ipt = 0;
8661         tools_vforcit(unsigned int,_hatcher.vertices(),itv) {
8662           vertices* vtxs = new vertices;
8663           vtxs->mode = gl::triangle_fan();
8664           for(size_t index=0;index<(*itv);index++) {
8665             vtxs->add(_points[ipt]);
8666             ipt++;
8667           }
8668           separator->add(vtxs);
8669           empty = false;
8670         }
8671       }
8672 
8673       empty = false;
8674     }
8675 
8676     if(empty) {
8677       delete separator;
8678     } else {
8679       a_parent.add(separator);
8680     }
8681   }
8682 
8683   void update_primitive_box(std::ostream& a_out,const plottable_box& a_obj){
8684 
8685     float z = xy_depth.value()*1.1F;
8686 
8687     vec3f pos1;
8688     axis_2_data_frame(vec3f(a_obj.m_X1,a_obj.m_Y1,z),pos1);
8689     xx_2_yy(pos1,pos1);
8690 
8691     vec3f pos2;
8692     axis_2_data_frame(vec3f(a_obj.m_X2,a_obj.m_Y2,z),pos2);
8693     xx_2_yy(pos2,pos2);
8694 
8695     z = pos1[2];
8696 
8697 //    ::printf("debug : tools::sg::plotter::update_primitive_box : FAIS %d : %g %g %g : %g %g %g\n",a_obj.m_FAIS,
8698 //        pos1.x(),pos1.y(),pos1.z(),pos2.x(),pos2.y(),pos2.z());
8699 
8700     if(a_obj.m_FAIS==plottable_box::HOLLOW) {
8701 
8702       separator* sep = new separator;
8703 
8704       rgba* mat = new rgba();
8705       mat->color = a_obj.m_PLCI;
8706       sep->add(mat);
8707 
8708       draw_style* ds = new draw_style;
8709       ds->style = draw_lines;
8710       ds->line_pattern = line_solid;
8711       ds->line_width = a_obj.m_LWID;
8712       sep->add(ds);
8713 
8714       vertices* vtxs = new vertices;
8715       vtxs->mode = gl::line_strip();
8716       sep->add(vtxs);
8717 
8718       vtxs->add(pos1[0],pos1[1],z);
8719       vtxs->add(pos2[0],pos1[1],z);
8720       vtxs->add(pos2[0],pos2[1],z);
8721       vtxs->add(pos1[0],pos2[1],z);
8722       vtxs->add(pos1[0],pos1[1],z);
8723 
8724       m_primitives_sep.add(sep);
8725 
8726     } else if(a_obj.m_FAIS==plottable_box::SOLID) {
8727       separator* sep = new separator;
8728 
8729       rgba* mat = new rgba();
8730       mat->color = a_obj.m_FACI;
8731       sep->add(mat);
8732 
8733       draw_style* ds = new draw_style;
8734       ds->style = draw_filled;
8735       sep->add(ds);
8736 
8737       vertices* vtxs = new vertices;
8738       vtxs->mode = gl::triangle_fan();
8739       sep->add(vtxs);
8740 
8741       vtxs->add(pos1[0],pos1[1],z);
8742       vtxs->add(pos2[0],pos1[1],z);
8743       vtxs->add(pos2[0],pos2[1],z);
8744       vtxs->add(pos1[0],pos2[1],z);
8745 
8746       m_primitives_sep.add(sep);
8747 
8748     } else if(a_obj.m_FAIS==plottable_box::HATCHED) {
8749 
8750      {separator* sep = new separator;
8751 
8752       rgba* mat = new rgba();
8753       mat->color = a_obj.m_FACI;
8754       sep->add(mat);
8755 
8756       hatching_policy hatching;
8757       float spacing;
8758       float angle_right;
8759       float angle_left;
8760       PAW_hatch(a_obj.m_FASI,hatching,spacing,angle_right,angle_left);
8761       float stripWidth = 0;
8762 
8763       if((hatching==hatching_right)||((hatching==hatching_left_and_right))) {
8764         rep_box_hatch(*sep,spacing,angle_right,stripWidth,pos1[0],pos1[1],pos2[0],pos2[1],z);
8765       }
8766       if((hatching==hatching_left)||((hatching==hatching_left_and_right))) {
8767         rep_box_hatch(*sep,spacing,angle_left,stripWidth,pos1[0],pos1[1],pos2[0],pos2[1],z);
8768       }
8769 
8770       if(hatching==hatching_none) {
8771         draw_style* ds = new draw_style;
8772         ds->style = draw_filled;
8773         sep->add(ds);
8774         vertices* vtxs = new vertices;
8775         vtxs->mode = gl::triangle_fan();
8776         sep->add(vtxs);
8777         vtxs->add(pos1[0],pos1[1],z);
8778         vtxs->add(pos2[0],pos1[1],z);
8779         vtxs->add(pos2[0],pos2[1],z);
8780         vtxs->add(pos1[0],pos2[1],z);
8781       }
8782 
8783       m_primitives_sep.add(sep);}
8784 
8785       if(a_obj.m_BORD) {
8786         separator* sep = new separator;
8787         rgba* mat = new rgba();
8788         mat->color = a_obj.m_PLCI;
8789         sep->add(mat);
8790 
8791         draw_style* ds = new draw_style;
8792         ds->style = draw_lines;
8793         ds->line_pattern = line_solid;
8794         ds->line_width = 1;
8795         sep->add(ds);
8796 
8797         vertices* vtxs = new vertices;
8798         vtxs->mode = gl::line_strip();
8799         sep->add(vtxs);
8800 
8801         z *= 1.01F;
8802         vtxs->add(pos1[0],pos1[1],z);
8803         vtxs->add(pos2[0],pos1[1],z);
8804         vtxs->add(pos2[0],pos2[1],z);
8805         vtxs->add(pos1[0],pos2[1],z);
8806         vtxs->add(pos1[0],pos1[1],z);
8807 
8808         m_primitives_sep.add(sep);
8809       }
8810 
8811     } else if(a_obj.m_FAIS==plottable_box::PATTERN) {
8812       a_out << "tools::sg::plotter::update_plottable_box FAIS PATTERN not yet handled." << std::endl;
8813     }
8814 
8815   }
8816 
8817   void update_primitive_ellipse(std::ostream& a_out,const plottable_ellipse& a_obj){
8818 
8819     float z = xy_depth.value()*1.1F;
8820 
8821     vec3f pos;
8822     axis_2_data_frame(vec3f(a_obj.m_X,a_obj.m_Y,z),pos);
8823     xx_2_yy(pos,pos);
8824 
8825     vec3f pos2;
8826     axis_2_data_frame(vec3f(a_obj.m_X+a_obj.m_R1,a_obj.m_Y+a_obj.m_R2,z),pos2);
8827     xx_2_yy(pos2,pos2);
8828 
8829     float rx = pos2[0]-pos[0];
8830     float ry = pos2[1]-pos[1];
8831 
8832     z = pos[2];
8833 
8834     //::printf("debug : tools::sg::plotter::update_primitive_ellipse : FAIS %d : %g %g %g : %g %g\n",a_obj.m_FAIS,
8835     //         pos.x(),pos.y(),pos.z(),rx,ry);
8836 
8837     if(a_obj.m_FAIS==plottable_ellipse::HOLLOW) {
8838 
8839       separator* sep = new separator;
8840 
8841       matrix* _tsf = new matrix;
8842       _tsf->set_translate(pos);
8843       sep->add(_tsf);
8844 
8845       rgba* mat = new rgba();
8846       mat->color = a_obj.m_PLCI;
8847       sep->add(mat);
8848 
8849       draw_style* ds = new draw_style;
8850       ds->style = draw_lines;
8851       ds->line_pattern = line_solid;
8852       ds->line_width = a_obj.m_LWID;
8853       sep->add(ds);
8854 
8855       ellipse* _ellipse = new ellipse;
8856       _ellipse->rx = rx;
8857       _ellipse->ry = ry;
8858       sep->add(_ellipse);
8859 
8860       m_primitives_sep.add(sep);
8861 
8862 /*
8863     } else if(a_obj.m_FAIS==plottable_ellipse::SOLID) {
8864       separator* sep = new separator;
8865 
8866       rgba* mat = new rgba();
8867       mat->color = a_obj.m_FACI;
8868       sep->add(mat);
8869 
8870       draw_style* ds = new draw_style;
8871       ds->style = draw_filled;
8872       sep->add(ds);
8873 
8874       vertices* vtxs = new vertices;
8875       vtxs->mode = gl::triangle_fan();
8876       sep->add(vtxs);
8877 
8878       vtxs->add(pos1[0],pos1[1],z);
8879       vtxs->add(pos2[0],pos1[1],z);
8880       vtxs->add(pos2[0],pos2[1],z);
8881       vtxs->add(pos1[0],pos2[1],z);
8882 
8883       m_primitives_sep.add(sep);
8884 
8885     } else if(a_obj.m_FAIS==plottable_ellipse::HATCHED) {
8886 
8887      {separator* sep = new separator;
8888 
8889       rgba* mat = new rgba();
8890       mat->color = a_obj.m_FACI;
8891       sep->add(mat);
8892 
8893       hatching_policy hatching;
8894       float spacing;
8895       float angle_right;
8896       float angle_left;
8897       PAW_hatch(a_obj.m_FASI,hatching,spacing,angle_right,angle_left);
8898       float stripWidth = 0;
8899 
8900       if((hatching==hatching_right)||((hatching==hatching_left_and_right))) {
8901         rep_box_hatch(*sep,spacing,angle_right,stripWidth,pos1[0],pos1[1],pos2[0],pos2[1],z);
8902       }
8903       if((hatching==hatching_left)||((hatching==hatching_left_and_right))) {
8904         rep_box_hatch(*sep,spacing,angle_left,stripWidth,pos1[0],pos1[1],pos2[0],pos2[1],z);
8905       }
8906 
8907       if(hatching==hatching_none) {
8908         draw_style* ds = new draw_style;
8909         ds->style = draw_filled;
8910         sep->add(ds);
8911         vertices* vtxs = new vertices;
8912         vtxs->mode = gl::triangle_fan();
8913         sep->add(vtxs);
8914         vtxs->add(pos1[0],pos1[1],z);
8915         vtxs->add(pos2[0],pos1[1],z);
8916         vtxs->add(pos2[0],pos2[1],z);
8917         vtxs->add(pos1[0],pos2[1],z);
8918       }
8919 
8920       m_primitives_sep.add(sep);}
8921 
8922       if(a_obj.m_BORD) {
8923         separator* sep = new separator;
8924         rgba* mat = new rgba();
8925         mat->color = a_obj.m_PLCI;
8926         sep->add(mat);
8927 
8928         draw_style* ds = new draw_style;
8929         ds->style = draw_lines;
8930         ds->line_pattern = line_solid;
8931         ds->line_width = 1;
8932         sep->add(ds);
8933 
8934         vertices* vtxs = new vertices;
8935         vtxs->mode = gl::line_strip();
8936         sep->add(vtxs);
8937 
8938         z *= 1.01F;
8939         vtxs->add(pos1[0],pos1[1],z);
8940         vtxs->add(pos2[0],pos1[1],z);
8941         vtxs->add(pos2[0],pos2[1],z);
8942         vtxs->add(pos1[0],pos2[1],z);
8943         vtxs->add(pos1[0],pos1[1],z);
8944 
8945         m_primitives_sep.add(sep);
8946       }
8947 
8948     } else if(a_obj.m_FAIS==plottable_ellipse::PATTERN) {
8949       a_out << "tools::sg::plotter::update_plottable_box FAIS PATTERN not yet handled." << std::endl;
8950 */
8951     } else {
8952       a_out << "tools::sg::plotter::update_plottable_box FAIS " << a_obj.m_FAIS << " not yet handled." << std::endl;
8953     }
8954 
8955   }
8956 
8957   void update_primitive_img(std::ostream& /*a_out*/,const plottable_img& a_obj){
8958 
8959     float z = xy_depth.value()*1.1F;
8960 
8961     vec3f pos;
8962     axis_2_data_frame(vec3f(a_obj.m_X,a_obj.m_Y,z),pos);
8963     xx_2_yy(pos,pos);   //pos = center of image in axes coordinates.
8964     z = pos[2];
8965 
8966     vec3f top;
8967     axis_2_data_frame(vec3f(0,a_obj.m_Y+a_obj.m_HEIGHT*0.5f,0),top);
8968     xx_2_yy(top,top);  //top = (o,y-top)  of image in axes coordinates.
8969     float scale = 2.0f*(top[1]-pos[1]);
8970     //float scale = a_obj.m_HEIGHT; //m_HEIGHT is then in page coordinate YSIZ.
8971 
8972     const img<byte>& img = a_obj.m_img;
8973 
8974   //::printf("debug : tools::sg::plotter::update_primitive_img : %d %d %d : %g %g %g : %g : %g %g\n",
8975   //    img.width(),img.height(),img.bpp(),
8976   //    pos.x(),pos.y(),pos.z(),a_obj.m_HEIGHT,a_obj.m_THETA,a_obj.m_PHI);
8977 
8978     separator* sep = new separator;
8979 
8980     rgba* mat = new rgba();
8981     mat->color = colorf_white();
8982     sep->add(mat);
8983 
8984     normal* nm = new normal;
8985     sep->add(nm);
8986 
8987     matrix* _tsf = new matrix;
8988     _tsf->set_translate(pos);
8989     _tsf->mul_rotate(0,1,0,a_obj.m_THETA*fpi()/180.0f);
8990     _tsf->mul_rotate(0,0,1,a_obj.m_PHI*fpi()/180.0f);
8991     _tsf->mul_scale(scale,scale,1);
8992     sep->add(_tsf);
8993 
8994     tex_rect* _img = new tex_rect();
8995     _img->img = img;
8996     sep->add(_img);
8997 
8998     m_primitives_sep.add(sep);
8999 
9000   }
9001 
9002 protected: //etc
9003   // background is at z = 0.
9004   // last z items are text in infos, legend boxes that should be at xy_depth().
9005 
9006   float _zoffset() const {
9007     // first data plane is at _zoffset.
9008     // last one at m_plottables.size()*_zoffset = xy_depth.value()-_zoffset().
9009     return xy_depth.value()/(float(m_plottables.size())+1.0f);
9010   }
9011   float _zaxis() const {return _zoffset();}
9012   float _zgrid() const {return xy_depth.value()-_zoffset()*0.5f;}
9013   float _ztext() const {return 0.01f;} //if text back is visible else 0. (sf<float> zfront ?)
9014   float _zscale_text() const {return _zoffset()*0.4f/_ztext();} //title and infos boxes thickness.
9015   float _zinfos() const {return xy_depth.value()-_zoffset()*0.4f;} //in front _zgrid
9016   float _zhatch() const {return _zoffset()*0.25f;}
9017   float _zerrors() const {return _zoffset()*0.5f;}
9018 
9019   //static void LIST_SET(vec3f a_list[],unsigned int a_index,float x,float y,float z) {a_list[a_index].set_value(x,y,z);}
9020 
9021   static float take_log(float a_x){
9022     if(a_x<=0) {
9023       return -FLT_MAX;
9024     } else {
9025       return flog10(a_x);
9026     }
9027   }
9028 
9029   static float verify_log(float a_val,float a_min,float a_dx,bool a_log){
9030     if(a_log) {
9031       if(a_val>0.0F) {
9032         return (flog10(a_val) - a_min)/a_dx;
9033       } else { // Return a negative large number :
9034         //return -FLT_MAX;
9035         return -100;
9036       }
9037     } else {
9038       // Simple protection against value that could exceed a float :
9039       if(a_val>(a_min+100.0F * a_dx)) return 100;
9040       if(a_val<(a_min-100.0F * a_dx)) return -100;
9041       // Rescale :
9042       return (a_val - a_min)/a_dx;
9043     }
9044   }
9045 
9046   static float verify_log_inv(float a_val,float a_min,float a_dx,bool a_log){
9047    if(a_log) {
9048       return fpow(10,a_val*a_dx+a_min);
9049     } else {
9050       return a_val*a_dx+a_min;
9051     }
9052   }
9053 
9054   style* merge_bins_style(unsigned int a_index,plottable&) {
9055     style& _style = bins_style(a_index);
9056     //uuu merge with a_p.infos().
9057     return new style(_style);
9058   }
9059 
9060   style* merge_left_hatch_style(unsigned int a_index,plottable&) {
9061     style& _style = left_hatch_style(a_index);
9062     //uuu merge with a_p.infos().
9063     return new style(_style);
9064   }
9065 
9066   style* merge_right_hatch_style(unsigned int a_index,plottable&) {
9067     style& _style = right_hatch_style(a_index);
9068     //uuu merge with a_p.infos().
9069     return new style(_style);
9070   }
9071 
9072   style* merge_errors_style(unsigned int a_index,plottable&) {
9073     style& _style = errors_style(a_index);
9074     //uuu merge with a_p.infos().
9075     return new style(_style);
9076   }
9077 
9078   style* merge_func_style(unsigned int a_index,plottable&) {
9079     style& _style = func_style(a_index);
9080     //uuu merge with a_p.infos().
9081     return new style(_style);
9082   }
9083 
9084   style* merge_points_style(unsigned int a_index,plottable&) {
9085     style& _style = points_style(a_index);
9086     //uuu merge with a_p.infos().
9087     return new style(_style);
9088   }
9089 
9090 /*
9091   text_style* merge_legend_style(unsigned int a_index,plottable& a_p) {
9092     if(a_index>=m_legend_style.size()) return new text_style();
9093     return new text_style(m_legend_style[a_index]);
9094     //uuu merge with a_p.infos().
9095   }
9096 */
9097 
9098   shape_type get_shape() const {
9099     if(!shape_automated) return shape.value();
9100 
9101     // Guess XY or XYZ shape :
9102   /*if(f_binsList.size()) { // major bins compells shape type.
9103       if(f_binsList[0]->getDimension()==1) {
9104         return XY;
9105       } else if(f_binsList[0]->getDimension()==2) {
9106         return XY; //lego is not the default.
9107       } else {
9108         return XYZ;
9109       }
9110     } else if(f_pointsList.size()) { // major points compells shape type.
9111       if(f_pointsList[0]->getDimension()==1) { //?
9112         return XY;
9113       } else if(f_pointsList[0]->getDimension()==2) {
9114         return XY;
9115       } else {
9116         return XYZ;
9117       }
9118     } else if(f_functionList.size()) { // major function compell shape type.
9119       if(f_functionList[0]->getDimension()==1) {
9120         return XY;
9121       } else {
9122         return XYZ;
9123       }
9124     } else*/ {
9125       return xy; //Default.
9126     }
9127   }
9128 
9129   void clear_plottables() {
9130     //unsigned int objn = m_plottables.size();
9131    {std::vector<plottable*>::iterator it;
9132     for(it=m_plottables.begin();it!=m_plottables.end();++it) delete *it;
9133     m_plottables.clear();}
9134 
9135     /*
9136     if(objn) {
9137       // If a title (logScale) had been given on some axis,
9138       // it is probably no more pertinent for further data.
9139       if(xAxisEnforced.value()==false)  {
9140         m_x_axis.title.setValue("");
9141         xAxisLogScale.setValue(false);
9142       }
9143       if(yAxisEnforced.value()==false)  {
9144         m_y_axis.title.setValue("");
9145         yAxisLogScale.setValue(false);
9146       }
9147       if(zAxisEnforced.value()==false)  {
9148         m_z_axis.title.setValue("");
9149         zAxisLogScale.setValue(false);
9150       }
9151     }
9152     */
9153 
9154     touch();
9155   }
9156   void clear_primitives() {
9157    {std::vector<plotprim*>::iterator it;
9158     for(it=m_primitives.begin();it!=m_primitives.end();++it) delete *it;
9159     m_primitives.clear();}
9160     touch();
9161   }
9162 
9163   void clear_todels() {m_todel_group.clear();}
9164 
9165   bool first_bins(bins1D*& a_1,bins2D*& a_2) const {
9166     tools_vforcit(plottable*,m_plottables,it) {
9167       plottable* object = *it;
9168       if(!object) continue;
9169       if(bins1D* b1 = safe_cast<plottable,bins1D>(*object)) {
9170         a_1 = b1;
9171         a_2 = 0;
9172         return true;
9173       } else if(bins2D* b2 = safe_cast<plottable,bins2D>(*object)) {
9174         a_1 = 0;
9175         a_2 = b2;
9176         return true;
9177       }
9178     }
9179     a_1 = 0;
9180     a_2 = 0;
9181     return false;
9182   }
9183 
9184   bool first_func(func1D*& a_1,func2D*& a_2) const {
9185     tools_vforcit(plottable*,m_plottables,it) {
9186       plottable* object = *it;
9187       if(!object) continue;
9188       if(func1D* f1 = safe_cast<plottable,func1D>(*object)) {
9189         a_1 = f1;
9190         a_2 = 0;
9191         return true;
9192       } else if(func2D* f2 = safe_cast<plottable,func2D>(*object)) {
9193         a_1 = 0;
9194         a_2 = f2;
9195         return true;
9196       }
9197     }
9198     a_1 = 0;
9199     a_2 = 0;
9200     return false;
9201   }
9202 
9203   bool first_points(points2D*& a_2,points3D*& a_3) const {
9204     tools_vforcit(plottable*,m_plottables,it) {
9205       plottable* object = *it;
9206       if(!object) continue;
9207       if(points2D* p2 = safe_cast<plottable,points2D>(*object)) {
9208         a_2 = p2;
9209         a_3 = 0;
9210         return true;
9211       } else if(points3D* p3 = safe_cast<plottable,points3D>(*object)) {
9212         a_2 = 0;
9213         a_3 = p3;
9214         return true;
9215       }
9216     }
9217     a_2 = 0;
9218     a_3 = 0;
9219     return false;
9220   }
9221 
9222   void clear_sg() {
9223     m_bins_sep.clear();
9224     m_errors_sep.clear();
9225     m_func_sep.clear();
9226     m_points_sep.clear();
9227   }
9228 
9229   void DUMP_UPDATE_WHAT(std::ostream&,const std::string&) {}
9230 /*
9231   void DUMP_UPDATE_WHAT(std::ostream& a_out,const std::string& a_msg) {
9232     a_out << "tools::sg::plotter :"
9233           << " " << a_msg
9234           << std::endl;
9235   }
9236 */
9237 
9238   static void add_pt(std::vector<float>& a_pts,float a_x,float a_y,float a_z){
9239     a_pts.push_back(a_x);
9240     a_pts.push_back(a_y);
9241     a_pts.push_back(a_z);
9242   }
9243 
9244   static void clip_points_2D(const std::vector<vec3f>& a_points,
9245                              const rep_box& a_box_x,const rep_box& a_box_y,std::vector<float>& a_pts) {
9246     float xmin = a_box_x.m_pos;
9247     float dx = a_box_x.m_width;
9248     bool xlog = a_box_x.m_log;
9249 
9250     float ymin = a_box_y.m_pos;
9251     float dy = a_box_y.m_width;
9252     bool ylog = a_box_y.m_log;
9253 
9254     a_pts.clear();
9255 
9256     float xx,yy,zz;
9257     tools_vforcit(vec3f,a_points,it) {
9258       const vec3f& _point = *it;
9259       xx = _point[0];
9260       yy = _point[1];
9261       zz = _point[2];
9262       xx = verify_log(xx,xmin,dx,xlog);
9263       yy = verify_log(yy,ymin,dy,ylog);
9264       if((xx>=0)&&(xx<=1)&&(yy>=0)&&(yy<=1)) add_pt(a_pts,xx,yy,zz);
9265     }
9266   }
9267 
9268   static void clip_polyline_2D(const std::vector<vec3f>& a_points,
9269                                const rep_box& a_box_x,const rep_box& a_box_y,std::vector<float>& a_pts) {
9270     //  Clip line in a_box_x, a_box_y.
9271 
9272     //NOTE : it is not a general algorithm.
9273     //       It is assumed that a_points are ordered with increasing x.
9274     //       And the algorithm clips against up and bottom BoxY lines.
9275     //       (Use clip<float> for a more general algorithm ?)
9276 
9277     float xmin = a_box_x.m_pos;
9278     float dx = a_box_x.m_width;
9279     bool xlog = a_box_x.m_log;
9280 
9281     float ymin = a_box_y.m_pos;
9282     float dy = a_box_y.m_width;
9283     bool ylog = a_box_y.m_log;
9284 
9285     a_pts.clear();
9286 
9287     float xprev = 0;
9288     float yprev = 0;
9289 
9290    {unsigned int index = 0;
9291     std::vector<vec3f>::const_iterator it;
9292     for(it=a_points.begin();it!=a_points.end();++it,index++) {
9293       const vec3f& _point = *it;
9294       float xx = _point[0];
9295       float yy = _point[1];
9296       float zz = _point[2];
9297       //add_pt(a_pts,xx,yy,zz);continue; //debug
9298       xx = verify_log(xx,xmin,dx,xlog);
9299       yy = verify_log(yy,ymin,dy,ylog);
9300       if((xx>=0)&&(xx<=1) ) {
9301         if(yy>1) {
9302           if(index==0) {
9303             add_pt(a_pts,xx,1,zz);
9304           } else {
9305             if(yprev>1) {
9306               add_pt(a_pts,xx,1,zz);
9307             } else if(yprev<0) {
9308               float a = (yy - yprev)/(xx - xprev);
9309               float b = yy - a * xx;
9310               add_pt(a_pts,-b/a,0,zz);
9311               add_pt(a_pts,(1 - b)/a,1,zz);
9312               add_pt(a_pts,xx,1,zz);
9313             } else {
9314               float a = (yy - yprev)/(xx - xprev);
9315               float b = yy - a * xx;
9316               add_pt(a_pts,(1 - b)/a,1,zz);
9317               add_pt(a_pts,xx,1,zz);
9318             }
9319           }
9320         } else if (yy < 0) {
9321           if(index==0) {
9322             add_pt(a_pts,xx,0,zz);
9323           } else {
9324             if(yprev<0) {
9325               add_pt(a_pts,xx,0,zz);
9326             } else if(yprev>1) {
9327               float a = (yy - yprev)/(xx - xprev);
9328               float b = yy - a * xx;
9329               add_pt(a_pts,(1 - b)/a,1,zz);
9330               add_pt(a_pts,-b/a,0,zz);
9331               add_pt(a_pts,xx,0,zz);
9332             } else {
9333               float a = (yy - yprev)/(xx - xprev);
9334               float b = yy - a * xx;
9335               add_pt(a_pts,-b/a,0,zz);
9336               add_pt(a_pts,xx,0,zz);
9337              }
9338           }
9339         } else {
9340           if(index==0) {
9341             add_pt(a_pts,xx,yy,zz);
9342           } else if( (yprev>1) || (yprev<0) ) {
9343             // interpolate :
9344             float a = (yy - yprev)/(xx - xprev);
9345             float b = yy - a * xx;
9346             if(yprev>1) {
9347               add_pt(a_pts,(1 - b)/a,1,zz);
9348             } else {
9349               add_pt(a_pts,-b/a,0,zz);
9350             }
9351             add_pt(a_pts,xx,yy,zz);
9352           } else {
9353             add_pt(a_pts,xx,yy,zz);
9354           }
9355         }
9356       }
9357       xprev = xx;
9358       yprev = yy;
9359     }}
9360   }
9361 
9362   bool sto(const std::string& a_s,vec2f& a_v) {
9363     std::vector<std::string> ws;
9364     words(a_s," ",false,ws);
9365     if(ws.size()!=2) return false;
9366     float x = 0;
9367     if(!to<float>(ws[0],x)) return false;
9368     float y = 0;
9369     if(!to<float>(ws[1],x)) return false;
9370     a_v.set_value(x,y);
9371     return true;
9372   }
9373 
9374   bool sto(const std::string& a_s,unit_type& a_v) {
9375     if(a_s=="percent") {a_v = unit_percent;return true;}
9376     else if(a_s=="axis") {a_v = unit_axis;return true;}
9377     return false;
9378   }
9379 
9380   void clear_cmaps() {
9381    {std::vector<base_colormap*>::iterator it;
9382     for(it=m_bins_cmaps.begin();it!=m_bins_cmaps.end();++it) delete *it;
9383     m_bins_cmaps.clear();}
9384 
9385    {std::vector<base_colormap*>::iterator it;
9386     for(it=m_points_cmaps.begin();it!=m_points_cmaps.end();++it) delete *it;
9387     m_points_cmaps.clear();}
9388 
9389    {std::vector<base_colormap*>::iterator it;
9390     for(it=m_func_cmaps.begin();it!=m_func_cmaps.end();++it) delete *it;
9391     m_func_cmaps.clear();}
9392   }
9393 
9394   void bar_chart(float a_bar_offset,float a_bar_width,
9395                  float& a_beg,float& a_end){
9396     float xe = (a_end - a_beg)*a_bar_offset;
9397     float xw = (a_end - a_beg)*a_bar_width;
9398     a_end = a_beg + xe + xw;
9399     a_beg = a_beg + xe;
9400   }
9401 
9402 protected:
9403   const base_freetype& m_ttf;
9404 protected: //fields for skeleton.
9405   group m_group;
9406 
9407   separator m_background_sep;
9408 
9409   separator m_cmap_sep;
9410   matrix m_cmap_matrix;
9411   separator m_cmap_cells_sep;
9412   matrix m_cmap_axis_matrix;
9413   sg::axis m_cmap_axis;
9414 
9415   separator m_infos_title_sep;
9416   separator m_infos_sep;
9417   separator m_legend_sep;
9418   separator m_title_box_sep;
9419 
9420   matrix m_tsf;
9421   matrix m_layout;
9422 
9423   separator m_title_sep;
9424 
9425   separator m_x_axis_sep;
9426   matrix m_x_axis_matrix;
9427   sg::axis m_x_axis;
9428 
9429   separator m_y_axis_sep;
9430   matrix m_y_axis_matrix;
9431   sg::axis m_y_axis;
9432 
9433   separator m_z_axis_sep;
9434   matrix m_z_axis_matrix;
9435   sg::axis m_z_axis;
9436 
9437   separator m_grid_sep;
9438 
9439   separator m_data_sep;
9440   torche m_data_light;
9441   matrix m_data_matrix;
9442   separator m_bins_sep;
9443   separator m_errors_sep;
9444   separator m_func_sep;
9445   separator m_points_sep;
9446   separator m_inner_frame_sep;
9447   separator m_primitives_sep;
9448   separator m_etc_sep;
9449 
9450 protected: //fields
9451   shape_type m_shape;
9452 
9453   data_axis m_x_axis_data;
9454   data_axis m_y_axis_data;
9455   data_axis m_z_axis_data;
9456 
9457   std::vector<plottable*> m_plottables; //it has ownership.
9458 
9459   std::vector<style> m_bins_style;
9460   std::vector<style> m_errors_style;
9461   std::vector<style> m_func_style;
9462   std::vector<style> m_points_style;
9463   std::vector<style> m_left_hatch_style;
9464   std::vector<style> m_right_hatch_style;
9465   std::vector<style> m_legend_style;
9466 
9467   text_style m_title_style;
9468   text_style m_infos_style;
9469   text_style m_title_box_style;
9470   style m_background_style;
9471   style m_wall_style; //for gopaw.
9472   style m_inner_frame_style;
9473   style m_grid_style;
9474 
9475 protected:
9476   std::vector<std::string> m_legend_strings;
9477 
9478   std::vector<base_colormap*> m_bins_cmaps;
9479   std::vector<base_colormap*> m_points_cmaps;
9480   std::vector<base_colormap*> m_func_cmaps;
9481 
9482   group m_todel_group;
9483   std::vector<plotprim*> m_primitives;
9484   cmaps_t m_cmaps;
9485   rtausmef m_rtausmef;
9486 };
9487 
9488 }}
9489 
9490 #endif