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