Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/sg/plotter

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

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