00001
00012
00013 #ifdef _MSC_VER
00014 #include "msdevstudio/MSconfig.h"
00015 #define finite _finite
00016 #endif
00017
00018 #include "AxisRepBase.h"
00019
00020 #include "axes/AxisModelBase.h"
00021 #include "axes/AxisTick.h"
00022 #include "graphics/Color.h"
00023 #include "graphics/ViewBase.h"
00024 #include "transforms/PeriodicBinaryTransform.h"
00025
00026 #include <cmath>
00027 #include <cassert>
00028
00029 using std::max;
00030 using std::min;
00031 using std::string;
00032 using std::vector;
00033 #ifdef __USE_ISOC99
00034 using std::isfinite;
00035 #endif
00036
00037 namespace {
00038 inline float XPADDING( ViewBase & view )
00039 {
00040 return ( view.getDrawRect().getWidth() * 0.01 );
00041 }
00042
00043 inline float YPADDING( ViewBase & view )
00044 {
00045 return ( view.getDrawRect().getHeight() * 0.01 );
00046 }
00047 }
00048
00049 using namespace hippodraw;
00050
00051 AxisRepBase::AxisRepBase()
00052 : m_axis_x_origin (0.),
00053 m_axis_y_origin ( 0.0),
00054 m_axis_width ( 0.0 ),
00055 m_axis_height ( 0.0 ),
00056 m_font_size( 1.0 ),
00057 m_x_font_size( 1.0 ),
00058 m_y_font_size( 1.0 ),
00059 m_xLabelFont( 0 ),
00060 m_yLabelFont( 0 ),
00061 m_zLabelFont( 0 ),
00062 m_titleFont( 0 ),
00063 m_draw_axes( true ),
00064 m_draw_titles( true )
00065 {
00066 }
00067
00068 AxisRepBase::AxisRepBase( const AxisRepBase & axis_rep )
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_axes( axis_rep.m_draw_axes ),
00081 m_draw_titles( axis_rep.m_draw_titles )
00082 {
00083 }
00084
00085 AxisRepBase::~AxisRepBase()
00086 {
00087 delete m_xLabelFont;
00088 delete m_yLabelFont;
00089 delete m_zLabelFont;
00090 delete m_titleFont;
00091 }
00092
00093 void
00094 AxisRepBase::
00095 initAxisRect( ViewBase & view )
00096 {
00097 const HippoRectangle & rect = view.getUserRect();
00098
00099 m_axis_x_origin = rect.getX();
00100 m_axis_y_origin = rect.getY();
00101 m_axis_width = rect.getWidth();
00102 m_axis_height = rect.getHeight();
00103 }
00104
00105 void AxisRepBase::setDrawAxes( bool set )
00106 {
00107 m_draw_axes = set;
00108 }
00109
00110 void
00111 AxisRepBase::
00112 beginPlot( ViewBase & view )
00113 {
00114 initAxisRect( view );
00115 }
00116
00117 void AxisRepBase::setDrawTitles( bool set )
00118 {
00119 m_draw_titles = set;
00120 }
00121
00122 void
00123 AxisRepBase::
00124 drawTitle ( ViewBase & view, const std::string & title )
00125 {
00126 float x, y;
00127
00128 HippoRectangle drawRect = view.getDrawRect();
00129 HippoRectangle marginRect = view.getMarginRect();
00130
00131 float dh = drawRect.getHeight();
00132
00133 float mx = marginRect.getX();
00134 float mw = marginRect.getWidth();
00135
00136 float y_font_size = 0.05 * dh;
00137 float x_font_size = ( mw * 2 ) / title.size();
00138
00139 m_font_size = min ( x_font_size, y_font_size );
00140 double one = 1.0;
00141 m_font_size = max ( m_font_size, one );
00142
00143 x = mx + 0.5 * mw;
00144 y = YPADDING( view );
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
00154 void
00155 AxisRepBase::
00156 setXFontSize ( const AxisModelBase & axisModel,
00157 ViewBase & view )
00158 {
00159 AxisLoc location = axisModel.getScaleLocation();
00160
00161 if ( location == PLOTBOTTOM )
00162 {
00163 m_x_font_size = min( (double)m_font_size,
00164 ( m_axis_y_origin -
00165 view.getDrawRect().getY() ) / 2.0 );
00166 }
00167 else if ( location == PLOTTOP )
00168 {
00169 m_x_font_size = min( (double)m_font_size,
00170 ( view.getDrawRect().getHeight() -
00171 m_axis_height -
00172 ( m_axis_y_origin
00173 - view.getDrawRect().getY() ) ) /2.0 );
00174 }
00175 }
00176
00178 void
00179 AxisRepBase::
00180 setYFontSize ( const AxisModelBase & axisModel,
00181 ViewBase & view )
00182 {
00183 const vector<AxisTick> & labels = axisModel.getTicks ( );
00184 if ( labels.empty () == true ) return;
00185
00186 if ( axisModel.getScaleLocation() & PLOTLEFT )
00187 {
00188 float yr;
00189
00190 if ( m_draw_titles &&
00191 axisModel.getLabelLocation() & PLOTLEFT ) {
00192 yr = 14;
00193 }
00194 else {
00195 yr = 0;
00196 }
00197 const AxisTick & tick = labels.back ( );
00198 m_y_font_size = min ( m_font_size,
00199 ( m_axis_x_origin -
00200 view.getDrawRect().getX() - yr )
00201 / tick.content().size() );
00202 }
00203 else if ( axisModel.getScaleLocation() & PLOTRIGHT )
00204 {
00205
00206 float yr;
00207 if ( m_draw_titles &&
00208 axisModel.getLabelLocation() & PLOTRIGHT ) {
00209 yr = 14;
00210 } else {
00211 yr = 0;
00212 }
00213 m_y_font_size = min( m_font_size,
00214 ( view.getDrawRect().getWidth() -
00215 m_axis_width -
00216 ( m_axis_x_origin -
00217 view.getDrawRect().getX() ) - yr )
00218 / labels[labels.size() - 1].content().size() );
00219 }
00220 }
00221
00222 void
00223 AxisRepBase::
00224 setZFontSize ( const AxisModelBase & axisModel,
00225 ViewBase & view )
00226 {
00227 AxisLoc location = axisModel.getScaleLocation();
00228
00229 if ( location == PLOTBOTTOM )
00230 {
00231 m_z_font_size = min( (double)m_font_size,
00232 ( m_axis_y_origin -
00233 view.getDrawRect().getY() ) / 2.0 );
00234 }
00235 else if ( location == PLOTTOP )
00236 {
00237 m_z_font_size = min( (double)m_font_size,
00238 ( view.getDrawRect().getHeight() -
00239 m_axis_height -
00240 ( m_axis_y_origin
00241 - view.getDrawRect().getY() ) ) /2.0 );
00242 }
00243 }
00244
00245 void
00246 AxisRepBase::
00247 drawXLabels ( const AxisModelBase & axisModel,
00248 ViewBase & view, const std::string & x_label )
00249 {
00250 float x, y;
00251 HippoRectangle draw_rect = view.getDrawRect ();
00252 float draw_h = draw_rect.getHeight ();
00253 float draw_w = draw_rect.getWidth ();
00254
00255 HippoRectangle margin_rect = view.getMarginRect ();
00256 float margin_x = margin_rect.getX ();
00257 float margin_w = margin_rect.getWidth ();
00258
00259 x = margin_x + 0.5 * margin_w;
00260
00261 float tmp = min ( 0.05 * draw_w, 0.05 * draw_h );
00262 tmp = max ( tmp, 1.0f );
00263 m_x_font_size = min ( tmp, static_cast<float>( 18.0 ) );
00264
00265 double ratio = draw_w / ( x_label.size() ) * 2;
00266 m_x_font_size = min ( m_x_font_size, ratio );
00267 double one = 1.0;
00268 m_x_font_size = max ( m_x_font_size, one );
00269
00270 if ( axisModel.getLabelLocation() & PLOTBOTTOM )
00271 {
00272 y = draw_h - 0.75 * YPADDING ( view ) - m_x_font_size;
00273 if ( m_xLabelFont != 0 ) {
00274 view.drawText ( x_label, x, y, 0., 0.0, 'c', 't',
00275 false, m_xLabelFont );
00276 } else {
00277 view.drawText ( x_label, x, y, m_x_font_size, 0.0, 'c', 't', false );
00278 }
00279 }
00280 else if ( axisModel.getLabelLocation() & PLOTTOP )
00281 {
00282 y = YPADDING ( view );
00283 if ( m_xLabelFont != 0 ) {
00284 view.drawText ( x_label, x, y, 0.0, 0.0, 'c', 't',
00285 false, m_xLabelFont );
00286 } else {
00287 view.drawText ( x_label, x, y, m_x_font_size, 0.0, 'c', 't', false );
00288 }
00289 }
00290 }
00291
00293 void
00294 AxisRepBase::
00295 drawYLabels ( const AxisModelBase & axisModel,
00296 ViewBase & view, const std::string & y_label )
00297 {
00298 float x, y;
00299 AxisLoc location = axisModel.getLabelLocation();
00300
00301 float tmp = min ( view.getDrawRect().getWidth() * 0.05,
00302 view.getDrawRect().getHeight() * 0.05 );
00303 m_y_font_size = min( tmp, static_cast<float>( 18.0 ) );
00304 m_y_font_size = min( m_y_font_size, view.getDrawRect().getHeight()
00305 / ( y_label.size() ) * 2 );
00306 double one = 1.0;
00307 m_y_font_size = max ( m_y_font_size, one );
00308 y = view.getMarginRect().getY() +
00309 view.getMarginRect().getHeight() / 2.0;
00310
00311 if ( location & PLOTLEFT )
00312 {
00313 x = XPADDING( view );
00314 if ( m_yLabelFont != 0 ) {
00315 view.drawText ( y_label, x, y, 0.0, 90.0, 'c', 't',
00316 false, m_yLabelFont );
00317 } else {
00318 view.drawText ( y_label, x, y, m_y_font_size, 90.0, 'c', 't', false );
00319 }
00320 }
00321 else if ( location & PLOTRIGHT )
00322 {
00323 x = view.getDrawRect().getWidth()
00324 - XPADDING( view );
00325 if ( m_yLabelFont != 0 ) {
00326 view.drawText ( y_label, x, y, 0.0, -90.0, 'c', 't',
00327 false, m_yLabelFont );
00328 } else {
00329 view.drawText ( y_label, x, y, m_y_font_size, -90.0, 'c', 't', false );
00330 }
00331 }
00332 }
00333
00334 void AxisRepBase::drawYMag ( const AxisModelBase & axisModel,
00335 ViewBase & view )
00336 {
00337 const HippoRectangle view_rect = view.getDrawRect ();
00338 float x = view_rect.getX();
00339
00340 if ( axisModel.getScaleLocation() & PLOTLEFT ) {
00341 x += m_font_size;
00342 }
00343 else {
00344 x -= m_font_size;
00345 }
00346
00347 const HippoRectangle margin_rect = view.getMarginRect ();
00348
00349 float y = view_rect.getY() + margin_rect.getY() - m_font_size;
00350 double pmag = axisModel.getPMag();
00351
00352 view.drawMag ( x, y, static_cast< int > ( pmag ), m_font_size * 0.75 );
00353 }
00354
00355 void
00356 AxisRepBase::
00357 drawAxesLines ( TransformBase & transform,
00358 ViewBase & view,
00359 const Range & x_range,
00360 const Range & y_range)
00361 {
00362 const BinaryTransform & t
00363 = dynamic_cast< const BinaryTransform & > ( transform );
00364 vector< double > xv ( 100 );
00365 vector< double > yv ( 100 );
00366 Color black ( 0, 0, 0 );
00367
00368 xv[0] = x_range.low( );
00369 yv[0] = y_range.low( );
00370 for( int i = 1; i < 100; i++)
00371 {
00372 xv[i] = xv[i-1] + ( x_range.high() - x_range.low() )/99;
00373 yv[i] = yv[i-1];
00374 }
00375 t.transform( xv, yv );
00376 view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
00377
00378
00379 xv[0] = x_range.high( );
00380 yv[0] = y_range.low( );
00381 for( int i = 1; i < 100; i++)
00382 {
00383 xv[i] = xv[i-1];
00384 yv[i] = yv[i-1] + ( y_range.high() - y_range.low() )/99; ;
00385 }
00386 t.transform( xv, yv );
00387 view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
00388
00389
00390 xv[0] = x_range.low( );
00391 yv[0] = y_range.high( );
00392 for( int i = 1; i < 100; i++)
00393 {
00394 xv[i] = xv[i-1] + ( x_range.high() - x_range.low() )/99;
00395 yv[i] = yv[i-1];
00396 }
00397
00398 t.transform( xv, yv );
00399 view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
00400
00401
00402 xv[0] = x_range.low( );
00403 yv[0] = y_range.low( );
00404 for( int i = 1; i < 100; i++)
00405 {
00406 xv[i] = xv[i-1];
00407 yv[i] = yv[i-1] + ( y_range.high() - y_range.low() )/99;
00408 }
00409
00410 t.transform( xv, yv );
00411 view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
00412
00413
00414 }
00415
00416
00417
00418 void AxisRepBase::drawGridLines( const AxisModelBase & axisModelX,
00419 const AxisModelBase & axisModelY,
00420 TransformBase & transform,
00421 ViewBase & view )
00422 {
00423 Range x_range = axisModelX.getRange( false );
00424 Range y_range = axisModelY.getRange( false );
00425
00426
00427 const vector< AxisTick > & x_ticks = axisModelX.getTicks();
00428 const vector< AxisTick > & y_ticks = axisModelY.getTicks();
00429
00430 unsigned int nxpoints = 100;
00431 unsigned int nypoints = 100;
00432 vector< double > xv(100), yv(100);
00433
00434 double user_x, user_y;
00435 Color grey( 180, 180, 180 );
00436
00437 BinaryTransform & t
00438 = dynamic_cast< BinaryTransform & > ( transform );
00439
00440 t.validate( x_range, y_range );
00441
00442 if ( x_ticks.empty () == true || y_ticks.empty () == true )
00443 return;
00444
00445
00446 double dx = ( x_range.high() - x_range.low() ) / ( nxpoints - 1 );
00447 double dy = ( y_range.high() - y_range.low() ) / ( nypoints - 1 ) ;
00448
00449
00450
00451
00452 for ( unsigned int i = 0; i < x_ticks.size(); i++ )
00453 {
00454 user_x = x_ticks[ i ].value();
00455
00456 for ( unsigned int j = 0; j < nypoints; j++ )
00457 {
00458 user_y = y_range.low() + j * dy;
00459
00460 xv[ j ] = user_x;
00461 yv[ j ] = user_y;
00462
00463 }
00464
00465 t.transform( xv, yv );
00466 view.drawPolyLine ( xv, yv, Line::Solid, grey, 0 );
00467
00468 }
00469
00470
00471
00472
00473 for ( unsigned int j = 0; j < y_ticks.size(); j++ )
00474 {
00475 user_y = y_ticks[ j ].value();
00476
00477 for ( unsigned int i = 0; i < nxpoints; i++ )
00478 {
00479 user_x = x_range.low() + i * dx;
00480
00481 xv[ i ] = user_x ;
00482 yv[ i ] = user_y ;
00483 }
00484
00485 t.transform( xv, yv );
00486 view.drawPolyLine( xv, yv, Line::Solid, grey, 0 );
00487 }
00488
00489 return;
00490 }
00491
00492 void
00493 AxisRepBase::
00494 drawXTickLines( const AxisModelBase & axisModelX,
00495 const AxisModelBase & axisModelY,
00496 const TransformBase & transform,
00497 ViewBase & view )
00498 {
00499 AxisLoc loc = axisModelX.getLabelLocation();
00500 assert( loc == PLOTBOTTOM || PLOTTOP );
00501
00502 const vector< AxisTick > & ticks = axisModelX.getTicks();
00503 if ( ticks.empty() == true ) return;
00504
00505 vector< double > xv;
00506 vector< double > yv;
00507
00508 unsigned int size = 4 * ticks.size();
00509 xv.reserve( size );
00510 yv.reserve( size );
00511
00512 const BinaryTransform & t
00513 = dynamic_cast< const BinaryTransform & > ( transform );
00514
00515 const HippoRectangle view_rect = view.getMarginRect();
00516 double tick_length = 0.05 * view_rect.getHeight();
00517
00518 Range yrange = axisModelY.getRange( false );
00519
00520 for ( unsigned int i = 0; i < ticks.size(); i++ )
00521 {
00522
00523
00524
00525
00526
00527 double user_x_start = ticks[i].value ();
00528 double user_x_temp = user_x_start;
00529
00530 double user_by_start = yrange.low();
00531 double user_ty_start = yrange.high();
00532
00533
00534 t.transform( user_x_start, user_by_start );
00535 t.transform( user_x_temp, user_ty_start );
00536
00537 double view_x_start = view.userToDrawX( user_x_start );
00538 double view_by_start = view.userToDrawY( user_by_start );
00539 double view_ty_start = view.userToDrawY( user_ty_start );
00540
00541 double user_x_end = ticks[i].value ();
00542 user_x_temp = user_x_end;
00543 double user_by_end
00544 = yrange.low() + .05 * ( yrange.high() - yrange.low() );
00545 double user_ty_end
00546 = yrange.high() - .05 * ( yrange.high() - yrange.low() );
00547
00548
00549 t.transform( user_x_end, user_by_end );
00550 t.transform( user_x_temp, user_ty_end );
00551
00552 double view_x_end = view.userToDrawX( user_x_end );
00553 double view_by_end = view.userToDrawY( user_by_end );
00554 double view_ty_end = view.userToDrawY( user_ty_end );
00555
00556
00557 double dx = view_x_end - view_x_start;
00558 double dy = view_by_end - view_by_start;
00559
00560 double ux = dx / sqrt( dx * dx + dy * dy );
00561 double uy = dy / sqrt( dx * dx + dy * dy );
00562
00563
00564
00565
00566 view_x_end = view_x_start + ux * tick_length;
00567 view_by_end = view_by_start + uy * tick_length;
00568 view_ty_end = view_ty_start - uy * tick_length;
00569
00570 #ifdef __USE_ISOC99
00571 if( isfinite( view_x_start ) &&
00572 isfinite( view_by_start ) &&
00573 isfinite( view_ty_start ) &&
00574 isfinite( view_x_start ) &&
00575 isfinite( view_by_end ) )
00576 #else
00577 if( finite( view_x_start ) &&
00578 finite( view_by_start ) &&
00579 finite( view_ty_start ) &&
00580 finite( view_x_start ) &&
00581 finite( view_by_end ) )
00582 #endif
00583 {
00584 xv.push_back( view_x_start );
00585 yv.push_back( view_by_start );
00586 xv.push_back( view_x_end );
00587 yv.push_back( view_by_end );
00588
00589 xv.push_back( view_x_start );
00590 yv.push_back( view_ty_start );
00591 xv.push_back( view_x_end );
00592 yv.push_back( view_ty_end );
00593 }
00594 }
00595
00596 view.drawViewLines ( xv, yv, Line::Solid, false, 1 );
00597 }
00598
00599 void
00600 AxisRepBase::
00601 drawYTickLines ( const AxisModelBase & axisModelX,
00602 const AxisModelBase & axisModelY,
00603 const TransformBase & transform,
00604 ViewBase & view )
00605 {
00606 AxisLoc loc = axisModelY.getLabelLocation ();
00607 assert ( loc == PLOTLEFT || loc == PLOTRIGHT );
00608
00609 const HippoRectangle draw_rect = view.getMarginRect ();
00610
00611 double tick_length = 0.05 * draw_rect.getWidth ();
00612
00613 vector< double > xv;
00614 vector< double > yv;
00615
00616 const vector< AxisTick > & ticks = axisModelY.getTicks ();
00617 unsigned int size = ticks.size ();
00618
00619 if ( size == 0 ) return;
00620
00621 size *= 4;
00622
00623 xv.reserve ( size );
00624 yv.reserve ( size );
00625
00626 const BinaryTransform & t
00627 = dynamic_cast< const BinaryTransform & > ( transform );
00628
00629 Range xrange = axisModelX.getRange( false );
00630
00631 for ( unsigned int i = 0; i < ticks.size(); i++ )
00632 {
00633
00634
00635
00636
00637
00638 double user_lx_start = xrange.low();
00639 double user_rx_start = xrange.high();
00640 double user_y_start = ticks[i].value();
00641 double user_y_temp = user_y_start;
00642
00643
00644 t.transform( user_lx_start, user_y_start );
00645 t.transform( user_rx_start, user_y_temp );
00646
00647 double view_lx_start = view.userToDrawX( user_lx_start );
00648 double view_rx_start = view.userToDrawX( user_rx_start );
00649 double view_y_start = view.userToDrawY( user_y_start );
00650
00651 double user_lx_end
00652 = xrange.low() + .05 * ( xrange.high() - xrange.low() );
00653 double user_rx_end
00654 = xrange.high() - .05 * ( xrange.high() - xrange.low() );
00655 double user_y_end = ticks[i].value ();
00656 user_y_temp = user_y_end;
00657
00658 t.transform( user_lx_end, user_y_end );
00659 t.transform( user_rx_end, user_y_temp );
00660
00661 double view_lx_end = view.userToDrawX( user_lx_end );
00662 double view_rx_end = view.userToDrawX( user_rx_end );
00663 double view_y_end = view.userToDrawY( user_y_end );
00664
00665
00666 double dx = view_lx_end - view_lx_start;
00667 double dy = view_y_end - view_y_start;
00668
00669 double ux = dx / sqrt( dx * dx + dy * dy );
00670 double uy = dy / sqrt( dx * dx + dy * dy );
00671
00672
00673
00674
00675 view_lx_end = view_lx_start + ux * tick_length;
00676 view_rx_end = view_rx_start - ux * tick_length;
00677 view_y_end = view_y_start + uy * tick_length;
00678
00679 #ifdef __USE_ISOC99
00680 if( isfinite( view_lx_start ) &&
00681 isfinite( view_y_start ) &&
00682 isfinite( view_lx_start ) &&
00683 isfinite( view_y_end ) )
00684 #else
00685 if( finite( view_lx_start ) &&
00686 finite( view_y_start ) &&
00687 finite( view_lx_start ) &&
00688 finite( view_y_end ) )
00689 #endif
00690 {
00691 xv.push_back( view_lx_start );
00692 yv.push_back( view_y_start );
00693 xv.push_back( view_lx_end );
00694 yv.push_back( view_y_end );
00695
00696 xv.push_back( view_rx_start );
00697 yv.push_back( view_y_start );
00698 xv.push_back( view_rx_end );
00699 yv.push_back( view_y_end );
00700 }
00701 }
00702
00703 view.drawViewLines ( xv, yv, Line::Solid, false, 1 );
00704 }
00705
00708 void
00709 AxisRepBase::
00710 setFontSize( const AxisModelBase * xAxisModel,
00711 const AxisModelBase * yAxisModel,
00712 const AxisModelBase * zAxisModel,
00713 ViewBase & view )
00714 {
00715 m_font_size = min( ( view.getDrawRect().getWidth() ) * 0.040, 12.0 );
00716 double one = 1.0;
00717 m_font_size = max ( m_font_size, one );
00718 setXFontSize ( *xAxisModel, view );
00719 setYFontSize ( *yAxisModel, view );
00720 if ( zAxisModel != 0 ) setZFontSize ( *zAxisModel, view );
00721 }
00722
00723 void
00724 AxisRepBase::
00725 drawXTickLabels ( const AxisModelBase & axisModelX,
00726 const AxisModelBase & axisModelY,
00727 const TransformBase & transform,
00728 ViewBase & view )
00729 {
00730 double xpadding = XPADDING ( view );
00731 double ypadding = YPADDING ( view );
00732 double padding = sqrt( xpadding * xpadding + ypadding * ypadding );
00733
00734 vector < double > xv;
00735 vector < double > yv;
00736
00737 const vector < AxisTick > & ticks = axisModelX.getTicks ();
00738 unsigned int size = ticks.size ();
00739 if ( size == 0 ) return;
00740
00741 xv.reserve ( size );
00742 yv.reserve ( size );
00743
00744 Range yrange = axisModelY.getRange( false );
00745
00746 for ( unsigned int i = 0; i < size; i++ ){
00747 xv.push_back ( ticks[i].value () );
00748 yv.push_back ( yrange.low() );
00749 }
00750
00751 const BinaryTransform & t
00752 = dynamic_cast< const BinaryTransform & > ( transform );
00753 t.transform ( xv, yv );
00754
00755
00756 const HippoRectangle & margin = view.getMarginRect ();
00757 float y = margin.getY ();
00758 float x;
00759 char yp = 'b';
00760 char xp = 'c';
00761
00762 if ( axisModelX.getScaleLocation() & PLOTBOTTOM ) {
00763 y = margin.getY () + margin.getHeight ();
00764 yp = 't';
00765 }
00766
00767
00768 for ( unsigned int i = 0; i < ticks.size(); i++ )
00769 {
00770
00771
00772
00773 double user_x_start = ticks[i].value();
00774 double user_y_start = yrange.low();
00775
00776 t.transform( user_x_start, user_y_start );
00777
00778 double view_x_start = view.userToDrawX( user_x_start );
00779 double view_y_start = view.userToDrawY( user_y_start );
00780
00781 double user_x_end = ticks[i].value ();
00782 double user_y_end =
00783 yrange.low() + .05 * ( yrange.high() - yrange.low() );
00784
00785 t.transform( user_x_end, user_y_end );
00786
00787 double view_x_end = view.userToDrawX( user_x_end );
00788 double view_y_end = view.userToDrawY( user_y_end );
00789
00790
00791 double dx = view_x_end - view_x_start;
00792 double dy = view_y_end - view_y_start;
00793
00794 double ux = dx / sqrt( dx * dx + dy * dy );
00795 double uy = dy / sqrt ( dx * dx + dy * dy );
00796
00797
00798
00799
00800 x = view_x_start - ux * padding;
00801 y = view_y_start - uy * padding;
00802
00803
00804 view.drawText ( ticks[i].content(), x, y, m_font_size, 0.0, xp, yp);
00805 }
00806
00807 if ( axisModelX.needPMag () )
00808 {
00809 double pmag = axisModelX.getPMag ();
00810 const HippoRectangle view_rect = view.getDrawRect ();
00811
00812 float last_x = view.userToDrawX ( xv[ size -1 ] );
00813 float x = margin.getX () + last_x;
00814
00815 const AxisTick & last_tick = ticks.back ();
00816 const string & last_label = last_tick.content ();
00817 float label_size = last_label.size ();
00818 x += 0.5 * label_size * m_font_size;
00819
00820 float margin_right = margin.getX () + margin.getWidth ();
00821 x = min ( x, margin_right );
00822
00823 if ( yp == 't' ) {
00824 y += m_font_size * 2.0;
00825 } else {
00826 y -= m_font_size * 2.0;
00827 }
00828
00829 x += view_rect.getX();
00830 y += view_rect.getY();
00831
00832
00833 if ( axisModelX.isLog () == false ) {
00834 x -= m_font_size;
00835 view.drawMag ( x, y, static_cast< int >( pmag ), m_font_size * 0.75 );
00836 }
00837 }
00838
00839 }
00840
00841 void
00842 AxisRepBase::
00843 drawYTickLabels ( const AxisModelBase & axisModelX,
00844 const AxisModelBase & axisModelY,
00845 const TransformBase & transform,
00846 ViewBase & view )
00847 {
00848
00849
00850
00851 float x, y;
00852 char xalign = 'r';
00853 double xpadding = XPADDING ( view );
00854 double ypadding = YPADDING ( view );
00855 double padding = sqrt( xpadding * xpadding + ypadding * ypadding );
00856
00857 const vector< AxisTick > & ticks = axisModelY.getTicks ();
00858 unsigned int size = ticks.size ();
00859 if ( size == 0 ) return;
00860
00861 const BinaryTransform & t
00862 = dynamic_cast< const BinaryTransform & > ( transform );
00863
00864 Range xrange = axisModelX.getRange( false );
00865
00866 for ( unsigned int i = 0; i < ticks.size(); i++ )
00867 {
00868
00869
00870
00871 double user_x_start = xrange.low();
00872 double user_y_start = ticks[i].value();
00873
00874 t.transform( user_x_start, user_y_start );
00875
00876 double view_x_start = view.userToDrawX( user_x_start );
00877 double view_y_start = view.userToDrawY( user_y_start );
00878
00879 double user_x_end
00880 = xrange.low() + .05 * ( xrange.high() - xrange.low() );
00881 double user_y_end = ticks[i].value ();
00882
00883 t.transform( user_x_end, user_y_end );
00884
00885 double view_x_end = view.userToDrawX( user_x_end );
00886 double view_y_end = view.userToDrawY( user_y_end );
00887
00888
00889 double dx = view_x_end - view_x_start;
00890 double dy = view_y_end - view_y_start;
00891
00892 double ux = dx / sqrt( dx * dx + dy * dy );
00893 double uy = dy / sqrt ( dx * dx + dy * dy );
00894
00895
00896
00897
00898 x = view_x_start - ux * padding;
00899 y = view_y_start - uy * padding;
00900
00901
00902 view.drawText ( ticks[i].content(), x, y,
00903 m_font_size, 0.0, xalign, 'c' );
00904 }
00905
00906 if ( axisModelY.needPMag() ) {
00907
00908 if ( !(axisModelY.isLog() ) ) {
00909 drawYMag ( axisModelY, view );
00910 }
00911 }
00912 }
00913
00914 void
00915 AxisRepBase::
00916 drawCrossHairs ( double x, double y,
00917 TransformBase & tb,
00918 ViewBase & view )
00919 {
00920
00921 vector < double > xv ( 4 );
00922 vector < double > yv ( 4 );
00923
00924
00925 const BinaryTransform & tf
00926 = dynamic_cast< const BinaryTransform & > ( tb );
00927
00928 if ( tf.isPeriodic() )
00929 {
00930 const PeriodicBinaryTransform & tp
00931 = dynamic_cast < const PeriodicBinaryTransform & > ( tb );
00932
00933 double xoffset = tp.xOffset();
00934 double yoffset = tp.yOffset();
00935
00936 x = tp.moduloSubX( x, xoffset );
00937 y = tp.moduloSubY( y, yoffset );
00938 }
00939
00940 tf.transform ( x,y );
00941
00942 xv[0] = m_axis_x_origin;
00943 yv[0] = y;
00944
00945 xv[1] = m_axis_width + m_axis_x_origin;
00946 yv[1] = y;
00947
00948 xv[2] = x;
00949 yv[2] = m_axis_height + m_axis_y_origin;
00950
00951 xv[3] = x;
00952 yv[3] = m_axis_y_origin;
00953
00954
00955 Color grey ( 180, 180, 180 );
00956 view.drawLines ( xv, yv, Line::Solid, grey, 0 );
00957
00958 }
00959
00964 void
00965 AxisRepBase::
00966 drawAllXTicks ( const AxisModelBase & axisModelX,
00967 const AxisModelBase & axisModelY,
00968 const TransformBase & transform,
00969 ViewBase & view )
00970 {
00971 drawXTickLines ( axisModelX, axisModelY, transform, view );
00972 drawXTickLabels ( axisModelX, axisModelY, transform, view );
00973 }
00974
00975 void
00976 AxisRepBase::
00977 drawAllYTicks ( const AxisModelBase & axisModelX,
00978 const AxisModelBase & axisModelY,
00979 const TransformBase & transform,
00980 ViewBase & view )
00981 {
00982 drawYTickLines ( axisModelX, axisModelY, transform, view );
00983 drawYTickLabels ( axisModelX, axisModelY, transform, view );
00984 }
00985
00986
00987 void AxisRepBase::setXLabelFont( FontBase* font )
00988 {
00989 assert( font != 0 );
00990 if( m_xLabelFont == NULL )
00991 m_xLabelFont = font;
00992 else
00993 {
00994 delete m_xLabelFont;
00995 m_xLabelFont = font;
00996 }
00997 }
00998
00999 FontBase* AxisRepBase::xLabelFont( )
01000 {
01001 return m_xLabelFont;
01002 }
01003
01004
01005 void AxisRepBase::setYLabelFont( FontBase* font )
01006 {
01007 assert( font != 0 );
01008 if( m_yLabelFont == NULL )
01009 m_yLabelFont = font;
01010 else
01011 {
01012 delete m_yLabelFont;
01013 m_yLabelFont = font;
01014 }
01015 }
01016
01017 FontBase* AxisRepBase::yLabelFont( )
01018 {
01019 return m_yLabelFont;
01020 }
01021
01022
01023 void AxisRepBase::setZLabelFont( FontBase* font )
01024 {
01025 assert( font != 0 );
01026 if( m_zLabelFont == NULL )
01027 m_zLabelFont = font;
01028 else
01029 {
01030 delete m_zLabelFont;
01031 m_zLabelFont = font;
01032 }
01033 }
01034
01035 FontBase* AxisRepBase::zLabelFont( )
01036 {
01037 return m_zLabelFont;
01038 }
01039
01040 void AxisRepBase::setTitleFont( FontBase* font )
01041 {
01042 assert( font != 0 );
01043 if( m_titleFont == NULL )
01044 m_titleFont = font;
01045 else
01046 {
01047 delete m_titleFont;
01048 m_titleFont = font;
01049 }
01050 }
01051
01052 FontBase* AxisRepBase::titleFont( )
01053 {
01054 return m_titleFont;
01055 }
01056
01057 void
01058 AxisRepBase::drawColorScale ( const BinToColor &, ViewBase & )
01059 {
01060 assert ( false );
01061 }