Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights 2 // See the file tools.license for terms. 3 4 #ifndef tools_sg_axis 5 #define tools_sg_axis 6 7 #include "node" 8 #include "line_style" 9 #include "text_style" 10 #include "enums" 11 #include "noderef" 12 #include "vertices" 13 #include "draw_style" 14 #include "rgba" 15 #include "normal" 16 #include "separator" 17 #include "tools" 18 #include "nodekit" 19 20 #include "../lina/vec3f" 21 #include "../mnmx" 22 #include "../hplot" 23 24 #include <cstdio> //sprintf 25 #include <cstring> //strcpy 26 27 namespace tools { 28 namespace sg { 29 30 class axis : public node { 31 public: 32 TOOLS_NODE(axis,tools::sg::axis,node) 33 public: 34 sf<float> width; 35 sf<float> minimum_value; 36 sf<float> maximum_value; 37 sf<unsigned int> divisions; 38 sf_string modeling; //hippo, hplot 39 sf<bool> is_log; 40 // If modeling is hippo or hplot, 41 // labels_enforced true let labels be an inp 42 sf<bool> labels_enforced; 43 sf<bool> tick_up; 44 sf<float> tick_length; 45 46 // NOTE : if modeling is none,the below are 47 // If modeling is hippo or hplot, the 48 // (filled by compute_ticks). 49 sf<unsigned int> tick_number; //output 50 mf_string labels; //output 51 mf<float> values; //output //in [minim 52 mf<float> coords; //output //in [0,wid 53 mf<float> sub_coords; //output 54 sf<int> magnitude; //output 55 56 sf_string title; 57 sf<float> title_to_axis; 58 sf<float> title_height; 59 sf_enum<hjust> title_hjust; 60 61 sf<float> label_to_axis; 62 sf<float> label_height; 63 64 sf<bool> labels_no_overlap_automated; 65 sf<float> labels_gap; //in percent of width. 66 67 // time labels only in hplot modeling for th 68 sf<bool> time_labels; 69 sf_string time_format; 70 sf<double> time_offset; 71 sf<bool> time_offset_is_GMT; 72 public: 73 virtual const desc_fields& node_desc_fields( 74 TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::axi 75 static const desc_fields s_v(parent::node_ 76 TOOLS_ARG_FIELD_DESC(width), 77 TOOLS_ARG_FIELD_DESC(minimum_value), 78 TOOLS_ARG_FIELD_DESC(maximum_value), 79 TOOLS_ARG_FIELD_DESC(divisions), 80 TOOLS_ARG_FIELD_DESC(modeling), 81 TOOLS_ARG_FIELD_DESC(is_log), 82 TOOLS_ARG_FIELD_DESC(labels_enforced), 83 TOOLS_ARG_FIELD_DESC(tick_up), 84 TOOLS_ARG_FIELD_DESC(tick_length), 85 TOOLS_ARG_FIELD_DESC(tick_number), 86 TOOLS_ARG_FIELD_DESC(labels), 87 TOOLS_ARG_FIELD_DESC(values), 88 TOOLS_ARG_FIELD_DESC(coords), 89 TOOLS_ARG_FIELD_DESC(sub_coords), 90 TOOLS_ARG_FIELD_DESC(magnitude), 91 TOOLS_ARG_FIELD_DESC(title), 92 TOOLS_ARG_FIELD_DESC(title_to_axis), 93 TOOLS_ARG_FIELD_DESC(title_height), 94 TOOLS_ARG_FIELD_DESC(title_hjust), 95 TOOLS_ARG_FIELD_DESC(label_to_axis), 96 TOOLS_ARG_FIELD_DESC(label_height), 97 TOOLS_ARG_FIELD_DESC(labels_no_overlap_a 98 TOOLS_ARG_FIELD_DESC(labels_gap), 99 100 TOOLS_ARG_FIELD_DESC(time_labels), 101 TOOLS_ARG_FIELD_DESC(time_format), 102 TOOLS_ARG_FIELD_DESC(time_offset), 103 TOOLS_ARG_FIELD_DESC(time_offset_is_GMT) 104 ); 105 return s_v; 106 } 107 virtual bool touched() { 108 if(parent::touched()) return true; 109 if(line_style().touched()) return true; 110 if(ticks_style().touched()) return true; 111 if(labels_style().touched()) return true; 112 if(mag_style().touched()) return true; 113 if(title_style().touched()) return true; 114 return false; 115 } 116 virtual void reset_touched() { 117 parent::reset_touched(); 118 line_style().reset_touched(); 119 ticks_style().reset_touched(); 120 labels_style().reset_touched(); 121 mag_style().reset_touched(); 122 title_style().reset_touched(); 123 } 124 private: 125 void add_fields(){ 126 // if adding a field, look for reset_style 127 add_field(&width); 128 add_field(&minimum_value); 129 add_field(&maximum_value); 130 add_field(&divisions); 131 add_field(&modeling); 132 add_field(&is_log); 133 add_field(&labels_enforced); 134 add_field(&tick_up); 135 add_field(&tick_length); 136 add_field(&tick_number); 137 add_field(&labels); 138 add_field(&values); 139 add_field(&coords); 140 add_field(&sub_coords); 141 add_field(&magnitude); 142 add_field(&title); 143 add_field(&title_to_axis); 144 add_field(&title_height); 145 add_field(&title_hjust); 146 add_field(&label_to_axis); 147 add_field(&label_height); 148 add_field(&labels_no_overlap_automated); 149 add_field(&labels_gap); 150 151 add_field(&time_labels); 152 add_field(&time_format); 153 add_field(&time_offset); 154 add_field(&time_offset_is_GMT); 155 } 156 void init_sg(){ 157 m_group.add(new noderef(m_line_sep)); 158 m_group.add(new noderef(m_ticks_sep)); 159 m_group.add(new noderef(m_labels_sep)); 160 m_group.add(new noderef(m_mag_sep)); 161 m_group.add(new noderef(m_title_sep)); 162 } 163 public: 164 virtual void render(render_action& a_action) 165 if(touched()) { 166 update_sg(a_action.out()); 167 reset_touched(); 168 } 169 m_group.render(a_action); 170 } 171 virtual void pick(pick_action& a_action) { 172 if(touched()) { 173 update_sg(a_action.out()); 174 reset_touched(); 175 } 176 //m_group.pick(a_action); 177 nodekit_pick(a_action,m_group,this); 178 } 179 virtual void search(search_action& a_action) 180 if(touched()) { 181 update_sg(a_action.out()); 182 reset_touched(); 183 } 184 parent::search(a_action); 185 if(a_action.done()) return; 186 m_group.search(a_action); 187 } 188 virtual void bbox(bbox_action& a_action) { 189 if(touched()) { 190 update_sg(a_action.out()); 191 reset_touched(); 192 } 193 m_group.bbox(a_action); 194 } 195 196 virtual bool write(write_action& a_action) { 197 //FIXME : this method should not be needed 198 // But m_[line,ticks,labels,mag,tit 199 200 if(touched()) { 201 update_sg(a_action.out()); 202 reset_touched(); 203 } 204 //if(!write_fields(a_action)) return false 205 return m_group.write(a_action); 206 } 207 public: 208 axis(const base_freetype& a_ttf) 209 :parent() 210 ,width(1) 211 ,minimum_value(0) 212 ,maximum_value(1) 213 ,divisions(510) 214 ,modeling(tick_modeling_hippo()) 215 ,is_log(false) 216 ,labels_enforced(false) 217 ,tick_up(true) 218 ,tick_length(0) 219 220 ,tick_number(0) 221 ,magnitude(0) 222 223 ,title("") 224 ,title_to_axis(0) //inited below 225 ,title_height(0) //inited below 226 ,title_hjust(right) 227 228 ,label_to_axis(0) //inited below 229 ,label_height(0) //inited below 230 231 ,labels_no_overlap_automated(true) 232 ,labels_gap(0.02f) 233 234 ,time_labels(false) 235 ,time_format("%H:%M:%S") 236 ,time_offset(0) //UTC_time_1970_01_01__00_00 237 ,time_offset_is_GMT(false) 238 239 ,m_ttf(a_ttf) 240 { 241 add_fields(); 242 243 init_sg(); 244 245 reset_style(true); 246 } 247 virtual ~axis(){} 248 public: 249 axis(const axis& a_from) 250 :parent(a_from) 251 ,width(a_from.width) 252 ,minimum_value(a_from.minimum_value) 253 ,maximum_value(a_from.maximum_value) 254 ,divisions(a_from.divisions) 255 ,modeling(a_from.modeling) 256 ,is_log(a_from.is_log) 257 ,labels_enforced(a_from.labels_enforced) 258 ,tick_up(a_from.tick_up) 259 ,tick_length(a_from.tick_length) 260 261 ,tick_number(a_from.tick_number) 262 ,magnitude(a_from.magnitude) 263 264 ,title(a_from.title) 265 ,title_to_axis(a_from.title_to_axis) 266 ,title_height(a_from.title_height) 267 ,title_hjust(a_from.title_hjust) 268 269 ,label_to_axis(a_from.label_to_axis) 270 ,label_height(a_from.label_height) 271 272 ,labels_no_overlap_automated(a_from.labels_n 273 ,labels_gap(a_from.labels_gap) 274 275 ,time_labels(a_from.time_labels) 276 ,time_format(a_from.time_format) 277 ,time_offset(a_from.time_offset) 278 ,time_offset_is_GMT(a_from.time_offset_is_GM 279 280 ,m_ttf(a_from.m_ttf) 281 282 ,m_line_style(a_from.m_line_style) 283 ,m_ticks_style(a_from.m_ticks_style) 284 ,m_labels_style(a_from.m_labels_style) 285 ,m_mag_style(a_from.m_mag_style) 286 ,m_title_style(a_from.m_title_style) 287 { 288 add_fields(); 289 init_sg(); 290 } 291 axis& operator=(const axis& a_from){ 292 parent::operator=(a_from); 293 294 width = a_from.width; 295 minimum_value = a_from.minimum_value; 296 maximum_value = a_from.maximum_value; 297 divisions = a_from.divisions; 298 modeling = a_from.modeling; 299 is_log = a_from.is_log; 300 labels_enforced = a_from.labels_enforced; 301 tick_up = a_from.tick_up; 302 tick_length = a_from.tick_length; 303 304 tick_number = a_from.tick_number; 305 magnitude = a_from.magnitude; 306 307 title = a_from.title; 308 title_to_axis = a_from.title_to_axis; 309 title_height = a_from.title_height; 310 title_hjust = a_from.title_hjust; 311 312 label_to_axis = a_from.label_to_axis; 313 label_height = a_from.label_height; 314 315 labels_no_overlap_automated = a_from.label 316 labels_gap = a_from.labels_gap; 317 318 time_labels = a_from.time_labels; 319 time_format = a_from.time_format; 320 time_offset = a_from.time_offset; 321 time_offset_is_GMT = a_from.time_offset_is 322 323 m_line_style = a_from.m_line_style; 324 m_ticks_style = a_from.m_ticks_style; 325 m_labels_style = a_from.m_labels_style; 326 m_mag_style = a_from.m_mag_style; 327 m_title_style = a_from.m_title_style; 328 329 return *this; 330 } 331 public: 332 sg::line_style& line_style() {return m_line_ 333 sg::line_style& ticks_style() {return m_tick 334 text_style& labels_style() {return m_labels_ 335 text_style& title_style() {return m_title_st 336 text_style& mag_style() {return m_mag_style; 337 338 void set_color(const colorf& a_color){ 339 m_line_style.color = a_color; 340 m_ticks_style.color = a_color; 341 m_labels_style.color = a_color; 342 m_title_style.color = a_color; 343 m_mag_style.color = a_color; 344 } 345 public: 346 void update_sg(std::ostream& a_out) { 347 //a_out << "debug : tools::axis::update_sg 348 349 if(width<=0) { 350 m_line_sep.clear(); 351 m_ticks_sep.clear(); 352 m_labels_sep.clear(); 353 m_mag_sep.clear(); 354 m_title_sep.clear(); 355 return; 356 } 357 358 // line scene graph : 359 m_line_sep.clear(); 360 if(m_line_style.visible) { 361 rgba* mat = new rgba(); 362 mat->color = m_line_style.color; 363 m_line_sep.add(mat); 364 365 draw_style* ds = new draw_style; 366 ds->style = draw_lines; 367 ds->line_pattern = m_line_style.pattern; 368 ds->line_width = m_line_style.width; 369 m_line_sep.add(ds); 370 371 vertices* vtxs = new vertices; 372 vtxs->mode = gl::line_strip(); 373 vtxs->add(0,0,0); 374 vtxs->add(width,0,0); 375 m_line_sep.add(vtxs); 376 } 377 378 // ticks scene graph : 379 if(modeling==tick_modeling_none()) { 380 } else if(modeling==tick_modeling_hplot()) 381 compute_ticks_HPLOT(a_out); 382 } else { 383 compute_ticks_hippo(); 384 } 385 386 m_ticks_sep.clear(); 387 if(m_ticks_style.visible) { 388 389 vertices* vtxs = new vertices; 390 vtxs->mode = gl::lines(); 391 392 if(modeling==tick_modeling_hplot()) { 393 394 size_t num = m_sub_ticks.size()/4; 395 size_t pos = 0; 396 for(size_t index=0;index<num;index++) 397 float bx = m_sub_ticks[pos];pos++; 398 float by = m_sub_ticks[pos];pos++; 399 float ex = m_sub_ticks[pos];pos++; 400 float ey = m_sub_ticks[pos];pos++; 401 if(tick_up) { 402 vtxs->add(bx,by,0); 403 vtxs->add(ex,ey,0); 404 } else { 405 vtxs->add(bx,-by,0); 406 vtxs->add(ex,-ey,0); 407 } 408 } 409 410 } else { 411 412 float yy = tick_up ? tick_length.value 413 for(unsigned int index=0;index<tick_nu 414 float xx = coords.values()[index]; 415 vtxs->add(xx,0,0); 416 vtxs->add(xx,yy,0); 417 } 418 } 419 420 if(vtxs->number()) { 421 422 rgba* mat = new rgba(); 423 mat->color = m_ticks_style.color; 424 m_ticks_sep.add(mat); 425 426 draw_style* ds = new draw_style; 427 ds->style = draw_lines; 428 ds->line_pattern = m_ticks_style.patte 429 ds->line_width = m_ticks_style.width; 430 m_ticks_sep.add(ds); 431 432 m_ticks_sep.add(vtxs); 433 } else { 434 delete vtxs; 435 } 436 437 } 438 439 // labels scene graph : 440 m_labels_sep.clear(); 441 if(m_labels_style.visible && tick_number ) 442 m_labels_seps.clear(); 443 m_labels_xs.clear(); 444 m_labels_mtxs.clear(); 445 446 rgba* mat = new rgba(); 447 mat->color = m_labels_style.color; 448 m_labels_sep.add(mat); 449 450 float text_size = label_height*m_labels_ 451 std::string font = m_labels_style.font.v 452 453 if(font==font_hershey()) { 454 draw_style* ds = new draw_style; 455 ds->style = draw_lines; 456 ds->line_pattern = m_labels_style.line 457 ds->line_width = m_labels_style.line_w 458 m_labels_sep.add(ds); 459 } else { 460 m_labels_sep.add(new normal); 461 } 462 463 vec3f X = m_labels_style.x_orientation.v 464 vec3f Y = m_labels_style.y_orientation.v 465 X.normalize(); 466 Y.normalize(); 467 vec3f Z;X.cross(Y,Z); 468 Z.cross(X,Y); 469 mat4f scale_rot(X.v0(),Y.v0(),Z.v0(),0, 470 X.v1(),Y.v1(),Z.v1(),0, 471 X.v2(),Y.v2(),Z.v2(),0, 472 0,0,0,1); 473 scale_rot.mul_scale(text_size,text_size, 474 475 bool bin_center = (m_labels_style.option 476 477 vec3f vec;float xx; 478 {unsigned int number = tick_number; 479 for(unsigned int index=0;index<number;in 480 481 if(bin_center) { //label at the center 482 if(index==(number-1)) continue; 483 xx = 0.5f*(coords.values()[index]+co 484 } else { // label on tick : 485 xx = coords.values()[index]; 486 } 487 488 vec.set_value(xx,-label_to_axis,0); 489 vec += m_labels_style.translation.valu 490 491 separator* sep = new separator; 492 m_labels_sep.add(sep); 493 494 matrix* _tsf = 495 add_string_opt(*sep, 496 font, 497 m_labels_style.font_m 498 m_labels_style.encodi 499 m_labels_style.smooth 500 labels.values()[index 501 vec[0],vec[1],vec[2], 502 scale_rot, 503 m_labels_style.hjust, 504 m_labels_style.vjust, 505 m_ttf); 506 if(_tsf) { 507 m_labels_seps.push_back(sep); 508 m_labels_xs.push_back(xx); 509 m_labels_mtxs.push_back(_tsf); 510 } 511 }} 512 513 if(labels_no_overlap_automated.value()) 514 m_labels_seps.clear(); 515 m_labels_xs.clear(); 516 m_labels_mtxs.clear(); 517 } 518 519 m_mag_sep.clear(); 520 if( magnitude.value() && m_mag_style.visib 521 rgba* mat = new rgba(); 522 mat->color = m_mag_style.color; 523 m_mag_sep.add(mat); 524 525 char string[64]; 526 if(magnitude>=0) 527 snpf(string,sizeof(string),"x10+%d",ma 528 else 529 snpf(string,sizeof(string),"x10-%d",:: 530 531 vec3f vec(width*1.03f,0,0); 532 vec += m_mag_style.translation.value(); 533 534 float text_size = label_height*0.8f * m_ 535 std::string font = m_mag_style.font.valu 536 537 if(font==font_hershey()) { 538 draw_style* ds = new draw_style; 539 ds->style = draw_lines; 540 ds->line_pattern = m_mag_style.line_pa 541 ds->line_width = m_mag_style.line_widt 542 m_mag_sep.add(ds); 543 } 544 545 add_string(m_mag_sep, 546 font, 547 m_mag_style.font_mode 548 m_mag_style.encoding. 549 m_mag_style.smoothing 550 string, 551 vec[0],vec[1],vec[2], 552 m_mag_style.x_orienta 553 m_mag_style.y_orienta 554 text_size, 555 m_mag_style.hjust, 556 m_mag_style.vjust, 557 m_ttf); 558 } 559 560 // title scene graph :if(update_title) { 561 m_title_sep.clear(); 562 if(title.value().size() && m_title_style.v 563 rgba* mat = new rgba(); 564 mat->color = m_title_style.color; 565 m_title_sep.add(mat); 566 567 float text_size = title_height*m_title_s 568 std::string font = m_title_style.font.va 569 570 if(font==font_hershey()) { 571 draw_style* ds = new draw_style; 572 ds->style = draw_lines; 573 ds->line_pattern = m_title_style.line_ 574 ds->line_width = m_title_style.line_wi 575 m_title_sep.add(ds); 576 } else { 577 m_title_sep.add(new normal); 578 } 579 580 float xx = 0; //left 581 if(title_hjust==center) { 582 xx = width/2; 583 } else if(title_hjust==right) { 584 xx = width; 585 } 586 587 vec3f vec(xx,-title_to_axis,0); 588 vec += m_title_style.translation.value() 589 590 //std::cout << "debug : axis : update_ti 591 // << " pos : " << vec[0] << " 592 // << std::endl; 593 594 add_string(m_title_sep, 595 font, 596 m_title_style.font_mo 597 m_title_style.encodin 598 m_title_style.smoothi 599 title.value(), 600 vec[0],vec[1],vec[2], 601 m_title_style.x_orien 602 m_title_style.y_orien 603 text_size, 604 m_title_style.hjust, 605 m_title_style.vjust, 606 m_ttf); 607 } 608 609 } 610 611 public: //style 612 void reset_style(bool a_geom = false) { 613 //reset fields that are considered as part 614 615 ////////////////////////////////////////// 616 // we do not touch : 617 ////////////////////////////////////////// 618 //width 619 //minimum_value 620 //maximum_value 621 //labels_enforced 622 //tick_number 623 //magnitude 624 //time_labels 625 //time_format 626 //time_offset 627 //time_offset_is_GMT 628 //labels 629 //values 630 //coords 631 //sub_coords 632 633 ////////////////////////////////////////// 634 divisions = 510; 635 modeling = tick_modeling_hippo(); 636 tick_up = true; 637 is_log = false; 638 title.value().clear(); 639 640 labels_no_overlap_automated = true; 641 labels_gap = 0.02f; 642 643 if(a_geom) { 644 ////////////////////////////////////////// 645 // Take PAW default : 646 float YSIZ = 20; //page height 647 float YMGL = 2; //low y margin (to data f 648 float YMGU = 2; //up y margin (to data fr 649 float VSIZ = 0.28F; //tick label character 650 float YVAL = 0.4F; //y distance of x tick 651 float XTIC = 0.3F; //y length of X axis t 652 float YLAB = 0.8F; //y distance of x title 653 float ASIZ = 0.28F; // axis title (label) 654 655 float hData = YSIZ-YMGL-YMGU; 656 657 // To map data space to width : 658 float to1 = width/hData; 659 660 float vsiz = VSIZ * to1; //0.0175F 661 float yval = YVAL * to1; //0.025F 662 float xtic = XTIC * to1; //0.01875F 663 float ylab = YLAB * to1; //0.05F 664 float asiz = ASIZ * to1; //0.0175F 665 666 //sf 667 tick_length = xtic; 668 label_to_axis = yval; 669 label_height = vsiz; 670 671 // The axis title is the PAW axis label. 672 // It is right justified at the end of axi 673 // (at end right for XY_X, at end top for 674 title_to_axis = ylab; 675 title_height = asiz; 676 } 677 678 title_hjust = right; 679 680 ////////////////////////////////////////// 681 // setup styles : 682 m_line_style = line_style(); 683 m_ticks_style = line_style(); 684 m_labels_style = text_style(); 685 m_mag_style = text_style(); 686 m_title_style = text_style(); 687 688 m_line_style.color = colorf_black(); 689 m_ticks_style.color = colorf_black(); 690 691 m_labels_style.color = colorf_black(); 692 m_labels_style.font = font_hershey(); 693 m_labels_style.encoding = encoding_PAW(); 694 695 m_mag_style.color = colorf_black(); 696 m_mag_style.font = font_hershey(); 697 m_mag_style.encoding = encoding_PAW(); 698 699 m_title_style.color = colorf_black(); 700 m_title_style.font = font_hershey(); 701 m_title_style.encoding = encoding_PAW(); 702 } 703 704 typedef std::pair<std::string,std::string> s 705 typedef std::vector<style_item_t> style_t; 706 bool set_from_style(std::ostream& a_out,cons 707 style_t::const_iterator it; 708 for(it=a_style.begin();it!=a_style.end();+ 709 const std::string& key = (*it).first; 710 const std::string& sv = (*it).second; 711 //::printf("debug : axis::set_from_style 712 //if(key=="reset") {} 713 714 // not part of style : 715 //width 716 //minimum_value 717 //maximum_value 718 //labels_enforced 719 //tick_number 720 //magnitude 721 //title 722 //time_labels 723 //time_format 724 //time_offset 725 //time_offset_is_GMT 726 //labels 727 //values 728 //coords 729 //sub_coords 730 731 if(key=="divisions") { 732 unsigned int v; 733 if(!to(sv,v)) {style_failed(a_out,key, 734 divisions = v; 735 } else if(key=="modeling") { 736 modeling = sv; 737 } else if(key=="is_log") { 738 bool v; 739 if(!to(sv,v)) {style_failed(a_out,key, 740 is_log = v; 741 742 } else if(key=="tick_up") { 743 bool v; 744 if(!to(sv,v)) {style_failed(a_out,key, 745 tick_up = v; 746 } else if(key=="tick_length") { 747 float v; 748 if(!to(sv,v)) {style_failed(a_out,key, 749 tick_length = v; 750 751 } else if(key=="title") { 752 title = sv; 753 } else if(key=="title_to_axis") { 754 float v; 755 if(!to(sv,v)) {style_failed(a_out,key, 756 title_to_axis = v; 757 } else if(key=="title_height") { 758 float v; 759 if(!to(sv,v)) {style_failed(a_out,key, 760 title_height = v; 761 } else if(key=="title_hjust") { 762 hjust v; 763 if(!shjust(sv,v)) 764 {style_failed(a_out,key,sv);return f 765 title_hjust = v; 766 767 } else if(key=="label_to_axis") { 768 float v; 769 if(!to(sv,v)) {style_failed(a_out,key, 770 label_to_axis = v; 771 } else if(key=="label_height") { 772 float v; 773 if(!to(sv,v)) {style_failed(a_out,key, 774 label_height = v; 775 776 } else if(key=="labels_no_overlap_automa 777 bool v; 778 if(!to(sv,v)) {style_failed(a_out,key, 779 labels_no_overlap_automated = v; 780 } else if(key=="labels_gap") { 781 float v; 782 if(!to(sv,v)) {style_failed(a_out,key, 783 labels_gap = v; 784 785 } else { 786 a_out << "axis::set_from_style :" 787 << " unknown key " << key << "." 788 << std::endl; 789 } 790 } 791 return true; 792 } 793 794 void set_encoding(const std::string& a_value 795 labels_style().encoding = a_value; 796 mag_style().encoding = a_value; 797 title_style().encoding = a_value; 798 } 799 protected: 800 float get_overlap(std::ostream& a_out,bool& 801 a_overlap = false; 802 std::vector<float> x_mins; 803 std::vector<float> x_maxs; 804 {size_t index = 0; 805 bbox_action _action(a_out); 806 tools_vforcit(separator*,m_labels_seps,it) 807 _action.reset(); 808 (*it)->bbox(_action); 809 if(_action.end()) { 810 float dx,dy,dz; 811 if(_action.box().get_size(dx,dy,dz)) { 812 if(dx>0) { 813 x_mins.push_back(m_labels_xs[index 814 x_maxs.push_back(m_labels_xs[index 815 } 816 } 817 } 818 index++; 819 }} 820 float dx_overlap = 0; 821 {size_t number = x_mins.size(); 822 for(size_t index=1;index<number;index++) { 823 float dx = x_mins[index]-x_maxs[index-1] 824 if(dx<0) { 825 a_overlap = true; 826 dx_overlap = mx(dx_overlap,-dx); 827 } 828 }} 829 return dx_overlap; 830 } 831 void avoid_labels_overlap(std::ostream& a_ou 832 bool overlap; 833 float first_scale = 1; 834 float first_overlap = get_overlap(a_out,ov 835 if(overlap) { 836 float second_scale = 1.1f; // greater th 837 {tools_vforcit(matrix*,m_labels_mtxs,it) 838 (*it)->mul_scale(second_scale,second_s 839 }} 840 float second_overlap = get_overlap(a_out 841 if(overlap) { 842 // first_overlap = a*first_scale+b 843 // second_overlap = a*second_scale+b 844 float a = (second_overlap-first_overlap)/(se 845 float b = first_overlap-a*first_scale; 846 //float wanted_scale = -b/a; //zero over 847 float wanted_gap = width.value()*label 848 float wanted_scale = (a==0.0f) ? 1 : ( 849 if(wanted_scale<=0) wanted_scale = 1; 850 wanted_scale /= second_scale; 851 {tools_vforcit(matrix*,m_labels_mtxs,it 852 (*it)->mul_scale(wanted_scale,wanted 853 }} 854 } else { //it should not happen. 855 tools_vforcit(matrix*,m_labels_mtxs,it 856 (*it)->mul_scale(1.0f/second_scale,1 857 } 858 } 859 } 860 } 861 862 static void style_failed(std::ostream& a_out 863 const std::string& 864 const std::string& 865 a_out << "axis::set_from_style :" 866 << " failed for key " << sout(a_key) 867 << " and value " << sout(a_value) << 868 << std::endl; 869 } 870 protected: 871 //////////////////////////////////////////// 872 /// Hippodraw tick modeling //////////////// 873 //////////////////////////////////////////// 874 void compute_ticks_hippo() { 875 // input fields : 876 // minimum_value 877 // maximum_value 878 // is_log 879 // output fields : 880 // values 881 // coords 882 // sub_coords 883 // labels (if labels_enforced is false) 884 // tick_number 885 886 887 float mn = minimum_value; 888 float mx = maximum_value; 889 890 bool a_is_log = is_log; 891 if(a_is_log) { 892 if((mn<=0) || (mx<=0) ) a_is_log = false 893 } 894 895 float magxxx,y,yr,startTick,tickSize; 896 float pmag; 897 char pstr[10] = ""; 898 char tmp[10]; 899 900 unsigned int tick_num = 0; 901 std::vector<float> tick_values; 902 std::vector<std::string> tick_labels; 903 904 // need include <float.h> which does not e 905 //NUM_FUZZ DBL_EPSILON*4 906 float NUM_FUZZ = 0.01f; 907 908 if (mn >= mx) { 909 if(tick_number) { 910 tick_number.value(0); 911 values.clear(); 912 coords.clear(); 913 sub_coords.clear(); 914 labels.clear(); 915 } 916 if(magnitude.value()) magnitude.value(0) 917 m_sub_ticks.clear(); 918 return; 919 } 920 921 if (!a_is_log) { 922 923 tickSize = calculate_ticks_hippo(mx-mn, 924 startTick = fceil( mn / tickSize) * tick 925 926 if (ffabs(magxxx) <= 3) 927 pmag = 0.0; 928 else 929 pmag = startTick != 0.0 ? ffloor(flog1 930 931 snpf(pstr,sizeof(pstr),"%%1.%df",(int)ma 932 933 y = startTick; 934 while (y <= mx*(1.0+NUM_FUZZ)) { 935 936 yr = ffloor(y/fpow(10,magxxx) + 0.5F); 937 938 snpf(tmp,sizeof(tmp),pstr,yr*fpow(10,m 939 940 {float val = yr * fpow(10.0,magxxx); 941 if((val>=mn)&&(val<=mx)) { //G.Barrand 942 tick_values.push_back(val); 943 tick_labels.push_back(tmp); 944 tick_num++; 945 }} 946 947 y += tickSize; 948 } 949 if (ffabs(magxxx) <= 3.0) magxxx = 0.0; 950 951 } else { 952 953 if (mn <= 0) { 954 if(tick_number) { 955 tick_number.value(0); 956 values.clear(); 957 coords.clear(); 958 sub_coords.clear(); 959 labels.clear(); 960 } 961 if(magnitude.value()) magnitude.value( 962 m_sub_ticks.clear(); 963 return; 964 } 965 966 int nLogTicks; 967 float logTicks[5]; 968 float magStep; 969 970 float maghigh = fceil(flog10(mx)); 971 float maglow = ffloor(flog10(mn)); 972 float magrng = maghigh - maglow; 973 974 if (magrng <=3) { 975 nLogTicks = 3; 976 logTicks[0] = 1.0; 977 logTicks[1] = 2.0; 978 logTicks[2] = 5.0; 979 magStep = 1.0; 980 } else { 981 nLogTicks = 1; 982 logTicks[0] = 1.0; 983 magStep = magrng <= 7 ? 1.0F : 2.0 984 } 985 986 pmag = (nLogTicks == 3 && (ffabs(maglow) 987 maglow : 0; 988 989 magxxx = maglow; 990 int i = 0; 991 while ((y=logTicks[i]*fpow(10,magxxx)) < 992 if (y >= mn) { 993 994 // be careful: there is a bug in the 995 // routine when you do, eg. printf 996 if ((magxxx-pmag) > 4 || (magxxx-pma 997 ::strcpy(pstr,"%1.0e"); 998 } else { 999 snpf(pstr,sizeof(pstr), 1000 "%%1.%df",(int)((magxxx-pmag 1001 } 1002 snpf(tmp,sizeof(tmp),pstr,y*fpow(10 1003 1004 {float val = flog10(y); 1005 if((val>=flog10(mn))&&(val<=flog10( 1006 tick_values.push_back(val); 1007 tick_labels.push_back(tmp); 1008 tick_num++; 1009 }} 1010 1011 } 1012 1013 i++; 1014 if (i>=nLogTicks) { 1015 i = 0; 1016 magxxx += magStep; 1017 } 1018 } 1019 1020 mn = flog10(mn); 1021 mx = flog10(mx); 1022 } 1023 1024 float range = mx - mn; 1025 1026 // it is assumes that tick_values are ord 1027 tick_number.value(tick_num); 1028 values.clear(); 1029 coords.clear(); 1030 for(unsigned int index=0;index<tick_num;i 1031 float val = tick_values[index]; 1032 float coord = width * (val-mn)/range; 1033 values.add(val); 1034 coords.add(coord); 1035 } 1036 1037 if(labels_enforced) { 1038 size_t n = labels.size(); 1039 if(tick_num>n) { 1040 for(size_t index=n;index<tick_num;ind 1041 } 1042 } else { 1043 labels = tick_labels; 1044 } 1045 1046 magnitude.value((int)pmag); 1047 1048 sub_coords.clear(); 1049 m_sub_ticks.clear(); 1050 } 1051 1052 static float calculate_ticks_hippo(float aS 1053 unsigned int MIN_TICKS = 4; 1054 1055 if (aSize <= 0.0) { 1056 //printf ("CalculateTicks : bad value \ 1057 aSize = ffabs(aSize); 1058 if (aSize == 0.0) aSize = 1.0; 1059 } 1060 1061 a_mag = ffloor(flog10(aSize)); 1062 if (aSize/fpow(10.0,a_mag) < MIN_TICKS) ( 1063 1064 // now fit the max number of ticks into t 1065 1066 float tickSize; 1067 int tickIndex; 1068 static const float goodTicks[] = {10.0, 5 1069 for(tickIndex = 0; 1070 aSize/(tickSize=goodTicks[tickIndex]*f 1071 tickIndex++){} 1072 1073 if (tickIndex == 0) a_mag++; 1074 1075 return tickSize; 1076 } 1077 1078 /////////////////////////////////////////// 1079 /// HPLOT tick modeling /////////////////// 1080 /////////////////////////////////////////// 1081 /////////////////////////////////////////// 1082 void compute_ticks_HPLOT(std::ostream& a_ou 1083 // Controlled by fields : 1084 // minimum_value 1085 // maximum_value 1086 // divisions 1087 // is_log 1088 // Set value on fields : 1089 // values 1090 // coords 1091 // labels (if labels_enforced is false 1092 // tick_number 1093 1094 float mn = minimum_value; 1095 float mx = maximum_value; 1096 1097 bool a_is_log = is_log; 1098 if(a_is_log) { 1099 if((mn<=0) || (mx<=0) ) a_is_log = fals 1100 } 1101 1102 // Use hplot::axis to get the ticks and s 1103 // and the labels text. 1104 1105 double xmin = 0; 1106 double ymin = 0; 1107 double xmax = width; 1108 double ymax = 0; 1109 1110 double gridlength = 0; 1111 std::string chopt; 1112 if(a_is_log) chopt += "G"; 1113 1114 std::vector<float> linesGrid; 1115 std::vector<hplot::_text> texts; 1116 1117 hplot::axis sbAxisHPLOT(a_out); 1118 1119 chopt += "S"; 1120 sbAxisHPLOT.set_tick_size(tick_length/wid 1121 1122 if(time_labels.value()) { 1123 chopt += "t"; 1124 sbAxisHPLOT.set_time_format(time_format 1125 sbAxisHPLOT.set_time_offset(time_offset 1126 time_offset 1127 } 1128 1129 // Get ticks : 1130 {double wmin = mn; 1131 double wmax = mx; 1132 int ndiv = divisions; 1133 sbAxisHPLOT.set_title(""); 1134 sbAxisHPLOT.paint(xmin,ymin,xmax,ymax, 1135 wmin,wmax,ndiv, //Modif 1136 chopt,gridlength,false, 1137 m_sub_ticks,linesGrid,t 1138 1139 if(a_is_log) { 1140 mn = flog10(mn); 1141 mx = flog10(mx); 1142 } 1143 1144 float range = mx - mn; 1145 1146 size_t tick_num = texts.size(); 1147 1148 // HPLOT stores the magnitude on the last 1149 magnitude.value(0); 1150 if(tick_num) { 1151 int pmag; 1152 if(::sscanf(texts[tick_num-1].fString.c 1153 magnitude.value(pmag); 1154 tick_num--; 1155 } 1156 } 1157 1158 tick_number.value(uint32(tick_num)); 1159 values.clear(); 1160 coords.clear(); 1161 for(size_t index=0;index<tick_num;index++ 1162 float coord = (float)texts[index].fX; 1163 //NOTE : are we sure that val is in [mn 1164 float val = (coord/width.value()) * ran 1165 coords.add(coord); 1166 values.add(val); 1167 } 1168 1169 if(labels_enforced) { 1170 size_t n = labels.size(); 1171 if(tick_num>n) { 1172 for(size_t index=n;index<tick_num;ind 1173 } 1174 } else { 1175 labels.clear(); 1176 for(size_t index=0;index<tick_num;index 1177 labels.add(texts[index].fString); 1178 } 1179 } 1180 1181 {sub_coords.clear(); 1182 size_t num = m_sub_ticks.size()/4; 1183 size_t pos = 0; 1184 for(size_t index=0;index<num;index++) { 1185 float coord = m_sub_ticks[pos]; 1186 pos += 4; 1187 bool found = false; 1188 for(size_t i=0;i<tick_num;i++) { 1189 if((float)texts[i].fX==coord) { 1190 found = true; 1191 break; 1192 } 1193 } 1194 if(!found) { //not a main tick 1195 sub_coords.add(coord); 1196 } 1197 }} 1198 } 1199 1200 protected: 1201 const base_freetype& m_ttf; 1202 1203 group m_group; 1204 1205 separator m_line_sep; 1206 separator m_ticks_sep; 1207 separator m_labels_sep; 1208 separator m_mag_sep; 1209 separator m_title_sep; 1210 1211 sg::line_style m_line_style; 1212 sg::line_style m_ticks_style; 1213 text_style m_labels_style; 1214 text_style m_mag_style; 1215 text_style m_title_style; 1216 1217 std::vector<float> m_sub_ticks; //n*(2+2) 1218 1219 std::vector<separator*> m_labels_seps; 1220 std::vector<float> m_labels_xs; 1221 std::vector<matrix*> m_labels_mtxs; 1222 }; 1223 1224 }} 1225 1226 #endif