00001
00012
00013 #ifdef HAVE_CONFIG_H
00014 #include "config.h"
00015 #endif
00016
00017
00018 #ifdef _MSC_VER
00019 #include "msdevstudio/MSconfig.h"
00020 #define finite _finite
00021 #endif
00022
00023 #include "AxisRepBase.h"
00024
00025 #include "axes/AxisModelBase.h"
00026 #include "graphics/Color.h"
00027 #include "graphics/DataView.h"
00028 #include "pattern/string_convert.h"
00029 #include "transforms/PeriodicBinaryTransform.h"
00030
00031 #include <cmath>
00032 #include <cassert>
00033 #include <cstdio>
00034
00035 using std::max;
00036 using std::min;
00037 using std::string;
00038 using std::vector;
00039 using std::sprintf;
00040 #ifdef __USE_ISOC99
00041 using std::isfinite;
00042 #endif
00043
00044 using namespace hippodraw;
00045
00046 AxisRepBase::AxisRepBase()
00047 : m_sci_note_x(false),
00048 m_sci_note_y(false),
00049 m_axis_x_origin (0.),
00050 m_axis_y_origin ( 0.0),
00051 m_axis_width ( 0.0 ),
00052 m_axis_height ( 0.0 ),
00053 m_font_size( 1.0 ),
00054 m_x_tick_font_size ( 1.0 ),
00055 m_y_tick_font_size ( 1.0 ),
00056 m_x_font_size( 1.0 ),
00057 m_y_font_size( 1.0 ),
00058 m_xLabelFont( 0 ),
00059 m_yLabelFont( 0 ),
00060 m_zLabelFont( 0 ),
00061 m_titleFont( 0 ),
00062 m_draw_titles( true )
00063 {
00064 }
00065
00066 AxisRepBase::AxisRepBase( const AxisRepBase & axis_rep )
00067 : m_sci_note_x(axis_rep.m_sci_note_x),
00068 m_sci_note_y(axis_rep.m_sci_note_y),
00069 m_axis_x_origin( axis_rep.m_axis_x_origin ),
00070 m_axis_y_origin( axis_rep.m_axis_y_origin ),
00071 m_axis_width( axis_rep.m_axis_width ),
00072 m_axis_height( axis_rep.m_axis_height ),
00073 m_font_size( axis_rep.m_font_size ),
00074 m_x_font_size( axis_rep.m_x_font_size ),
00075 m_y_font_size( axis_rep.m_y_font_size ),
00076 m_xLabelFont( axis_rep.m_xLabelFont ),
00077 m_yLabelFont( axis_rep.m_yLabelFont ),
00078 m_zLabelFont( axis_rep.m_zLabelFont ),
00079 m_titleFont( axis_rep.m_titleFont ),
00080 m_draw_titles( axis_rep.m_draw_titles )
00081 {
00082 }
00083
00084 AxisRepBase::~AxisRepBase()
00085 {
00086 delete m_xLabelFont;
00087 delete m_yLabelFont;
00088 delete m_zLabelFont;
00089 delete m_titleFont;
00090 }
00091
00092 void
00093 AxisRepBase::
00094 initAxisRect( ViewBase & view )
00095 {
00096 const Rect & rect = view.getUserRect();
00097
00098 m_axis_x_origin = rect.getX();
00099 m_axis_y_origin = rect.getY();
00100 m_axis_width = rect.getWidth();
00101 m_axis_height = rect.getHeight();
00102 }
00103
00104 void
00105 AxisRepBase::
00106 beginPlot( ViewBase & view )
00107 {
00108 initAxisRect( view );
00109 }
00110
00111 void AxisRepBase::setDrawTitles( bool set )
00112 {
00113 m_draw_titles = set;
00114 }
00115
00116 void
00117 AxisRepBase::
00118 drawTitle ( ViewBase & base, const std::string & title )
00119 {
00120
00121 DataView & view = dynamic_cast < DataView & > ( base );
00122
00123
00124 #ifdef HAVE_TEX_UTILS
00125 if (String::ci_find(title, "tex:")==0) {
00126 string tex_snippet = title.substr(4);
00127 view.drawLatex ( tex_snippet, 1 );
00128 }
00129
00130 else {
00131 #endif
00132 const Rect & marginRect = view.getMarginRect();
00133 float mx = marginRect.getX();
00134 Rect rect = view.getDrawRect ();
00135 float mw = rect.getWidth();
00136
00137 double x_font_size = ( 1.3 * mw ) / title.size();
00138 m_font_size = min(x_font_size,12.0);
00139
00140 double one = 1.0;
00141 m_font_size = max ( m_font_size, one );
00142
00143 float x = mx + 0.5 * marginRect.getWidth ();
00144 float y = 2.0;
00145
00146 if ( m_titleFont != 0 ) {
00147 view.drawText ( title, x, y, 0.0, 0.0, 'c', 't', false,
00148 m_titleFont );
00149 } else {
00150 view.drawText ( title, x, y, m_font_size, 0.0, 'c', 't', false );
00151 }
00152
00153 #ifdef HAVE_TEX_UTILS
00154 }
00155 #endif
00156 }
00157
00158 void
00159 AxisRepBase::
00160 setXFontSize ( const AxisModelBase & axisModel,
00161 ViewBase & view )
00162 {
00163 Rect draw_rect = view.getDrawRect();
00164 m_x_tick_font_size = min( ( draw_rect.getWidth() ) * 0.040, 12.0 );
00165 double one = 1.0;
00166 m_x_tick_font_size = max ( m_x_tick_font_size, one );
00167
00168 AxisLoc location = axisModel.getScaleLocation();
00169
00170 if ( location == PLOTBOTTOM )
00171 {
00172 m_x_font_size = min( (double)m_x_tick_font_size,
00173 ( m_axis_y_origin -
00174 draw_rect.getY() ) / 2.0 );
00175 }
00176 else if ( location == PLOTTOP )
00177 {
00178 m_x_font_size = min( (double)m_x_tick_font_size,
00179 ( draw_rect.getHeight() -
00180 m_axis_height -
00181 ( m_axis_y_origin
00182 - draw_rect.getY() ) ) /2.0 );
00183 }
00184 }
00185
00186 void
00187 AxisRepBase::
00188 setYFontSize ( const AxisModelBase & axisModel,
00189 ViewBase & view )
00190 {
00191 assert ( m_y_tick_font_size > 0 );
00192
00193 Rect draw_rect = view.getDrawRect();
00194 double height = draw_rect.getHeight ();
00195 double size = height * 0.040;
00196 size = std::min ( size, 11.0 );
00197 double one = 1.0;
00198 m_y_tick_font_size = std::max ( size, one );
00199
00200 assert ( m_y_tick_font_size > 0 );
00201 const vector<AxisTick> & labels = axisModel.getTicks ( );
00202 if ( labels.empty () == true ) return;
00203
00204 if ( axisModel.getScaleLocation() & PLOTLEFT )
00205 {
00206 float yr;
00207
00208 if ( m_draw_titles &&
00209 axisModel.getLabelLocation() & PLOTLEFT ) {
00210 yr = 14;
00211 }
00212 else {
00213 yr = 0;
00214 }
00215 const AxisTick & tick = labels.back ( );
00216 m_y_font_size = min ( m_y_tick_font_size,
00217 ( m_axis_x_origin -
00218 draw_rect.getX() - yr )
00219 / tick.content().size() );
00220 }
00221 else if ( axisModel.getScaleLocation() & PLOTRIGHT )
00222 {
00223
00224 float yr;
00225 if ( m_draw_titles &&
00226 axisModel.getLabelLocation() & PLOTRIGHT ) {
00227 yr = 14;
00228 } else {
00229 yr = 0;
00230 }
00231
00232 m_y_font_size = min( m_y_tick_font_size,
00233 ( draw_rect.getWidth() -
00234 m_axis_width -
00235 ( m_axis_x_origin -
00236 draw_rect.getX() ) - yr )
00237 / labels[labels.size() - 1].content().size() );
00238 }
00239 }
00240
00241 void
00242 AxisRepBase::
00243 setZFontSize ( const AxisModelBase & axisModel,
00244 ViewBase & view )
00245 {
00246 AxisLoc location = axisModel.getScaleLocation();
00247 Rect draw_rect = view.getDrawRect();
00248 if ( location == PLOTBOTTOM )
00249 {
00250 m_z_font_size = min( (double)m_font_size,
00251 ( m_axis_y_origin -
00252 draw_rect.getY() ) / 2.0 );
00253 }
00254 else if ( location == PLOTTOP )
00255 {
00256 m_z_font_size = min( (double)m_font_size,
00257 ( draw_rect.getHeight() -
00258 m_axis_height -
00259 ( m_axis_y_origin
00260 - draw_rect.getY() ) ) /2.0 );
00261 }
00262 }
00263
00264 void
00265 AxisRepBase::
00266 drawXLabels ( const AxisModelBase & axisModel,
00267 ViewBase & base, const std::string & x_label )
00268 {
00269 DataView & view = dynamic_cast < DataView & > ( base );
00270
00271
00272
00273 const vector< AxisTick > & ticks = axisModel.getTicks();
00274 m_sci_note_x=false;
00275 int mid = ticks.size()/2;
00276 double ref = ticks[mid].value();
00277 double range = ticks[mid+1].value()-ref;
00278 if (fabs(ref/range)>1e6) m_sci_note_x=true;
00279
00280
00281 #ifdef HAVE_TEX_UTILS
00282 if (String::ci_find(x_label, "tex:")==0) {
00283 string tex_snippet = x_label.substr(4);
00284 if (m_sci_note_x) {
00285 tex_snippet+="-"+ticks[mid].content();
00286 if (axisModel.needPMag()) {
00287
00288 tex_snippet+="\\times 10^"+String::convert ( static_cast <int> (axisModel.getPMag()) );
00289 }
00290 }
00291 view.drawLatex ( tex_snippet, 2 );
00292 }
00293
00294 else {
00295 #endif
00296 std::string label;
00297 if (m_sci_note_x) {
00298 label = x_label+" - "+ticks[mid].content();
00299 }
00300 else {
00301 label = x_label;
00302 }
00303
00304 float x = 0., y = 0.;
00305 Rect draw_rect = view.getDrawRect ();
00306 float draw_h = draw_rect.getHeight ();
00307 float draw_w = draw_rect.getWidth ();
00308
00309 const Rect & margin_rect = view.getMarginRect ();
00310 float margin_x = margin_rect.getX ();
00311 float margin_w = margin_rect.getWidth ();
00312
00313 x = margin_x + 0.5 * margin_w;
00314
00315 float tmp = 0.045 * draw_w;
00316 tmp = max ( tmp, 1.0f );
00317 m_x_font_size = min ( tmp, static_cast<float>( 18.0 ) );
00318 assert ( m_x_font_size > 0 );
00319
00320 double ratio = draw_w / ( label.size() ) * 2;
00321 m_x_font_size = std::min ( m_x_font_size, ratio );
00322 assert ( m_x_font_size > 0 );
00323 double one = 2.0;
00324 m_x_font_size = std::max ( m_x_font_size, one );
00325
00326 assert ( m_x_font_size > 0 );
00327 if ( axisModel.getLabelLocation() & PLOTBOTTOM )
00328 {
00329 if ( m_xLabelFont != 0 ) {
00330 y = draw_h - 1.5*m_xLabelFont->pointSize()-6.0;
00331 view.drawText ( label, x, y, 0., 0.0, 'c', 't',
00332 false, m_xLabelFont );
00333 } else {
00334 y = draw_h - m_x_font_size - 6.0;
00335 view.drawText ( label, x, y, m_x_font_size, 0.0, 'c', 't', false );
00336 }
00337 }
00338 else if ( axisModel.getLabelLocation() & PLOTTOP )
00339 {
00340 y = 1.0;
00341 if ( m_xLabelFont != 0 ) {
00342
00343 view.drawText ( label, x, y, 0.0, 0.0, 'c', 't',
00344 false, m_xLabelFont );
00345 } else {
00346
00347 view.drawText ( label, x, y, m_x_font_size, 0.0, 'c', 't', false );
00348 }
00349 }
00350
00351
00352
00353
00354 if ( (m_sci_note_x) && (axisModel.needPMag() ) ){
00355 if ( m_xLabelFont == NULL ) {
00356 x = x+0.27 * m_x_font_size * label.size();
00357 y = y+0.2 * m_x_font_size;
00358 view.drawText ( " x10", x, y, m_x_font_size*0.8, 0.0, 'c', 't', false );
00359
00360 double pmag = axisModel.getPMag();
00361 int i = static_cast < int > ( pmag );
00362 const string text = String::convert ( i );
00363 x += 1.0 * m_x_font_size ;
00364 y -= 0.4 * m_x_font_size;
00365 view.drawText ( text, x, y, m_x_font_size*0.8, 0.0, 'c', 't', false );
00366 } else {
00367 x = x+0.4 * m_xLabelFont->pointSize() * label.size();
00368 view.drawText ( " x10", x, y, 0.0, 0.0, 'c', 't', false, m_xLabelFont );
00369
00370 double pmag = axisModel.getPMag();
00371 int i = static_cast < int > ( pmag );
00372 const string text = String::convert ( i );
00373 x += 1.6 * m_xLabelFont->pointSize() ;
00374 y -= 0.4 * m_xLabelFont->pointSize();
00375 view.drawText ( text, x, y, 0.0, 0.0, 'c', 't', false, m_xLabelFont );
00376 }
00377 }
00378 #ifdef HAVE_TEX_UTILS
00379 }
00380 #endif
00381
00382 }
00383 void
00384 AxisRepBase::
00385 drawYLabels ( const AxisModelBase & axisModel,
00386 ViewBase & base, const std::string & y_label )
00387 {
00388 DataView & view = dynamic_cast < DataView & > ( base );
00389
00390
00391
00392 const vector< AxisTick > & ticks = axisModel.getTicks();
00393 m_sci_note_y=false;
00394 int mid = ticks.size()/2;
00395 double ref = ticks[mid].value();
00396 double range = ticks[mid+1].value()-ref;
00397 if (fabs(ref/range)>1e6) m_sci_note_y=true;
00398
00399
00400 #ifdef HAVE_TEX_UTILS
00401
00402 if (String::ci_find(y_label, "tex:")==0) {
00403 string tex_snippet = y_label.substr(4);
00404
00405 if (m_sci_note_y) {
00406 tex_snippet+="-"+ticks[mid].content();
00407 if (axisModel.needPMag()) {
00408
00409 tex_snippet+="\\times 10^"+String::convert ( static_cast <int> (axisModel.getPMag()) );
00410 }
00411 }
00412
00413
00414 view.drawLatex ( tex_snippet, 3 );
00415 }
00416
00417 else {
00418 #endif
00419
00420
00421 std::string label;
00422 if (m_sci_note_y) {
00423 label = y_label+" - "+ticks[mid].content();
00424 }
00425 else {
00426 label = y_label;
00427 }
00428
00429 Rect draw_rect = view.getDrawRect ();
00430
00431 float x = 0., y = 0.;
00432 AxisLoc location = axisModel.getLabelLocation();
00433
00434
00435
00436 float tmp = draw_rect.getHeight() * 0.05;
00437 m_y_font_size = min( tmp, static_cast<float>( 18.0 ) );
00438 m_y_font_size = min( m_y_font_size, draw_rect.getHeight()
00439 / ( label.size() ) * 2 );
00440 double one = 1.0;
00441 m_y_font_size = max ( m_y_font_size, one );
00442 y = view.getMarginRect().getY() +
00443 view.getMarginRect().getHeight() *0.5;
00444
00445 if ( location & PLOTLEFT )
00446 {
00447 x = 2.0;
00448 if ( m_yLabelFont != 0 ) {
00449 view.drawText ( label, x, y, 0.0, 90.0, 'c', 't',
00450 false, m_yLabelFont );
00451 } else {
00452 view.drawText ( label, x, y, m_y_font_size, 90.0, 'c', 't', false );
00453 }
00454 }
00455 else if ( location & PLOTRIGHT )
00456 {
00457 x = draw_rect.getWidth() - 2.0;
00458 if ( m_yLabelFont != 0 ) {
00459 view.drawText ( label, x, y, 0.0, -90.0, 'c', 't',
00460 false, m_yLabelFont );
00461 } else {
00462 view.drawText ( label, x, y, m_y_font_size, -90.0, 'c', 't', false );
00463 }
00464 }
00465
00466
00467
00468
00469 if ( (m_sci_note_y) && (axisModel.needPMag() ) ){
00470 if ( m_yLabelFont == NULL ) {
00471 y = y-0.27 * m_y_font_size * label.size();
00472 x = x+0.2 * m_y_font_size;
00473 view.drawText ( " x10", x, y, m_y_font_size*0.8, 90.0, 'c', 't', false );
00474
00475 double pmag = axisModel.getPMag();
00476 int i = static_cast < int > ( pmag );
00477 const string text = String::convert ( i );
00478 x -= 0.4 * m_y_font_size ;
00479 y -= 1.0 * m_y_font_size;
00480 view.drawText ( text, x, y, m_y_font_size*0.8, 90.0, 'c', 't', false );
00481 } else {
00482 y = y-0.4 * m_yLabelFont->pointSize() * label.size();
00483 view.drawText ( " x10", x, y, 0.0, 90.0, 'c', 't', false, m_yLabelFont );
00484
00485 double pmag = axisModel.getPMag();
00486 int i = static_cast < int > ( pmag );
00487 const string text = String::convert ( i );
00488 x -= 0.4 * m_yLabelFont->pointSize() ;
00489 y -= 1.6 * m_yLabelFont->pointSize();
00490 view.drawText ( text, x, y, 0.0, 90.0, 'c', 't', false, m_yLabelFont );
00491 }
00492 }
00493 #ifdef HAVE_TEX_UTILS
00494 }
00495 #endif
00496 }
00497
00498 void
00499 AxisRepBase::
00500 drawReferencePoint( const AxisModelBase & axisModel,
00501 ViewBase & base,
00502 const std::string & ref)
00503 {
00504 if ( axisModel.getScaleLocation() & PLOTBOTTOM )
00505 {
00506 DataView & view = dynamic_cast < DataView & > ( base );
00507
00508 const Rect & margin_rect = view.getMarginRect ();
00509 float x = margin_rect.getX() + margin_rect.getWidth ();
00510
00511 x -= 1 * m_x_tick_font_size * ref.size();
00512
00513 Rect view_rect = view.getDrawRect ();
00514 float y = + view_rect.getHeight ();
00515
00516 view.drawText ( "X Ref:"+ref, x, y, m_x_tick_font_size, 0., 'l', 'b' );
00517 }
00518 else if (axisModel.getScaleLocation() & PLOTLEFT)
00519 {
00520 DataView & view = dynamic_cast < DataView & > ( base );
00521
00522 float x = 2.;
00523 x += m_y_tick_font_size;
00524
00525 const Rect & margin_rect = view.getMarginRect ();
00526 float y = margin_rect.getY() + 0.2 * m_y_tick_font_size;
00527
00528 view.drawText ( "Y Ref:"+ref, x, y, m_y_tick_font_size, 0., 'l', 'b' );
00529 }
00530
00531 }
00532
00533
00534 void
00535 AxisRepBase::
00536 drawXMag ( const AxisModelBase & axisModel,
00537 ViewBase & base , const std::string & mag )
00538 {
00539 DataView & view = dynamic_cast < DataView & > ( base );
00540
00541 const Rect & margin_rect = view.getMarginRect ();
00542 float x = margin_rect.getX() + margin_rect.getWidth ();
00543
00544 double pmag = axisModel.getPMag();
00545 int i = static_cast<int> (pmag);
00546 const string text = String::convert ( i );
00547 x -= 0.8 * m_x_tick_font_size * text.size();
00548
00549 Rect view_rect = view.getDrawRect ();
00550 float y = + view_rect.getHeight ();
00551
00552 view.drawText ( "x10", x, y, 0.75 * m_x_tick_font_size, 0., 'l', 'b' );
00553
00554 x += 1.25 * m_x_tick_font_size ;
00555 y -= 0.5 * m_x_tick_font_size;
00556
00557 if (m_sci_note_x) {
00558 view.drawText( mag, x, y, 0.75 * m_x_tick_font_size, 0., 'l', 'b' );
00559 } else {
00560 view.drawText ( text, x, y, 0.75 * m_x_tick_font_size, 0., 'l', 'b' );
00561 }
00562 }
00563
00564 void
00565 AxisRepBase::
00566 drawYMag ( const AxisModelBase & axisModel,
00567 ViewBase & base, const std::string & mag )
00568 {
00569 DataView & view = dynamic_cast < DataView & > ( base );
00570
00571 float x = 2.;
00572 if ( axisModel.getScaleLocation() & PLOTLEFT ) {
00573 x += m_y_tick_font_size;
00574 }
00575 else {
00576 x -= m_y_tick_font_size;
00577 }
00578
00579 const Rect & margin_rect = view.getMarginRect ();
00580 float y = margin_rect.getY() + 0.5 * m_y_tick_font_size;
00581
00582 view.drawText ( "x10", x, y, m_y_tick_font_size, 0., 'l', 'b' );
00583
00584 double pmag = axisModel.getPMag();
00585 int i = static_cast < int > ( pmag );
00586 const string text = String::convert ( i );
00587 x += 1.75 * m_y_tick_font_size ;
00588 y -= 0.5 * m_y_tick_font_size;
00589
00590 if (m_sci_note_y) {
00591 view.drawText ( mag, x, y, m_y_tick_font_size, 0., 'l', 'b' );
00592 } else {
00593 view.drawText ( text, x, y, m_y_tick_font_size, 0., 'l', 'b' );
00594 }
00595
00596 }
00597
00598 void
00599 AxisRepBase::
00600 drawAxesLines ( TransformBase & transform,
00601 ViewBase & view,
00602 const Range & x_range,
00603 const Range & y_range)
00604 {
00605 const BinaryTransform & t
00606 = dynamic_cast< const BinaryTransform & > ( transform );
00607 vector< double > xv ( 100 );
00608 vector< double > yv ( 100 );
00609 Color black ( 0, 0, 0 );
00610
00611 xv[0] = x_range.low( );
00612 yv[0] = y_range.low( );
00613 for( int i = 1; i < 100; i++)
00614 {
00615 xv[i] = xv[i-1] + ( x_range.high() - x_range.low() )/99;
00616 yv[i] = yv[i-1];
00617 }
00618 t.transform( xv, yv );
00619 view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
00620
00621
00622 xv[0] = x_range.high( );
00623 yv[0] = y_range.low( );
00624 for( int i = 1; i < 100; i++)
00625 {
00626 xv[i] = xv[i-1];
00627 yv[i] = yv[i-1] + ( y_range.high() - y_range.low() )/99; ;
00628 }
00629 t.transform( xv, yv );
00630 view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
00631
00632
00633 xv[0] = x_range.low( );
00634 yv[0] = y_range.high( );
00635 for( int i = 1; i < 100; i++)
00636 {
00637 xv[i] = xv[i-1] + ( x_range.high() - x_range.low() )/99;
00638 yv[i] = yv[i-1];
00639 }
00640
00641 t.transform( xv, yv );
00642 view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
00643
00644
00645 xv[0] = x_range.low( );
00646 yv[0] = y_range.low( );
00647 for( int i = 1; i < 100; i++)
00648 {
00649 xv[i] = xv[i-1];
00650 yv[i] = yv[i-1] + ( y_range.high() - y_range.low() )/99;
00651 }
00652
00653 t.transform( xv, yv );
00654 view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
00655
00656
00657 }
00658
00659
00660
00661 void AxisRepBase::drawGridLines( const AxisModelBase & axisModelX,
00662 const AxisModelBase & axisModelY,
00663 TransformBase & transform,
00664 ViewBase & view )
00665 {
00666 Range x_range = axisModelX.getRange( false );
00667 Range y_range = axisModelY.getRange( false );
00668
00669
00670 const vector< AxisTick > & x_ticks = axisModelX.getTicks();
00671 const vector< AxisTick > & y_ticks = axisModelY.getTicks();
00672
00673 unsigned int nxpoints = 100;
00674 unsigned int nypoints = 100;
00675 vector< double > xv(100), yv(100);
00676
00677 double user_x, user_y;
00678 Color grey( 180, 180, 180 );
00679
00680 BinaryTransform & t
00681 = dynamic_cast< BinaryTransform & > ( transform );
00682
00683 t.validate( x_range, y_range );
00684
00685 if ( x_ticks.empty () == true || y_ticks.empty () == true )
00686 return;
00687
00688
00689 double dx = ( x_range.high() - x_range.low() ) / ( nxpoints - 1 );
00690 double dy = ( y_range.high() - y_range.low() ) / ( nypoints - 1 ) ;
00691
00692
00693
00694
00695
00696 for ( unsigned int i = ( x_range.low() == x_ticks[0].value() )?1:0;
00697 i < x_ticks.size(); i++ )
00698 {
00699 user_x = x_ticks[ i ].value();
00700
00701 for ( unsigned int j = 0; j < nypoints; j++ )
00702 {
00703 user_y = y_range.low() + j * dy;
00704
00705 xv[ j ] = user_x;
00706 yv[ j ] = user_y;
00707
00708 }
00709
00710 t.transform( xv, yv );
00711 view.drawPolyLine ( xv, yv, Line::Dot, grey, 0 );
00712
00713 }
00714
00715
00716
00717
00718
00719 for ( unsigned int j = ( y_range.low() == y_ticks[0].value() )?1:0;
00720 j < y_ticks.size(); j++ )
00721 {
00722 user_y = y_ticks[ j ].value();
00723
00724 for ( unsigned int i = 0; i < nxpoints; i++ )
00725 {
00726 user_x = x_range.low() + i * dx;
00727
00728 xv[ i ] = user_x ;
00729 yv[ i ] = user_y ;
00730 }
00731
00732 t.transform( xv, yv );
00733 view.drawPolyLine( xv, yv, Line::Dot, grey, 0 );
00734 }
00735
00736 return;
00737 }
00738
00739 void
00740 AxisRepBase::
00741 drawXTickLines( const AxisModelBase & axisModelX,
00742 const AxisModelBase & axisModelY,
00743 const TransformBase & transform,
00744 ViewBase & base )
00745 {
00746 DataView & view = dynamic_cast < DataView & > ( base );
00747 AxisLoc loc = axisModelX.getLabelLocation();
00748 assert( loc == PLOTBOTTOM || PLOTTOP );
00749
00750 const vector< AxisTick > & ticks = axisModelX.getTicks();
00751 if ( ticks.empty() == true ) return;
00752
00753 vector< double > xv;
00754 vector< double > yv;
00755
00756 unsigned int size = 4 * ticks.size();
00757 xv.reserve( size );
00758 yv.reserve( size );
00759
00760 const BinaryTransform & t
00761 = dynamic_cast< const BinaryTransform & > ( transform );
00762
00763 const Rect & view_rect = view.getMarginRect();
00764 double tick_length = 0.05 * view_rect.getHeight();
00765 tick_length = min ( tick_length, 8. );
00766 Range yrange = axisModelY.getRange( false );
00767
00768 for ( unsigned int i = 0; i < ticks.size(); i++ )
00769 {
00770 double user_x_start = ticks[i].value ();
00771 double user_x_temp = user_x_start;
00772
00773 double user_by_start = yrange.low();
00774 double user_ty_start = yrange.high();
00775
00776
00777 t.transform ( user_x_start, user_by_start );
00778 t.transform ( user_x_temp, user_ty_start );
00779
00780 double view_x_start = view.userToDrawXAutoInv ( user_x_start );
00781 double view_by_start = view.userToDrawY ( user_by_start );
00782 double view_ty_start = view.userToDrawY ( user_ty_start );
00783
00784 double view_x_end = view_x_start;
00785 double view_by_end = view_by_start - tick_length;
00786 double view_ty_end = view_ty_start + tick_length;
00787
00788 #ifdef __USE_ISOC99
00789 if( isfinite( view_x_start ) &&
00790 isfinite( view_by_start ) &&
00791 isfinite( view_ty_start ) &&
00792 isfinite( view_x_start ) &&
00793 isfinite( view_by_end ) )
00794 #else
00795 if( finite( view_x_start ) &&
00796 finite( view_by_start ) &&
00797 finite( view_ty_start ) &&
00798 finite( view_x_start ) &&
00799 finite( view_by_end ) )
00800 #endif
00801 {
00802 xv.push_back( view_x_start );
00803 yv.push_back( view_by_start );
00804 xv.push_back( view_x_end );
00805 yv.push_back( view_by_end );
00806
00807 xv.push_back( view_x_start );
00808 yv.push_back( view_ty_start );
00809 xv.push_back( view_x_end );
00810 yv.push_back( view_ty_end );
00811 }
00812 }
00813
00814 view.drawViewLines ( xv, yv, Line::Solid, false, 1 );
00815 }
00816
00817 void
00818 AxisRepBase::
00819 drawYTickLines ( const AxisModelBase & axisModelX,
00820 const AxisModelBase & axisModelY,
00821 const TransformBase & transform,
00822 ViewBase & base )
00823 {
00824 AxisLoc loc = axisModelY.getLabelLocation ();
00825 assert ( loc == PLOTLEFT || loc == PLOTRIGHT );
00826
00827 DataView & view = dynamic_cast < DataView & > ( base );
00828 const Rect & draw_rect = view.getMarginRect ();
00829
00830 double tick_length = 0.05 * draw_rect.getWidth ();
00831 tick_length = min ( tick_length, 8. );
00832
00833 vector< double > xv;
00834 vector< double > yv;
00835
00836 const vector< AxisTick > & ticks = axisModelY.getTicks ();
00837 unsigned int size = ticks.size ();
00838
00839 if ( size == 0 ) return;
00840
00841 size *= 4;
00842
00843 xv.reserve ( size );
00844 yv.reserve ( size );
00845
00846 const BinaryTransform & t
00847 = dynamic_cast< const BinaryTransform & > ( transform );
00848
00849 Range xrange = axisModelX.getRange( false );
00850
00851 for ( unsigned int i = 0; i < ticks.size(); i++ )
00852 {
00853 double user_lx_start = xrange.low();
00854 double user_rx_start = xrange.high();
00855 double user_y_start = ticks[i].value();
00856 double user_y_temp = user_y_start;
00857
00858
00859 t.transform( user_lx_start, user_y_start );
00860 t.transform( user_rx_start, user_y_temp );
00861
00862 double view_lx_start = view.userToDrawX( user_lx_start );
00863 double view_rx_start = view.userToDrawX( user_rx_start );
00864 double view_y_start = view.userToDrawY( user_y_start );
00865
00866 double view_lx_end = view_lx_start + tick_length;
00867 double view_rx_end = view_rx_start - tick_length;
00868 double view_y_end = view_y_start;
00869
00870 #ifdef __USE_ISOC99
00871 if( isfinite( view_lx_start ) &&
00872 isfinite( view_y_start ) &&
00873 isfinite( view_lx_start ) &&
00874 isfinite( view_y_end ) )
00875 #else
00876 if( finite( view_lx_start ) &&
00877 finite( view_y_start ) &&
00878 finite( view_lx_start ) &&
00879 finite( view_y_end ) )
00880 #endif
00881 {
00882 xv.push_back( view_lx_start );
00883 yv.push_back( view_y_start );
00884 xv.push_back( view_lx_end );
00885 yv.push_back( view_y_end );
00886
00887 xv.push_back( view_rx_start );
00888 yv.push_back( view_y_start );
00889 xv.push_back( view_rx_end );
00890 yv.push_back( view_y_end );
00891 }
00892 }
00893
00894 view.drawViewLines ( xv, yv, Line::Solid, false, 1 );
00895 }
00896
00897 void
00898 AxisRepBase::
00899 setFontSize( const AxisModelBase * xAxisModel,
00900 const AxisModelBase * yAxisModel,
00901 const AxisModelBase * zAxisModel,
00902 ViewBase & view )
00903 {
00904 Rect draw_rect = view.getDrawRect();
00905
00906 m_font_size = min( ( draw_rect.getWidth() ) * 0.040, 12.0 );
00907 m_font_size = min (m_font_size, 12.0);
00908 double one = 1.0;
00909 m_font_size = max ( m_font_size, one );
00910 setXFontSize ( *xAxisModel, view );
00911 setYFontSize ( *yAxisModel, view );
00912 if ( zAxisModel != 0 ) setZFontSize ( *zAxisModel, view );
00913 }
00914
00915 void
00916 AxisRepBase::
00917 drawXTickLabels ( const AxisModelBase & axisModelX,
00918 const AxisModelBase & axisModelY,
00919 const TransformBase & transform,
00920 ViewBase & base )
00921 {
00922 double padding = 1.0;
00923
00924 vector < double > xv;
00925 vector < double > yv;
00926
00927 const vector < AxisTick > & ticks = axisModelX.getTicks ();
00928 unsigned int size = ticks.size ();
00929 if ( size == 0 ) return;
00930
00931 xv.reserve ( size );
00932 yv.reserve ( size );
00933
00934 Range yrange = axisModelY.getRange( false );
00935
00936 for ( unsigned int i = 0; i < size; i++ ){
00937 xv.push_back ( ticks[i].value () );
00938 yv.push_back ( yrange.low() );
00939 }
00940
00941 const BinaryTransform & t
00942 = dynamic_cast< const BinaryTransform & > ( transform );
00943 t.transform ( xv, yv );
00944
00945
00946 DataView & view = dynamic_cast < DataView & > ( base );
00947 const Rect & margin = view.getMarginRect ();
00948 float y = margin.getY ();
00949 float x;
00950 char yp = 'b';
00951
00952 if ( axisModelX.getScaleLocation() & PLOTBOTTOM ) {
00953 y = margin.getY () + margin.getHeight ();
00954 yp = 't';
00955 }
00956
00957
00958 string mag="";
00959 double ref = 0.;
00960 if (m_sci_note_x) {
00961 int mid = ticks.size()/2;
00962 ref = ticks[mid].value();
00963 double range = ticks[mid+1].value()-ref;
00964 char cstr[8];
00965 sprintf(cstr, "%.0e", range);
00966 string str(cstr);
00967 string::size_type pos = str.find ( 'e' );
00968 mag=string( str, pos + 1 );
00969 }
00970
00971 for ( unsigned int i = 0; i < ticks.size(); i++ )
00972 {
00973
00974
00975
00976 double user_x_start = ticks[i].value();
00977 double user_y_start = yrange.low();
00978
00979 t.transform( user_x_start, user_y_start );
00980
00981 double view_x_start = view.userToDrawXAutoInv( user_x_start );
00982 double view_y_start = view.userToDrawY( user_y_start );
00983
00984 double user_x_end = ticks[i].value ();
00985 double user_y_end =
00986 yrange.low() + .05 * ( yrange.high() - yrange.low() );
00987
00988 t.transform( user_x_end, user_y_end );
00989
00990 double view_x_end = view.userToDrawXAutoInv( user_x_end );
00991 double view_y_end = view.userToDrawY( user_y_end );
00992
00993
00994 double dx = view_x_end - view_x_start;
00995 double dy = view_y_end - view_y_start;
00996
00997 double ux = dx / sqrt( dx * dx + dy * dy );
00998 double uy = dy / sqrt ( dx * dx + dy * dy );
00999
01000
01001
01002
01003 x = view_x_start - ux * padding;
01004 y = view_y_start - uy * padding;
01005
01006
01007 if (m_sci_note_x){
01008
01009 double diff=ticks[i].value()-ref;
01010
01011 char pstr[8];
01012 sprintf(pstr, "%.0e", diff);
01013 const std::string str(pstr);
01014 string::size_type pos = str.find ( 'e' );
01015 string m ( str, 0, pos );
01016 string e ( str, pos + 1 );
01017
01018 if (e!=mag && m!="0") m+="0";
01019 drawXTickLabel ( m, x, y, view );
01020 }
01021 else {
01022
01023 drawXTickLabel ( ticks[i].content(), x, y, view );
01024 }
01025 }
01026
01027
01028 if (m_sci_note_x) {
01029 drawXMag( axisModelX, view, mag );
01030
01031
01032 }
01033
01034 else if ( axisModelX.needPMag () )
01035 {
01036
01037 if ( axisModelX.isLog () == false ) {
01038 drawXMag ( axisModelX, view );
01039 }
01040 }
01041 }
01042
01043 void
01044 AxisRepBase::
01045 drawYTickLabels ( const AxisModelBase & axisModelX,
01046 const AxisModelBase & axisModelY,
01047 const TransformBase & transform,
01048 ViewBase & view )
01049 {
01050 double padding = 2.0;
01051
01052 const vector< AxisTick > & ticks = axisModelY.getTicks ();
01053 unsigned int size = ticks.size ();
01054 if ( size == 0 ) return;
01055
01056 const BinaryTransform & t
01057 = dynamic_cast< const BinaryTransform & > ( transform );
01058
01059 Range xrange = axisModelX.getRange( false );
01060
01061
01062 string mag="";
01063 double ref = 0.;
01064 if (m_sci_note_y) {
01065 int mid = ticks.size()/2;
01066 ref = ticks[mid].value();
01067 double range = ticks[mid+1].value()-ref;
01068 char cstr[8];
01069 sprintf(cstr, "%.0e", range);
01070 string str(cstr);
01071 string::size_type pos = str.find ( 'e' );
01072 mag=string( str, pos + 1 );
01073 }
01074
01075 for ( unsigned int i = 0; i < ticks.size(); i++ )
01076 {
01077
01078
01079
01080 double user_x_start = xrange.low();
01081 double user_y_start = ticks[i].value();
01082
01083 t.transform( user_x_start, user_y_start );
01084
01085 double view_x_start = view.userToDrawX( user_x_start );
01086 double view_y_start = view.userToDrawY( user_y_start );
01087
01088 double user_x_end
01089 = xrange.low() + .05 * ( xrange.high() - xrange.low() );
01090 double user_y_end = ticks[i].value ();
01091
01092 t.transform( user_x_end, user_y_end );
01093
01094 double view_x_end = view.userToDrawX( user_x_end );
01095 double view_y_end = view.userToDrawY( user_y_end );
01096
01097
01098 double dx = view_x_end - view_x_start;
01099 double dy = view_y_end - view_y_start;
01100
01101 double ux = dx / sqrt( dx * dx + dy * dy );
01102 double uy = dy / sqrt ( dx * dx + dy * dy );
01103
01104
01105
01106
01107 float x = view_x_start - ux * padding;
01108 float y = view_y_start - uy * 1.5;
01109
01110
01111 if (m_sci_note_y){
01112
01113 double diff=ticks[i].value()-ref;
01114
01115 char pstr[8];
01116 sprintf(pstr, "%.0e", diff);
01117 const std::string str(pstr);
01118 string::size_type pos = str.find ( 'e' );
01119 string m ( str, 0, pos );
01120 string e ( str, pos + 1 );
01121
01122 if (e!=mag && m!="0") m+="0";
01123 drawYTickLabel ( m, x, y, view );
01124 }
01125 else {
01126
01127 drawYTickLabel ( ticks[i].content(), x, y, view );
01128 }
01129 }
01130
01131
01132
01133 if (m_sci_note_y) {
01134 drawYMag( axisModelY, view, mag );
01135 }
01136
01137 else if ( axisModelY.needPMag () ){
01138
01139 if ( axisModelY.isLog () == false ) {
01140 drawYMag ( axisModelY, view );
01141 }
01142 }
01143 }
01144
01145 void
01146 AxisRepBase::
01147 drawXTickLabel ( const std::string & label, float x, float y, ViewBase & view )
01148 {
01149 char xalign = 'c';
01150 char yalign = 't';
01151 float angle = 0.;
01152 double & font_size = m_x_tick_font_size;
01153
01154 string::size_type pos = label.find ( 'e' );
01155 if ( pos == string::npos ) {
01156 view.drawText ( label, x, y, m_x_tick_font_size, angle, xalign, yalign );
01157 }
01158 else {
01159 double ss_size = 0.9 * font_size;
01160 string m ( label, 0, pos );
01161 string e ( label, pos + 1 );
01162 if ( m == "1" ) {
01163 m += "0";
01164 x += 0.25 * font_size;
01165 y += 0.25 * ss_size;
01166 view.drawText ( m, x, y, font_size, angle, 'r', yalign );
01167
01168 if ( e[0] == '-' ) {
01169 x -= 0.10 * font_size;
01170 }
01171 y -= 0.5 * ss_size;
01172 view.drawText ( e, x, y, ss_size, angle, 'l', yalign );
01173 }
01174 else {
01175 m += "x10";
01176 x += 0.25 * font_size;
01177 y += 0.25 * ss_size;
01178 view.drawText ( m, x, y, font_size, angle, 'r', yalign );
01179
01180 if ( e[0] == '-' ) {
01181 x -= 0.10 * font_size;
01182 }
01183 y -= 0.5 * ss_size;
01184 view.drawText ( e, x, y, ss_size, angle, 'l', yalign );
01185 }
01186 }
01187 }
01188
01189
01190 void
01191 AxisRepBase::
01192 drawYTickLabel ( const std::string & label,
01193 float x, float y,
01194 ViewBase & view )
01195 {
01196 char xalign = 'r';
01197 char yalign = 'c';
01198 float angle = 0.;
01199 double font_size = m_y_tick_font_size;
01200
01201 string::size_type pos = label.find ( 'e' );
01202 if ( pos == string::npos ) {
01203 view.drawText ( label, x, y, font_size, angle, xalign, yalign );
01204 }
01205
01206 else {
01207 string m ( label, 0, pos );
01208 string e ( label, pos + 1 );
01209
01210 if ( m == "1" ) {
01211 m += "0";
01212 x = x - 0.40 * font_size * e.size();
01213 view.drawText ( m, x, y, font_size, angle, xalign, yalign );
01214
01215 if ( e[0] == '-' ) {
01216 x -= 0.20 * font_size;
01217 }
01218 y = y - 0.625 * font_size;
01219 view.drawText ( e, x, y, 0.9 * font_size, angle, 'l', yalign );
01220 }
01221 else {
01222 m += "x10";
01223 x = x - 0.40 * font_size * e.size();
01224 view.drawText (m, x, y, font_size, angle, xalign, yalign );
01225
01226 if ( e[0] == '-' ) {
01227 x -= 0.20 * font_size;
01228 }
01229 y = y - 0.625 * font_size;
01230 view.drawText ( e, x, y, 0.9 * font_size, angle, 'l', yalign );
01231 }
01232 }
01233 }
01234
01235
01236 void
01237 AxisRepBase::
01238 drawYTickLabels ( const std::vector < AxisTick > & ticks,
01239 const std::vector < float > & xv,
01240 const std::vector < float> & yv,
01241 ViewBase & view)
01242 {
01243 char xalign = 'r';
01244 char yalign = 'c';
01245 float angle = 0.;
01246 double font_size = m_y_tick_font_size;
01247
01248 const string & alabel = ticks[0].content();
01249 string::size_type pos = alabel.find ( 'e' );
01250 bool sci_notate = pos != string::npos;
01251
01252 if ( sci_notate == false ) {
01253 for ( unsigned int i = 0; i < ticks.size(); i++ ) {
01254 view.drawText ( ticks[i].content(), xv[i], yv[i],
01255 font_size, angle, xalign, yalign );
01256 }
01257 }
01258 else {
01259 bool mixed_m = false;
01260 for ( unsigned int i = 0; i < ticks.size (); i++ ) {
01261 const string & label = ticks[i].content ();
01262 string m ( label, 0, pos );
01263 string e ( label, pos + 1 );
01264 mixed_m |= m != "1";
01265 }
01266 if ( mixed_m == true ) {
01267 font_size *= 0.90;
01268 }
01269 for ( unsigned int i = 0; i < ticks.size (); i++ ) {
01270 const string & label = ticks[i].content();
01271 string::size_type pos = alabel.find ( 'e' );
01272 string m ( label, 0, pos );
01273 string e ( label, pos + 1 );
01274 if ( m == "1" ) {
01275 m += "0";
01276 float x = xv[i] - 0.40 * font_size * e.size();
01277 view.drawText ( m, x, yv[i], font_size, angle, xalign, yalign );
01278
01279 if ( e[0] == '-' ) {
01280 x -= 0.20 * font_size;
01281 }
01282 float y = yv[i] - 0.625 * font_size;
01283 view.drawText ( e, x, y, 0.9 * font_size, angle, 'l', yalign );
01284 }
01285 else {
01286 m += "x10";
01287 float x = xv[i] - 0.40 * font_size * e.size();
01288 view.drawText (m, x, yv[i], font_size, angle, xalign, yalign );
01289
01290 if ( e[0] == '-' ) {
01291 x -= 0.20 * font_size;
01292 }
01293 float y = yv[i] - 0.625 * font_size;
01294 view.drawText ( e, x, y, 0.9 * font_size, angle, 'l', yalign );
01295 }
01296 }
01297 }
01298 }
01299
01300 void
01301 AxisRepBase::
01302 drawCrossHairs ( double x, double y,
01303 TransformBase & tb,
01304 ViewBase & view )
01305 {
01306
01307 vector < double > xv ( 4 );
01308 vector < double > yv ( 4 );
01309
01310
01311 const BinaryTransform & tf
01312 = dynamic_cast< const BinaryTransform & > ( tb );
01313
01314 if ( tf.isPeriodic() )
01315 {
01316 const PeriodicBinaryTransform & tp
01317 = dynamic_cast < const PeriodicBinaryTransform & > ( tb );
01318
01319 double xoffset = tp.xOffset();
01320 double yoffset = tp.yOffset();
01321
01322 x = tp.moduloSubX( x, xoffset );
01323 y = tp.moduloSubY( y, yoffset );
01324 }
01325
01326 tf.transform ( x,y );
01327
01328 xv[0] = m_axis_x_origin;
01329 yv[0] = y;
01330
01331 xv[1] = m_axis_width + m_axis_x_origin;
01332 yv[1] = y;
01333
01334 xv[2] = x;
01335 yv[2] = m_axis_height + m_axis_y_origin;
01336
01337 xv[3] = x;
01338 yv[3] = m_axis_y_origin;
01339
01340
01341 Color grey ( 180, 180, 180 );
01342 view.drawLines ( xv, yv, Line::Solid, grey, 0 );
01343
01344 }
01345
01350 void
01351 AxisRepBase::
01352 drawAllXTicks ( const AxisModelBase & axisModelX,
01353 const AxisModelBase & axisModelY,
01354 const TransformBase & transform,
01355 ViewBase & view )
01356 {
01357 drawXTickLines ( axisModelX, axisModelY, transform, view );
01358 drawXTickLabels ( axisModelX, axisModelY, transform, view );
01359 }
01360
01361 void
01362 AxisRepBase::
01363 drawAllYTicks ( const AxisModelBase & axisModelX,
01364 const AxisModelBase & axisModelY,
01365 const TransformBase & transform,
01366 ViewBase & view )
01367 {
01368 drawYTickLines ( axisModelX, axisModelY, transform, view );
01369 drawYTickLabels ( axisModelX, axisModelY, transform, view );
01370 }
01371
01372
01373 void AxisRepBase::setXLabelFont( FontBase* font )
01374 {
01375 assert( font != 0 );
01376 if( m_xLabelFont == NULL )
01377 m_xLabelFont = font;
01378 else
01379 {
01380 delete m_xLabelFont;
01381 m_xLabelFont = font;
01382 }
01383 }
01384
01385 FontBase* AxisRepBase::xLabelFont( )
01386 {
01387 return m_xLabelFont;
01388 }
01389
01390
01391 void AxisRepBase::setYLabelFont( FontBase* font )
01392 {
01393 assert( font != 0 );
01394 if( m_yLabelFont == NULL )
01395 m_yLabelFont = font;
01396 else
01397 {
01398 delete m_yLabelFont;
01399 m_yLabelFont = font;
01400 }
01401 }
01402
01403 FontBase* AxisRepBase::yLabelFont( )
01404 {
01405 return m_yLabelFont;
01406 }
01407
01408
01409 void AxisRepBase::setZLabelFont( FontBase* font )
01410 {
01411 assert( font != 0 );
01412 if( m_zLabelFont == NULL )
01413 m_zLabelFont = font;
01414 else
01415 {
01416 delete m_zLabelFont;
01417 m_zLabelFont = font;
01418 }
01419 }
01420
01421 FontBase* AxisRepBase::zLabelFont( )
01422 {
01423 return m_zLabelFont;
01424 }
01425
01426 void AxisRepBase::setTitleFont( FontBase* font )
01427 {
01428 assert( font != 0 );
01429 if( m_titleFont == NULL )
01430 m_titleFont = font;
01431 else
01432 {
01433 delete m_titleFont;
01434 m_titleFont = font;
01435 }
01436 }
01437
01438 FontBase* AxisRepBase::titleFont( )
01439 {
01440 return m_titleFont;
01441 }
01442
01443 void
01444 AxisRepBase::drawColorScale ( const BinToColor &, ViewBase & )
01445 {
01446 assert ( false );
01447 }