Warning, /include/Geant4/tools/sg/plots is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_sg_plots
0005 #define tools_sg_plots
0006
0007 #include "_switch"
0008 #include "matrix"
0009
0010 #include "plotter"
0011
0012 namespace tools {
0013 namespace sg {
0014
0015 class plots : public node {
0016 TOOLS_NODE(plots,tools::sg::plots,node)
0017 public:
0018 sf<float> width;
0019 sf<float> height;
0020 sf<unsigned int> cols; //must never be 0.
0021 sf<unsigned int> rows; //must never be 0.
0022 sf<bool> view_border; //current plotter border
0023 sf<float> plotter_scale; //scale factor applied to each plotter.
0024
0025 sf<bool> border_visible;
0026 sf<float> border_width;
0027 sf<float> border_height;
0028 sf<float> border_z;
0029 sf<float> border_scale;
0030 sf_vec<colorf,float> border_color;
0031
0032 // for gopaw :
0033 sf<float> left_margin;
0034 sf<float> right_margin;
0035 sf<float> top_margin;
0036 sf<float> bottom_margin;
0037 sf<float> horizontal_spacing;
0038 sf<float> vertical_spacing;
0039 public:
0040 virtual const desc_fields& node_desc_fields() const {
0041 TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::plots)
0042 static const desc_fields s_v(parent::node_desc_fields(),18, //WARNING : take care of count.
0043 TOOLS_ARG_FIELD_DESC(width), //1
0044 TOOLS_ARG_FIELD_DESC(height),
0045 TOOLS_ARG_FIELD_DESC(cols),
0046 TOOLS_ARG_FIELD_DESC(rows),
0047 TOOLS_ARG_FIELD_DESC(view_border),
0048 TOOLS_ARG_FIELD_DESC(plotter_scale),
0049 TOOLS_ARG_FIELD_DESC(border_visible),
0050 TOOLS_ARG_FIELD_DESC(border_width),
0051 TOOLS_ARG_FIELD_DESC(border_height),
0052 TOOLS_ARG_FIELD_DESC(border_z), //10
0053 TOOLS_ARG_FIELD_DESC(border_scale),
0054 TOOLS_ARG_FIELD_DESC(border_color),
0055 TOOLS_ARG_FIELD_DESC(left_margin),
0056 TOOLS_ARG_FIELD_DESC(right_margin),
0057 TOOLS_ARG_FIELD_DESC(top_margin),
0058 TOOLS_ARG_FIELD_DESC(bottom_margin),
0059 TOOLS_ARG_FIELD_DESC(horizontal_spacing),
0060 TOOLS_ARG_FIELD_DESC(vertical_spacing)
0061 );
0062 return s_v;
0063 }
0064 virtual bool touched() {
0065 if(parent::touched()) return true;
0066
0067 if(m_sep.empty()) return true;
0068 if(m_extras.size()!=m_extras_sep.size()) return true;
0069
0070 return false;
0071 }
0072 private:
0073 void add_fields(){
0074 add_field(&width);
0075 add_field(&height);
0076 add_field(&cols);
0077 add_field(&rows);
0078 add_field(&view_border);
0079 add_field(&plotter_scale);
0080 add_field(&border_visible);
0081 add_field(&border_width);
0082 add_field(&border_height);
0083 add_field(&border_z);
0084 add_field(&border_scale);
0085 add_field(&border_color);
0086 add_field(&left_margin);
0087 add_field(&right_margin);
0088 add_field(&top_margin);
0089 add_field(&bottom_margin);
0090 add_field(&horizontal_spacing);
0091 add_field(&vertical_spacing);
0092 }
0093 private:
0094 static unsigned int MATRIX() {return 0;}
0095 static unsigned int BORDER() {return 1;}
0096 static unsigned int PLOTTER() {return 2;}
0097
0098 typedef std::vector<plottable*> ptbs_t;
0099 typedef std::vector<node*> todels_t;
0100 typedef std::vector<plotprim*> prims_t;
0101 public:
0102 virtual void render(render_action& a_action) {
0103 update_if_touched();
0104 m_group.render(a_action);
0105 }
0106 virtual void pick(pick_action& a_action) {
0107 update_if_touched();
0108 nodekit_pick(a_action,m_group,this);
0109 }
0110 virtual void search(search_action& a_action) {
0111 update_if_touched();
0112 parent::search(a_action);
0113 if(a_action.done()) return;
0114 if(a_action.do_path()) a_action.path_push(this);
0115 m_group.search(a_action);
0116 if(a_action.done()) return;
0117 if(a_action.do_path()) a_action.path_pop();
0118 }
0119 virtual void bbox(bbox_action& a_action) {
0120 update_if_touched();
0121 m_group.bbox(a_action);
0122 }
0123
0124 virtual void event(event_action& a_action) {
0125 update_if_touched();
0126 m_group.event(a_action);
0127 if(a_action.done()) return;
0128 }
0129 virtual bool write(write_action& a_action) {
0130 update_if_touched();
0131 return m_group.write(a_action);
0132 }
0133 public:
0134 plots(const base_freetype& a_ttf)
0135 :parent()
0136 ,width(1)
0137 ,height(1)
0138 ,cols(1)
0139 ,rows(1)
0140 ,view_border(true)
0141 ,plotter_scale(1)
0142 ,border_visible(false)
0143 ,border_width(0)
0144 ,border_height(0)
0145 ,border_z(0)
0146 ,border_scale(1)
0147 ,border_color(colorf_grey())
0148 ,left_margin(0)
0149 ,right_margin(0)
0150 ,top_margin(0)
0151 ,bottom_margin(0)
0152 ,horizontal_spacing(0)
0153 ,vertical_spacing(0)
0154
0155 ,m_ttf(a_ttf)
0156 ,m_current(0)
0157 ,m_extras()
0158 ,m_old_cols(0)
0159 ,m_old_rows(0)
0160 {
0161 add_fields();
0162 init_sg();
0163 }
0164 virtual ~plots() {
0165 }
0166 public:
0167 plots(const plots& a_from)
0168 :parent(a_from)
0169 ,width(a_from.width)
0170 ,height(a_from.height)
0171 ,cols(a_from.cols)
0172 ,rows(a_from.rows)
0173 ,view_border(a_from.view_border)
0174 ,plotter_scale(a_from.plotter_scale)
0175 ,border_visible(a_from.border_visible)
0176 ,border_width(a_from.border_width)
0177 ,border_height(a_from.border_height)
0178 ,border_z(a_from.border_z)
0179 ,border_scale(a_from.border_scale)
0180 ,border_color(a_from.border_color)
0181 ,left_margin(a_from.left_margin)
0182 ,right_margin(a_from.right_margin)
0183 ,top_margin(a_from.top_margin)
0184 ,bottom_margin(a_from.bottom_margin)
0185 ,horizontal_spacing(a_from.horizontal_spacing)
0186 ,vertical_spacing(a_from.vertical_spacing)
0187
0188 ,m_ttf(a_from.m_ttf)
0189 ,m_current(a_from.m_current)
0190 ,m_extras(a_from.m_extras)
0191 ,m_old_cols(0)
0192 ,m_old_rows(0)
0193 ,m_origins(a_from.m_origins)
0194 ,m_sizes(a_from.m_sizes)
0195 ,m_extras_origins(a_from.m_extras_origins)
0196 ,m_extras_sizes(a_from.m_extras_sizes)
0197 {
0198 add_fields();
0199 init_sg();
0200 if(!copy_plotters(a_from)) {}
0201 }
0202 plots& operator=(const plots& a_from){
0203 parent::operator=(a_from);
0204 if(&a_from==this) return *this;
0205
0206 width = a_from.width;
0207 height = a_from.height;
0208
0209 cols = a_from.cols;
0210 rows = a_from.rows;
0211 view_border = a_from.view_border;
0212 plotter_scale = a_from.plotter_scale;
0213
0214 border_visible = a_from.border_visible;
0215 border_width = a_from.border_width;
0216 border_height = a_from.border_height;
0217 border_z = a_from.border_z;
0218 border_scale = a_from.border_scale;
0219 border_color = a_from.border_color;
0220
0221 left_margin = a_from.left_margin;
0222 right_margin = a_from.right_margin;
0223 top_margin = a_from.top_margin;
0224 bottom_margin = a_from.bottom_margin;
0225 horizontal_spacing = a_from.horizontal_spacing;
0226 vertical_spacing = a_from.vertical_spacing;
0227
0228 m_old_cols = 0;
0229 m_old_rows = 0;
0230 m_origins = a_from.m_origins;
0231 m_sizes = a_from.m_sizes;
0232 m_extras_origins = a_from.m_extras_origins;
0233 m_extras_sizes = a_from.m_extras_sizes;
0234
0235 m_current = a_from.m_current;
0236 m_extras = a_from.m_extras;
0237
0238 if(!copy_plotters(a_from)) {}
0239
0240 return *this;
0241 }
0242 public:
0243 unsigned int number() const {return cols*rows;}
0244 unsigned int current_index() const {return m_current;}
0245
0246 void adjust_size(unsigned int a_ww,unsigned int a_wh) {
0247 if(!a_ww||!a_wh) return;
0248 float aspect = float(a_ww)/float(a_wh);
0249 width = height * aspect;
0250 }
0251
0252 const base_freetype& ttf() const {return m_ttf;}
0253 public:
0254 void clear() {
0255 update_if_touched();
0256 {size_t _number = m_sep.size();
0257 for(size_t index=0;index<_number;index++) {
0258 separator* sep = (separator*)m_sep[index];
0259 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0260 _plotter->clear();
0261 }}
0262 tools_vforit(extra,m_extras,it) {
0263 separator* sep = (*it).m_sep;
0264 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0265 _plotter->clear();
0266 }
0267 }
0268
0269 bool has_data() {
0270 update_if_touched();
0271 {size_t _number = m_sep.size();
0272 for(size_t index=0;index<_number;index++) {
0273 separator* sep = (separator*)m_sep[index];
0274 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0275 if(_plotter->plottables().size()) return true;
0276 }}
0277 tools_vforit(extra,m_extras,it) {
0278 separator* sep = (*it).m_sep;
0279 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0280 if(_plotter->plottables().size()) return true;
0281 }
0282 return false;
0283 }
0284
0285 void touch_plotters() { //used in exlib/geant4/session.
0286 update_if_touched();
0287 {size_t _number = m_sep.size();
0288 for(size_t index=0;index<_number;index++) {
0289 separator* sep = (separator*)m_sep[index];
0290 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0291 _plotter->touch();
0292 }}
0293 tools_vforit(extra,m_extras,it) {
0294 separator* sep = (*it).m_sep;
0295 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0296 _plotter->touch();
0297 }
0298 }
0299
0300 void next() {
0301 update_if_touched();
0302 size_t _number = m_sep.size();
0303 if(m_current>=(uint32(_number)-1)) {
0304 m_current = 0;
0305 } else {
0306 m_current++;
0307 }
0308 update_current_border();
0309 }
0310
0311 bool set_current_plotter(unsigned int a_index) {
0312 update_if_touched();
0313 if(a_index>=m_sep.size()) return false;
0314 m_current = a_index;
0315 update_current_border();
0316 return true;
0317 }
0318
0319 bool set_current(plotter* a_plotter) { //for popup.
0320 update_if_touched();
0321 size_t _number = m_sep.size();
0322 for(size_t index=0;index<_number;index++) {
0323 separator* sep = (separator*)m_sep[index];
0324 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0325 if(_plotter==a_plotter) {
0326 m_current = uint32(index);
0327 update_current_border();
0328 return true;
0329 }
0330 }
0331 return false;
0332 }
0333
0334 plotter& current_plotter() {
0335 update_if_touched();
0336 separator* sep = (separator*)m_sep[m_current];
0337 return *((plotter*)(*sep)[PLOTTER()]);
0338 }
0339 plotter* find_plotter(unsigned int a_index) {
0340 update_if_touched();
0341 if(a_index>=m_sep.size()) return 0;
0342 separator* sep = (separator*)m_sep[a_index];
0343 return (plotter*)(*sep)[PLOTTER()];
0344 }
0345
0346 void set_regions(unsigned int a_cols = 1,unsigned int a_rows = 1,bool a_transfer = false) {
0347 unsigned int oldn = cols*rows;
0348
0349 std::vector<ptbs_t> ptbss;
0350 std::vector<prims_t> primss;
0351 std::vector<todels_t> tdlss;
0352 std::vector<plotter> pls;
0353
0354 if(a_transfer) {
0355 ptbss.resize(oldn);
0356 primss.resize(oldn);
0357 tdlss.resize(oldn);
0358 pls.resize(oldn,plotter(m_ttf));
0359 for(unsigned int index=0;index<oldn;index++) {
0360 plotter* p = find_plotter(index);
0361 p->transfer_plottables(ptbss[index]);
0362 p->transfer_primitives(primss[index]);
0363 p->transfer_todels(tdlss[index]);
0364 pls[index] = *p; //to copy styles.
0365 }
0366 }
0367
0368 cols = a_cols?a_cols:1;
0369 rows = a_rows?a_rows:1;
0370 if(view_border.value()) {view_border = (number()==1?false:true);}
0371 update_sg();
0372 set_current_plotter(0);
0373 clear();
0374 if(a_transfer) {
0375 //fill new plotters with old data :
0376 unsigned int num = min_of(oldn,cols*rows);
0377 for(unsigned int index=0;index<num;index++) {
0378 plotter* p = find_plotter(index);
0379 p->copy_style(pls[index]); //it must not touch p width, height, depth.
0380
0381 {const ptbs_t& ptbs = ptbss[index];
0382 tools_vforcit(plottable*,ptbs,it) p->add_plottable(*it);}
0383 {const prims_t& prims = primss[index];
0384 tools_vforcit(plotprim*,prims,it) p->add_primitive(*it);}
0385 {const todels_t& todels = tdlss[index];
0386 tools_vforcit(node*,todels,it) p->add_node_todel(*it);}
0387 }
0388 }
0389 reset_touched();
0390 }
0391
0392 void current_to_one() {
0393 ptbs_t ptbs;current_plotter().transfer_plottables(ptbs);
0394 prims_t prims;current_plotter().transfer_primitives(prims);
0395 todels_t tdls;current_plotter().transfer_todels(tdls);
0396 plotter pl = current_plotter(); //to copy styles.
0397
0398 set_regions(1,1,false);
0399
0400 plotter& p = current_plotter();
0401 p.copy_style(pl); //copy styles.
0402
0403 {tools_vforcit(plottable*,ptbs,it) p.add_plottable(*it);}
0404 {tools_vforcit(plotprim*,prims,it) p.add_primitive(*it);}
0405 {tools_vforcit(node*,tdls,it) p.add_node_todel(*it);}
0406
0407 }
0408
0409 void plotters(std::vector<plotter*>& a_vec) { //a_vec do NOT get ownership of sg::plotter objects. Use in G4Analysis.
0410 a_vec.clear();
0411 update_if_touched();
0412 size_t _number = m_sep.size();
0413 for(size_t index=0;index<_number;index++) {
0414 separator* sep = (separator*)m_sep[index];
0415 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0416 a_vec.push_back(_plotter);
0417 }
0418 }
0419
0420 //////////////////////////////////////////////////////////////////////
0421 //// styling methods : ///////////////////////////////////////////////
0422 //////////////////////////////////////////////////////////////////////
0423 void set_line_width(float a_line_width) {
0424 update_if_touched();
0425 size_t _number = m_sep.size();
0426 for(size_t index=0;index<_number;index++) {
0427 separator* sep = (separator*)m_sep[index];
0428 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0429
0430 _plotter->bins_style(0).line_width = a_line_width;
0431 _plotter->inner_frame_style().line_width = a_line_width;
0432 _plotter->grid_style().line_width = a_line_width;
0433 _plotter->x_axis().line_style().width = a_line_width;
0434 _plotter->x_axis().ticks_style().width = a_line_width;
0435 _plotter->y_axis().line_style().width = a_line_width;
0436 _plotter->y_axis().ticks_style().width = a_line_width;
0437 _plotter->z_axis().line_style().width = a_line_width;
0438 _plotter->z_axis().ticks_style().width = a_line_width;
0439 _plotter->colormap_axis().line_style().width = a_line_width;
0440 _plotter->colormap_axis().ticks_style().width = a_line_width;
0441
0442 // needed if font is hershey :
0443 _plotter->title_style().line_width = a_line_width;
0444 _plotter->infos_style().line_width = a_line_width;
0445 _plotter->title_box_style().line_width = a_line_width;
0446
0447 _plotter->x_axis().labels_style().line_width = a_line_width;
0448 _plotter->x_axis().mag_style().line_width = a_line_width;
0449 _plotter->x_axis().title_style().line_width = a_line_width;
0450
0451 _plotter->y_axis().labels_style().line_width = a_line_width;
0452 _plotter->y_axis().mag_style().line_width = a_line_width;
0453 _plotter->y_axis().title_style().line_width = a_line_width;
0454
0455 _plotter->z_axis().labels_style().line_width = a_line_width;
0456 _plotter->z_axis().mag_style().line_width = a_line_width;
0457 _plotter->z_axis().title_style().line_width = a_line_width;
0458
0459 _plotter->colormap_axis().labels_style().line_width = a_line_width;
0460 _plotter->colormap_axis().mag_style().line_width = a_line_width;
0461 _plotter->colormap_axis().title_style().line_width = a_line_width;
0462 }
0463 }
0464
0465 void set_grids_visibility(bool a_visible = false) {
0466 update_if_touched();
0467 size_t _number = m_sep.size();
0468 for(size_t index=0;index<_number;index++) {
0469 separator* sep = (separator*)m_sep[index];
0470 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0471 _plotter->grid_style().visible = a_visible;
0472 }
0473 border_visible = true;
0474 }
0475
0476 void adjust_scales(float a_plotter_scale = 1) {
0477 // Rescale some plotter parameters (for example margins) according to the number of plots.
0478 // We assume that these parameters had been set previously according to one plot per page.
0479 // Then this function must be applied after all the styles had been applied (because
0480 // a plotting style may set these parameters).
0481
0482 float ww_wc = width.value();
0483 float wh_wc = height.value();
0484 float rw_wc = ww_wc/cols.value();
0485 float rh_wc = wh_wc/rows.value();
0486
0487 float cooking = 1.2f; //if increased the data area is diminished.
0488
0489 float wfac = (rw_wc/ww_wc)*cooking;
0490 float hfac = (rh_wc/wh_wc)*cooking;
0491
0492 float label_cooking = 1.6f; //if increased the labels are bigger.
0493
0494 if((cols.value()>=4)&&(cols.value()>rows.value())) label_cooking = 0.9f;
0495
0496 float title_cooking = 1.1f; //extra title cooking.
0497
0498 plotter_scale = a_plotter_scale;
0499
0500 update_if_touched();
0501 {size_t _number = m_sep.size();
0502 for(size_t index=0;index<_number;index++) {
0503 separator* sep = (separator*)m_sep[index];
0504 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0505
0506 _plotter->left_margin = _plotter->left_margin * wfac;
0507 _plotter->right_margin = _plotter->right_margin * wfac;
0508 _plotter->bottom_margin = _plotter->bottom_margin * hfac;
0509 _plotter->top_margin = _plotter->top_margin * hfac;
0510
0511 _plotter->x_axis().tick_length = _plotter->x_axis().tick_length * wfac;
0512 _plotter->y_axis().tick_length = _plotter->y_axis().tick_length * hfac;
0513
0514 _plotter->title_to_axis = _plotter->title_to_axis * hfac;
0515 _plotter->title_height = _plotter->title_height * hfac * title_cooking;
0516
0517 _plotter->x_axis().label_height = _plotter->x_axis().label_height * hfac * label_cooking;
0518 _plotter->y_axis().label_height = _plotter->y_axis().label_height * hfac * label_cooking;
0519 }}
0520 }
0521
0522 //gopaw:
0523 void configure_grid_PAW(unsigned int a_ww,unsigned int a_wh) {
0524
0525 m_origins.clear();
0526 m_sizes.clear();
0527
0528 float wvp = float(a_ww); //pixels.
0529 float hvp = float(a_wh); //pixels.
0530 if( (wvp<=0)||(hvp<=0)||(width.value()<=0)||(height.value()<=0) ) return;
0531
0532 unsigned int _cols = cols.value();
0533 unsigned int _rows = rows.value();
0534 if((!_cols)||(!_rows)) return;
0535
0536 float wdata = (width.value()-left_margin.value()-right_margin.value()-(_cols-1)*horizontal_spacing.value())/_cols;
0537 float hdata = (height.value()-bottom_margin.value()-top_margin.value()-(_rows-1)*vertical_spacing.value())/_rows;
0538
0539 if((wdata<=0)||(hdata<=0)) return;
0540
0541
0542 unsigned int _num = number();
0543 for(unsigned int iregion=0;iregion<_num;iregion++) {
0544 //iregion = col + row * cols
0545 unsigned int row = iregion/_cols;
0546 unsigned int col = iregion - row * _cols;
0547
0548 float wr,hr,x,y,lm,rm,bm,tm;
0549 wr = hr = x = y = 0;
0550 lm = rm = bm = tm = 0;
0551
0552 if(_cols==1) {
0553 wr = width.value();
0554 x = 0;
0555 lm = left_margin.value();
0556 rm = right_margin.value();
0557 } else {
0558 float wrl = left_margin.value()+wdata+horizontal_spacing.value()/2;
0559 float wrr = right_margin.value()+wdata+horizontal_spacing.value()/2;
0560 float wri = wdata+horizontal_spacing.value();
0561 if(col==0) {
0562 wr = wrl;
0563 x = 0;
0564 lm = left_margin.value();
0565 rm = horizontal_spacing.value()/2;
0566 } else if(col==(_cols-1)) {
0567 wr = wrr;
0568 x = width.value() - wrr;
0569 lm = horizontal_spacing.value()/2;
0570 rm = right_margin.value();
0571 } else {
0572 wr = wri;
0573 x = wrl + (col-1) * wri;
0574 lm = horizontal_spacing.value()/2;
0575 rm = horizontal_spacing.value()/2;
0576 }
0577 }
0578
0579 if(_rows==1) {
0580 hr = height.value();
0581 y = 0;
0582 tm = top_margin.value();
0583 bm = bottom_margin.value();
0584 } else {
0585 float hrt = top_margin.value()+hdata+vertical_spacing.value()/2; //top
0586 float hrb = bottom_margin.value()+hdata+vertical_spacing.value()/2; //bottom
0587 float hri = hdata+vertical_spacing.value();
0588 if(row==0) { //top row.
0589 hr = hrt;
0590 y = height.value()-hrt;
0591 tm = top_margin.value();
0592 bm = vertical_spacing.value()/2;
0593 } else if(row==(_rows-1)) {
0594 hr = hrb;
0595 y = 0;
0596 tm = vertical_spacing.value()/2;
0597 bm = bottom_margin.value();
0598 } else {
0599 hr = hri;
0600 y = height.value()- (hrt + row * hri);
0601 tm = vertical_spacing.value()/2;
0602 bm = vertical_spacing.value()/2;
0603 }
0604 }
0605
0606 m_origins.push_back(vec2f(x,y));
0607 m_sizes.push_back(vec2f(wr,hr));
0608
0609 separator* sep = (separator*)m_sep[iregion];
0610 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0611
0612 _plotter->left_margin = lm;
0613 _plotter->right_margin = rm;
0614
0615 _plotter->top_margin = tm;
0616 _plotter->bottom_margin = bm;
0617 }
0618 }
0619
0620 void configure_extras_PAW(unsigned int a_ww,unsigned int a_wh) {
0621
0622 m_extras_origins.clear();
0623 m_extras_sizes.clear();
0624
0625 float wvp = float(a_ww); //pixels.
0626 float hvp = float(a_wh); //pixels.
0627 if( (wvp<=0)||(hvp<=0)||(width.value()<=0)||(height.value()<=0) ) return;
0628
0629 tools_vforcit(extra,m_extras,it) {
0630 const extra& _extra = *it;
0631
0632 unsigned int _cols = _extra.m_cols;
0633 unsigned int _rows = _extra.m_rows;
0634 if((!_cols)||(!_rows)) continue;
0635
0636 float wdata = (width.value()-left_margin.value()-right_margin.value()-(_cols-1)*horizontal_spacing.value())/_cols;
0637 float hdata = (height.value()-bottom_margin.value()-top_margin.value()-(_rows-1)*vertical_spacing.value())/_rows;
0638
0639 if((wdata<=0)||(hdata<=0)) continue;
0640
0641 unsigned int iregion = _extra.m_index;
0642 unsigned int row = iregion/_cols;
0643 unsigned int col = iregion - row * _cols;
0644
0645 float wr,hr,x,y,lm,rm,bm,tm;
0646 wr = hr = x = y = 0;
0647 lm = rm = bm = tm = 0;
0648
0649 if(_cols==1) {
0650 wr = width.value();
0651 x = 0;
0652 lm = left_margin.value();
0653 rm = right_margin.value();
0654 } else {
0655 float wrl = left_margin.value()+wdata+horizontal_spacing.value()/2;
0656 float wrr = right_margin.value()+wdata+horizontal_spacing.value()/2;
0657 float wri = wdata+horizontal_spacing.value();
0658 if(col==0) {
0659 wr = wrl;
0660 x = 0;
0661 lm = left_margin.value();
0662 rm = horizontal_spacing.value()/2;
0663 } else if(col==(_cols-1)) {
0664 wr = wrr;
0665 x = width.value() - wrr;
0666 lm = horizontal_spacing.value()/2;
0667 rm = right_margin.value();
0668 } else {
0669 wr = wri;
0670 x = wrl + (col-1) * wri;
0671 lm = horizontal_spacing.value()/2;
0672 rm = horizontal_spacing.value()/2;
0673 }
0674 }
0675
0676 if(_rows==1) {
0677 hr = height.value();
0678 y = 0;
0679 tm = top_margin.value();
0680 bm = bottom_margin.value();
0681 } else {
0682 float hrt = top_margin.value()+hdata+vertical_spacing.value()/2; //top
0683 float hrb = bottom_margin.value()+hdata+vertical_spacing.value()/2; //bottom
0684 float hri = hdata+vertical_spacing.value();
0685 if(row==0) { //top row.
0686 hr = hrt;
0687 y = height.value()-hrt;
0688 tm = top_margin.value();
0689 bm = vertical_spacing.value()/2;
0690 } else if(row==(_rows-1)) {
0691 hr = hrb;
0692 y = 0;
0693 tm = vertical_spacing.value()/2;
0694 bm = bottom_margin.value();
0695 } else {
0696 hr = hri;
0697 y = height.value()- (hrt + row * hri);
0698 tm = vertical_spacing.value()/2;
0699 bm = vertical_spacing.value()/2;
0700 }
0701 }
0702
0703 m_extras_origins.push_back(vec2f(x,y));
0704 m_extras_sizes.push_back(vec2f(wr,hr));
0705
0706 separator* sep = _extra.m_sep;
0707 plotter* _plotter = (plotter*)(*sep)[PLOTTER()];
0708
0709 _plotter->left_margin = lm;
0710 _plotter->right_margin = rm;
0711
0712 _plotter->top_margin = tm;
0713 _plotter->bottom_margin = bm;
0714 } //tools_vforcit
0715 }
0716 void configure_PAW(unsigned int a_ww,unsigned int a_wh) {
0717 configure_grid_PAW(a_ww,a_wh);
0718 configure_extras_PAW(a_ww,a_wh);
0719 touch();
0720 update_if_touched();
0721 }
0722 //////////////////////////////////////////////////////////////////////
0723 //////////////////////////////////////////////////////////////////////
0724 //////////////////////////////////////////////////////////////////////
0725
0726 //gopaw:
0727 void delete_extras() {
0728 m_extras_sep.clear();
0729 m_extras.clear();
0730 }
0731
0732 plotter* create_extra_plotter(unsigned int a_cols,unsigned int a_rows,unsigned int a_index) {
0733 // Create a plotter with size and position as if in a grid of a_colsxa_rows and at position a_index.
0734 // The index numbering being for example for a grid of 3x2 :
0735 // 0 1 2
0736 // 3 4 5
0737 m_extras.push_back(extra(a_cols,a_rows,a_index));
0738 update_if_touched();
0739 separator* sep = m_extras.back().m_sep;
0740 return (plotter*)(*sep)[PLOTTER()];
0741 }
0742 plotter* last_extra_plotter() const {
0743 if(m_extras.empty()) return 0;
0744 separator* sep = m_extras.back().m_sep;
0745 return (plotter*)(*sep)[PLOTTER()];
0746 }
0747 public:
0748 void init_sg() { // used also in gopaw::base_viewer::clean_gstos().
0749 m_group.clear();
0750 m_sep.clear();
0751 m_border_sep.clear();
0752 m_extras_sep.clear();
0753 m_group.add(new noderef(m_sep));
0754 m_group.add(new noderef(m_border_sep));
0755 m_group.add(new noderef(m_extras_sep));
0756 }
0757 void clear_sg() { //used in GL_plots_viewer.
0758 m_group.clear();
0759 m_sep.clear();
0760 m_border_sep.clear();
0761 m_extras_sep.clear();
0762 }
0763 protected:
0764 void update_if_touched() {
0765 if(touched()) {
0766 update_sg();
0767 reset_touched();
0768 }
0769 }
0770 void update_sg(){
0771
0772 if(m_sep.empty()||(cols.value()!=m_old_cols)||(rows.value()!=m_old_rows)){
0773
0774 m_old_cols = cols;
0775 m_old_rows = rows;
0776
0777 m_sep.clear();
0778
0779 for(unsigned int irow=0;irow<rows;irow++) {
0780 for(unsigned int icol=0;icol<cols;icol++) {
0781 separator* sep = new separator;
0782 m_sep.add(sep);
0783
0784 sep->add(new sg::matrix); //MATRIX()
0785
0786 _switch* border = new _switch;
0787 sep->add(border); //BORDER()
0788
0789 sep->add(new plotter(m_ttf)); //PLOTTER()
0790 }
0791 }
0792
0793 if(m_current>=m_sep.size()) m_current = 0;
0794 }
0795
0796 update_current_border();
0797 update_border();
0798
0799 if((width.value()>0)&&(height.value()>0)) {
0800 size_t _number = m_sep.size();
0801
0802 bool configure = (m_origins.size()==_number)&&(m_sizes.size()==_number)?true:false;
0803
0804 // all window wc :
0805 float ww_wc = width;
0806 float wh_wc = height;
0807
0808 for(size_t index=0;index<_number;index++) {
0809 separator* sep = (separator*)m_sep[index];
0810 set_plotter_layout(*sep,index,configure,cols.value(),rows.value(),
0811 ww_wc,wh_wc,m_origins,m_sizes,plotter_scale.value());
0812 }
0813 }
0814
0815 update_extras();
0816 }
0817
0818 bool copy_plotters(const plots& a_from) {
0819 update_if_touched();
0820 if(m_sep.size()==a_from.m_sep.size()) {
0821 size_t _number = m_sep.size();
0822 for(size_t index=0;index<_number;index++) {
0823 separator* _from_sep = (separator*)a_from.m_sep[index];
0824 matrix* _from_matrix = (matrix*)(*_from_sep)[MATRIX()];
0825 plotter* _from_plotter = (plotter*)(*_from_sep)[PLOTTER()];
0826
0827 separator* _sep = (separator*)m_sep[index];
0828 matrix* _matrix = (matrix*)(*_sep)[MATRIX()];
0829 plotter* _plotter = (plotter*)(*_sep)[PLOTTER()];
0830
0831 _matrix->operator=(*_from_matrix);
0832 _plotter->operator=(*_from_plotter);
0833 }
0834 }
0835 if(m_extras_sep.size()==a_from.m_extras_sep.size()) {
0836 size_t _number = m_extras_sep.size();
0837 for(size_t index=0;index<_number;index++) {
0838 separator* _from_sep = (separator*)a_from.m_extras_sep[index];
0839 matrix* _from_matrix = (matrix*)(*_from_sep)[MATRIX()];
0840 plotter* _from_plotter = (plotter*)(*_from_sep)[PLOTTER()];
0841
0842 separator* _sep = (separator*)m_extras_sep[index];
0843 matrix* _matrix = (matrix*)(*_sep)[MATRIX()];
0844 plotter* _plotter = (plotter*)(*_sep)[PLOTTER()];
0845
0846 _matrix->operator=(*_from_matrix);
0847 _plotter->operator=(*_from_plotter);
0848 }
0849 }
0850 return true;
0851 }
0852
0853 static void create_plotter_border(_switch& a_parent,float a_w,float a_h) {
0854 a_parent.clear();
0855
0856 group* sep = new group;
0857 a_parent.add(sep);
0858
0859 a_parent.add(new group()); //empty
0860
0861 rgba* mat = new rgba();
0862 mat->color = colorf_red();
0863 sep->add(mat);
0864
0865 draw_style* ds = new draw_style;
0866 ds->style = draw_lines;
0867 ds->line_width = 4;
0868 sep->add(ds);
0869
0870 vertices* vtxs = new vertices;
0871 vtxs->mode = gl::line_strip();
0872 sep->add(vtxs);
0873
0874 float dw = a_w*0.5f;
0875 float dh = a_h*0.5f;
0876 vtxs->add(-dw,-dh,0);
0877 vtxs->add( dw,-dh,0);
0878 vtxs->add( dw, dh,0);
0879 vtxs->add(-dw, dh,0);
0880 vtxs->add(-dw,-dh,0);
0881 }
0882
0883 void update_current_border() {
0884 size_t _number = m_sep.size();
0885 for(size_t index=0;index<_number;index++) {
0886 separator* sep = (separator*)m_sep[index];
0887 _switch* _border = (_switch*)(*sep)[BORDER()];
0888 if(index==m_current) {
0889 _border->which = view_border.value()?0:1;
0890 } else {
0891 _border->which = 1;
0892 }
0893 }
0894 }
0895
0896 void update_border() {
0897 m_border_sep.clear();
0898
0899 if(!border_visible.value()) return;
0900
0901 if(width.value()<=0) return;
0902 if(height.value()<=0) return;
0903 if(border_width.value()<=0) return;
0904 if(border_height.value()<=0) return;
0905
0906 // border_scale could be used as an offscreen (inzb_[ps,png,jpeg], gl2s_pdf)
0907 // cooking to avoid seeing a one pixel line at some side (in general left)
0908 // coming from the border.
0909 if(border_scale.value()!=1) {
0910 matrix* _m = new matrix;
0911 _m->set_scale(border_scale.value(),border_scale.value(),1);
0912 m_border_sep.add(_m);
0913 }
0914
0915 float bw = border_width;
0916 float bh = border_height;
0917
0918 // do it with four externals back_area.
0919
0920 float zz = border_z.value();
0921
0922 // top :
0923 {separator* sep = new separator;
0924 m_border_sep.add(sep);
0925
0926 float wba = width+2*bw;
0927 float hba = bh;
0928 float x = 0;
0929 float y = height*0.5f+bh*0.5f;
0930
0931 matrix* _m = new matrix;
0932 _m->set_translate(x,y,zz);
0933 sep->add(_m);
0934
0935 back_area* b = new back_area;
0936 b->border_visible = false;
0937 b->color = border_color;
0938 b->width = wba;
0939 b->height = hba;
0940 sep->add(b);}
0941
0942 // bottom :
0943 {separator* sep = new separator;
0944 m_border_sep.add(sep);
0945
0946 float wba = width+2*bw;
0947 float hba = bh;
0948 float x = 0;
0949 float y = -height*0.5f-bh*0.5f;
0950
0951 matrix* _m = new matrix;
0952 _m->set_translate(x,y,zz);
0953 sep->add(_m);
0954
0955 back_area* b = new back_area;
0956 b->border_visible = false;
0957 b->color = border_color;
0958 b->width = wba;
0959 b->height = hba;
0960 sep->add(b);}
0961
0962 // left :
0963 {separator* sep = new separator;
0964 m_border_sep.add(sep);
0965
0966 float wba = bw;
0967 float hba = height+2*bh;
0968 float x = -width*0.5f-bw*0.5f;
0969 float y = 0;
0970
0971 matrix* _m = new matrix;
0972 _m->set_translate(x,y,zz);
0973 sep->add(_m);
0974
0975 back_area* b = new back_area;
0976 b->border_visible = false;
0977 b->color = border_color;
0978 b->width = wba;
0979 b->height = hba;
0980 sep->add(b);}
0981
0982 // right :
0983 {separator* sep = new separator;
0984 m_border_sep.add(sep);
0985
0986 float wba = bw;
0987 float hba = height+2*bh;
0988 float x = width*0.5f+bw*0.5f;
0989 float y = 0;
0990
0991 matrix* _m = new matrix;
0992 _m->set_translate(x,y,zz);
0993 sep->add(_m);
0994
0995 back_area* b = new back_area;
0996 b->border_visible = false;
0997 b->color = border_color;
0998 b->width = wba;
0999 b->height = hba;
1000 sep->add(b);}
1001
1002 }
1003 protected:
1004 class extra {
1005 public:
1006 extra(unsigned int a_cols,unsigned int a_rows,unsigned int a_index)
1007 :m_cols(a_cols),m_rows(a_rows),m_index(a_index),m_sep(0){}
1008 virtual ~extra(){}
1009 public:
1010 extra(const extra& a_from):m_cols(a_from.m_cols),m_rows(a_from.m_rows),m_index(a_from.m_index),m_sep(0){}
1011 extra& operator=(const extra& a_from) {
1012 m_cols = a_from.m_cols;
1013 m_rows = a_from.m_rows;
1014 m_index = a_from.m_index;
1015 m_sep = a_from.m_sep;
1016 return *this;
1017 }
1018 public:
1019 unsigned int m_cols;
1020 unsigned int m_rows;
1021 unsigned int m_index;
1022 separator* m_sep;
1023 };
1024
1025 void update_extras() {
1026 if(m_extras.size()!=m_extras_sep.size()) {
1027 m_extras_sep.clear();
1028 tools_vforit(extra,m_extras,it) { // same sg layout than grid plotters.
1029 separator* sep = new separator;
1030 m_extras_sep.add(sep);
1031 (*it).m_sep = sep; //*it does not get ownership.
1032
1033 sep->add(new sg::matrix); //MATRIX()
1034
1035 _switch* border = new _switch;
1036 sep->add(border); //BORDER()
1037 sep->add(new plotter(m_ttf)); //PLOTTER()
1038 }
1039 }
1040
1041 if(width.value()<=0) return;
1042 if(height.value()<=0) return;
1043
1044 // all window wc :
1045 float ww_wc = width;
1046 float wh_wc = height;
1047
1048 size_t _number = m_extras.size();
1049
1050 bool configure = (m_extras_origins.size()==_number)&&(m_extras_sizes.size()==_number)?true:false;
1051
1052 tools_vforcit(extra,m_extras,it) {
1053 const extra& _extra = *it;
1054 unsigned int index = _extra.m_index;
1055 if(index>=(m_extras_sep.size())) index = 0;
1056
1057 separator* sep = _extra.m_sep;
1058 set_plotter_layout(*sep,index,configure,_extra.m_cols,_extra.m_rows,
1059 ww_wc,wh_wc,m_extras_origins,m_extras_sizes,plotter_scale.value());
1060 }
1061
1062 }
1063 protected:
1064 static void set_plotter_layout(separator& a_sep,size_t a_index,bool a_configure,
1065 unsigned int a_cols,unsigned int a_rows,
1066 float a_ww_wc,float a_wh_wc,
1067 const std::vector<vec2f>& a_origins,const std::vector<vec2f>& a_sizes,float a_scale) {
1068 size_t row = a_index/a_cols;
1069 size_t col = a_index-a_cols*row;
1070
1071 float rw_wc = a_ww_wc/a_cols;
1072 float rh_wc = a_wh_wc/a_rows;
1073
1074 matrix* _matrix = (matrix*)(a_sep)[MATRIX()];
1075 plotter* _plotter = (plotter*)(a_sep)[PLOTTER()];
1076
1077 if(a_configure) {
1078 _plotter->width = a_sizes[a_index].x();
1079 _plotter->height = a_sizes[a_index].y();
1080 float x = -a_ww_wc*0.5f + a_origins[a_index].x() + _plotter->width*0.5f;
1081 float y = -a_wh_wc*0.5f + a_origins[a_index].y() + _plotter->height*0.5f;
1082 _matrix->set_translate(x,y,0);
1083 } else {
1084 float x = -a_ww_wc*0.5f + col * rw_wc + rw_wc * 0.5f;
1085 float y = a_wh_wc*0.5f - row * rh_wc - rh_wc * 0.5f;
1086 _matrix->set_translate(x,y,0);
1087 }
1088 _matrix->mul_scale(a_scale,a_scale,1); //applied first.
1089
1090 {_switch* _border = (_switch*)(a_sep)[BORDER()];
1091 create_plotter_border(*_border,rw_wc,rh_wc);
1092 _border->which = 1;
1093 }
1094
1095 if(_plotter->shape.value()==plotter::xy) {
1096 _plotter->depth = min_of(rw_wc,rh_wc);
1097 } else {
1098 _plotter->depth = rh_wc;
1099 }
1100
1101 if(a_configure) {
1102 } else {
1103 if(_plotter->shape.value()==plotter::xy) {
1104 _plotter->width = rw_wc;
1105 _plotter->height = rh_wc;
1106 } else {
1107 if((rw_wc/rh_wc)>=1.0f) {
1108 _plotter->width = rh_wc;
1109 _plotter->height = rh_wc;
1110 } else {
1111 _plotter->width = rw_wc;
1112 _plotter->height = rw_wc;
1113 }
1114 }
1115 }
1116 }
1117 protected:
1118 const base_freetype& m_ttf;
1119
1120 group m_group;
1121 separator m_sep;
1122 separator m_border_sep;
1123 separator m_extras_sep;
1124 unsigned int m_current;
1125
1126 std::vector<extra> m_extras;
1127
1128 //updater* m_updater;
1129 unsigned int m_old_cols;
1130 unsigned int m_old_rows;
1131
1132 std::vector<vec2f> m_origins;
1133 std::vector<vec2f> m_sizes;
1134 std::vector<vec2f> m_extras_origins;
1135 std::vector<vec2f> m_extras_sizes;
1136
1137 };
1138
1139 }}
1140
1141 #endif