AxisRepBase.cxx
Go to the documentation of this file.
1 
12 // for tex
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16 
17 // for truncation warning
18 #ifdef _MSC_VER
19 #include "msdevstudio/MSconfig.h"
20 #define finite _finite
21 #endif
22 
23 #include "AxisRepBase.h"
24 
25 #include "axes/AxisModelBase.h"
26 #include "graphics/Color.h"
27 #include "graphics/DataView.h"
28 #include "pattern/string_convert.h"
30 
31 #include <cmath>
32 #include <cassert>
33 #include <cstdio>
34 
35 using std::max;
36 using std::min;
37 using std::string;
38 using std::vector;
39 using std::sprintf;
40 #ifdef __USE_ISOC99
41 using std::isfinite;
42 #endif
43 
44 using namespace hippodraw;
45 
47  : m_sci_note_x(false),
48  m_sci_note_y(false),
49  m_axis_x_origin (0.),
50  m_axis_y_origin ( 0.0),
51  m_axis_width ( 0.0 ),
52  m_axis_height ( 0.0 ),
53  m_font_size( 1.0 ),
54  m_x_tick_font_size ( 1.0 ),
55  m_y_tick_font_size ( 1.0 ),
56  m_x_font_size( 1.0 ),
57  m_y_font_size( 1.0 ),
58  m_xLabelFont( 0 ),
59  m_yLabelFont( 0 ),
60  m_zLabelFont( 0 ),
61  m_titleFont( 0 ),
62  m_draw_titles( true )
63 {
64 }
65 
67  : m_sci_note_x(axis_rep.m_sci_note_x),
68  m_sci_note_y(axis_rep.m_sci_note_y),
69  m_axis_x_origin( axis_rep.m_axis_x_origin ),
70  m_axis_y_origin( axis_rep.m_axis_y_origin ),
71  m_axis_width( axis_rep.m_axis_width ),
72  m_axis_height( axis_rep.m_axis_height ),
73  m_font_size( axis_rep.m_font_size ),
74  m_x_font_size( axis_rep.m_x_font_size ),
75  m_y_font_size( axis_rep.m_y_font_size ),
76  m_xLabelFont( axis_rep.m_xLabelFont ),
77  m_yLabelFont( axis_rep.m_yLabelFont ),
78  m_zLabelFont( axis_rep.m_zLabelFont ),
79  m_titleFont( axis_rep.m_titleFont ),
80  m_draw_titles( axis_rep.m_draw_titles )
81 {
82 }
83 
85 {
86  delete m_xLabelFont;
87  delete m_yLabelFont;
88  delete m_zLabelFont;
89  delete m_titleFont;
90 }
91 
92 void
95 {
96  const Rect & rect = view.getUserRect();
97 
98  m_axis_x_origin = rect.getX();
99  m_axis_y_origin = rect.getY();
100  m_axis_width = rect.getWidth();
101  m_axis_height = rect.getHeight();
102 }
103 
104 void
107 {
108  initAxisRect( view );
109 }
110 
112 {
113  m_draw_titles = set;
114 }
115 
116 void
118 drawTitle ( ViewBase & base, const std::string & title )
119 {
120 
121  DataView & view = dynamic_cast < DataView & > ( base );
122 
123  // Draw Latex at the top of the plotter if in Latex format
124 #ifdef HAVE_TEX_UTILS
125  if (String::ci_find(title, "tex:")==0) {
126  string tex_snippet = title.substr(4);
127  view.drawLatex ( tex_snippet, 1 );
128  }
129 
130  else {
131 #endif
132  const Rect & marginRect = view.getMarginRect();
133  float mx = marginRect.getX();
134  Rect rect = view.getDrawRect ();
135  float mw = rect.getWidth();
136 
137  double x_font_size = ( 1.3 * mw ) / title.size();
138  m_font_size = min(x_font_size,12.0);
139 
140  double one = 1.0;
141  m_font_size = max ( m_font_size, one );
142 
143  float x = mx + 0.5 * marginRect.getWidth ();
144  float y = 2.0;
145 
146  if ( m_titleFont != 0 ) {
147  view.drawText ( title, x, y, 0.0, 0.0, 'c', 't', false,
148  m_titleFont );
149  } else {
150  view.drawText ( title, x, y, m_font_size, 0.0, 'c', 't', false );
151  }
152 
153 #ifdef HAVE_TEX_UTILS
154  }
155 #endif
156 }
157 
158 void
160 setXFontSize ( const AxisModelBase & axisModel,
161  ViewBase & view )
162 {
163  Rect draw_rect = view.getDrawRect();
164  m_x_tick_font_size = min( ( draw_rect.getWidth() ) * 0.040, 12.0 );
165  double one = 1.0;
166  m_x_tick_font_size = max ( m_x_tick_font_size, one );
167 
168  AxisLoc location = axisModel.getScaleLocation();
169 
170  if ( location == PLOTBOTTOM )
171  {
172  m_x_font_size = min( (double)m_x_tick_font_size,
173  ( m_axis_y_origin -
174  draw_rect.getY() ) / 2.0 );
175  }
176  else if ( location == PLOTTOP )
177  {
178  m_x_font_size = min( (double)m_x_tick_font_size,
179  ( draw_rect.getHeight() -
180  m_axis_height -
182  - draw_rect.getY() ) ) /2.0 );
183  }
184 }
185 
186 void
188 setYFontSize ( const AxisModelBase & axisModel,
189  ViewBase & view )
190 {
191  assert ( m_y_tick_font_size > 0 );
192 
193  Rect draw_rect = view.getDrawRect();
194  double height = draw_rect.getHeight ();
195  double size = height * 0.040;
196  size = std::min ( size, 11.0 );
197  double one = 1.0;
198  m_y_tick_font_size = std::max ( size, one );
199 
200  assert ( m_y_tick_font_size > 0 );
201  const vector<AxisTick> & labels = axisModel.getTicks ( );
202  if ( labels.empty () == true ) return;
203 
204  if ( axisModel.getScaleLocation() & PLOTLEFT )
205  {
206  float yr;
207 
208  if ( m_draw_titles &&
209  axisModel.getLabelLocation() & PLOTLEFT ) {
210  yr = 14;
211  }
212  else {
213  yr = 0;
214  }
215  const AxisTick & tick = labels.back ( );
217  ( m_axis_x_origin -
218  draw_rect.getX() - yr )
219  / tick.content().size() );
220  }
221  else if ( axisModel.getScaleLocation() & PLOTRIGHT )
222  {
223  // Estimates the space needed for the Y axis label.
224  float yr;
225  if ( m_draw_titles &&
226  axisModel.getLabelLocation() & PLOTRIGHT ) {
227  yr = 14;
228  } else {
229  yr = 0;
230  }
231 
233  ( draw_rect.getWidth() -
234  m_axis_width -
235  ( m_axis_x_origin -
236  draw_rect.getX() ) - yr )
237  / labels[labels.size() - 1].content().size() );
238  }
239 }
240 
241 void
243 setZFontSize ( const AxisModelBase & axisModel,
244  ViewBase & view )
245 {
246  AxisLoc location = axisModel.getScaleLocation();
247  Rect draw_rect = view.getDrawRect();
248  if ( location == PLOTBOTTOM )
249  {
250  m_z_font_size = min( (double)m_font_size,
251  ( m_axis_y_origin -
252  draw_rect.getY() ) / 2.0 );
253  }
254  else if ( location == PLOTTOP )
255  {
256  m_z_font_size = min( (double)m_font_size,
257  ( draw_rect.getHeight() -
258  m_axis_height -
260  - draw_rect.getY() ) ) /2.0 );
261  }
262 }
263 
264 void
266 drawXLabels ( const AxisModelBase & axisModel,
267  ViewBase & base, const std::string & x_label )
268 {
269  DataView & view = dynamic_cast < DataView & > ( base );
270 
271  // Calculate the ratio of range(rmag) and value(pmag) to decide
272  // where scientific notation is needed.
273  const vector< AxisTick > & ticks = axisModel.getTicks();
274  m_sci_note_x=false;
275  int mid = ticks.size()/2;
276  double ref = ticks[mid].value();
277  double range = ticks[mid+1].value()-ref;
278  if (fabs(ref/range)>1e6) m_sci_note_x=true;
279 
280  // Draw Latex at the bottom of the plotter if in Latex format
281 #ifdef HAVE_TEX_UTILS
282  if (String::ci_find(x_label, "tex:")==0) {
283  string tex_snippet = x_label.substr(4);
284  if (m_sci_note_x) {
285  tex_snippet+="-"+ticks[mid].content();
286  if (axisModel.needPMag()) {
287  // Use LaTeX to generate: label-mid*10^Pmag
288  tex_snippet+="\\times 10^"+String::convert ( static_cast <int> (axisModel.getPMag()) );
289  }
290  }
291  view.drawLatex ( tex_snippet, 2 );
292  }
293 
294  else {
295 #endif
296  std::string label;
297  if (m_sci_note_x) {
298  label = x_label+" - "+ticks[mid].content();
299  }
300  else {
301  label = x_label;
302  }
303 
304  float x = 0., y = 0.;
305  Rect draw_rect = view.getDrawRect ();
306  float draw_h = draw_rect.getHeight ();
307  float draw_w = draw_rect.getWidth ();
308 
309  const Rect & margin_rect = view.getMarginRect ();
310  float margin_x = margin_rect.getX ();
311  float margin_w = margin_rect.getWidth ();
312 
313  x = margin_x + 0.5 * margin_w;
314 
315  float tmp = 0.045 * draw_w;
316  tmp = max ( tmp, 1.0f );
317  m_x_font_size = min ( tmp, static_cast<float>( 18.0 ) );
318  assert ( m_x_font_size > 0 );
319 
320  double ratio = draw_w / ( label.size() ) * 2;
321  m_x_font_size = std::min ( m_x_font_size, ratio );
322  assert ( m_x_font_size > 0 );
323  double one = 2.0;
324  m_x_font_size = std::max ( m_x_font_size, one );
325 
326  assert ( m_x_font_size > 0 );
327  if ( axisModel.getLabelLocation() & PLOTBOTTOM )
328  {
329  if ( m_xLabelFont != 0 ) {
330  y = draw_h - 1.5*m_xLabelFont->pointSize()-6.0; // experimental
331  view.drawText ( label, x, y, 0., 0.0, 'c', 't',
332  false, m_xLabelFont );
333  } else {
334  y = draw_h - m_x_font_size - 6.0; // take into account descenders
335  view.drawText ( label, x, y, m_x_font_size, 0.0, 'c', 't', false );
336  }
337  }
338  else if ( axisModel.getLabelLocation() & PLOTTOP )
339  {
340  y = 1.0;
341  if ( m_xLabelFont != 0 ) {
342 
343  view.drawText ( label, x, y, 0.0, 0.0, 'c', 't',
344  false, m_xLabelFont );
345  } else {
346 
347  view.drawText ( label, x, y, m_x_font_size, 0.0, 'c', 't', false );
348  }
349  }
350 
351 
352  // Draw the mag when both pmag and small range sci_note are needed.
353  // TODO: handle (location & PLOTTOP)
354  if ( (m_sci_note_x) && (axisModel.needPMag() ) ){
355  if ( m_xLabelFont == NULL ) {
356  x = x+0.27 * m_x_font_size * label.size();
357  y = y+0.2 * m_x_font_size;
358  view.drawText ( " x10", x, y, m_x_font_size*0.8, 0.0, 'c', 't', false );
359 
360  double pmag = axisModel.getPMag();
361  int i = static_cast < int > ( pmag );
362  const string text = String::convert ( i );
363  x += 1.0 * m_x_font_size ;
364  y -= 0.4 * m_x_font_size;
365  view.drawText ( text, x, y, m_x_font_size*0.8, 0.0, 'c', 't', false );
366  } else {
367  x = x+0.4 * m_xLabelFont->pointSize() * label.size();
368  view.drawText ( " x10", x, y, 0.0, 0.0, 'c', 't', false, m_xLabelFont );
369 
370  double pmag = axisModel.getPMag();
371  int i = static_cast < int > ( pmag );
372  const string text = String::convert ( i );
373  x += 1.6 * m_xLabelFont->pointSize() ;
374  y -= 0.4 * m_xLabelFont->pointSize();
375  view.drawText ( text, x, y, 0.0, 0.0, 'c', 't', false, m_xLabelFont );
376  }
377  }
378 #ifdef HAVE_TEX_UTILS
379  }
380 #endif
381 
382 }
383 void
385 drawYLabels ( const AxisModelBase & axisModel,
386  ViewBase & base, const std::string & y_label )
387 {
388  DataView & view = dynamic_cast < DataView & > ( base );
389 
390  // Calculate the ratio of range(rmag) and value(pmag) to decide
391  // where scientific notation is needed.
392  const vector< AxisTick > & ticks = axisModel.getTicks();
393  m_sci_note_y=false;
394  int mid = ticks.size()/2;
395  double ref = ticks[mid].value();
396  double range = ticks[mid+1].value()-ref;
397  if (fabs(ref/range)>1e6) m_sci_note_y=true;
398 
399 
400 #ifdef HAVE_TEX_UTILS
401  // Draw Latex at the left of the plotter if in Latex format
402  if (String::ci_find(y_label, "tex:")==0) {
403  string tex_snippet = y_label.substr(4);
404 
405  if (m_sci_note_y) {
406  tex_snippet+="-"+ticks[mid].content();
407  if (axisModel.needPMag()) {
408  // Use LaTeX to generate: label-mid*10^Pmag
409  tex_snippet+="\\times 10^"+String::convert ( static_cast <int> (axisModel.getPMag()) );
410  }
411  }
412 
413 
414  view.drawLatex ( tex_snippet, 3 );
415  }
416 
417  else {
418 #endif
419 
420 
421  std::string label;
422  if (m_sci_note_y) {
423  label = y_label+" - "+ticks[mid].content();
424  }
425  else {
426  label = y_label;
427  }
428 
429  Rect draw_rect = view.getDrawRect ();
430 
431  float x = 0., y = 0.;
432  AxisLoc location = axisModel.getLabelLocation();
433 
434  //float tmp = min ( view.getDrawRect().getWidth() * 0.05,
435  // view.getDrawRect().getHeight() * 0.05 );
436  float tmp = draw_rect.getHeight() * 0.05;
437  m_y_font_size = min( tmp, static_cast<float>( 18.0 ) );
438  m_y_font_size = min( m_y_font_size, draw_rect.getHeight()
439  / ( label.size() ) * 2 );
440  double one = 1.0;
441  m_y_font_size = max ( m_y_font_size, one );
442  y = view.getMarginRect().getY() +
443  view.getMarginRect().getHeight() *0.5;
444 
445  if ( location & PLOTLEFT )
446  {
447  x = 2.0;
448  if ( m_yLabelFont != 0 ) {
449  view.drawText ( label, x, y, 0.0, 90.0, 'c', 't',
450  false, m_yLabelFont );
451  } else {
452  view.drawText ( label, x, y, m_y_font_size, 90.0, 'c', 't', false );
453  }
454  }
455  else if ( location & PLOTRIGHT )
456  {
457  x = draw_rect.getWidth() - 2.0;
458  if ( m_yLabelFont != 0 ) {
459  view.drawText ( label, x, y, 0.0, -90.0, 'c', 't',
460  false, m_yLabelFont );
461  } else {
462  view.drawText ( label, x, y, m_y_font_size, -90.0, 'c', 't', false );
463  }
464  }
465 
466 
467  // Draw the mag when both pmag and small range sci_note are needed.
468  // TODO: handle (location & PLOTTOP)
469  if ( (m_sci_note_y) && (axisModel.needPMag() ) ){
470  if ( m_yLabelFont == NULL ) {
471  y = y-0.27 * m_y_font_size * label.size();
472  x = x+0.2 * m_y_font_size;
473  view.drawText ( " x10", x, y, m_y_font_size*0.8, 90.0, 'c', 't', false );
474 
475  double pmag = axisModel.getPMag();
476  int i = static_cast < int > ( pmag );
477  const string text = String::convert ( i );
478  x -= 0.4 * m_y_font_size ;
479  y -= 1.0 * m_y_font_size;
480  view.drawText ( text, x, y, m_y_font_size*0.8, 90.0, 'c', 't', false );
481  } else {
482  y = y-0.4 * m_yLabelFont->pointSize() * label.size();
483  view.drawText ( " x10", x, y, 0.0, 90.0, 'c', 't', false, m_yLabelFont );
484 
485  double pmag = axisModel.getPMag();
486  int i = static_cast < int > ( pmag );
487  const string text = String::convert ( i );
488  x -= 0.4 * m_yLabelFont->pointSize() ;
489  y -= 1.6 * m_yLabelFont->pointSize();
490  view.drawText ( text, x, y, 0.0, 90.0, 'c', 't', false, m_yLabelFont );
491  }
492  }
493 #ifdef HAVE_TEX_UTILS
494  }
495 #endif
496 }
497 
498 void
500 drawReferencePoint( const AxisModelBase & axisModel,
501  ViewBase & base,
502  const std::string & ref)
503 {
504  if ( axisModel.getScaleLocation() & PLOTBOTTOM )
505  {
506  DataView & view = dynamic_cast < DataView & > ( base );
507 
508  const Rect & margin_rect = view.getMarginRect ();
509  float x = margin_rect.getX() + margin_rect.getWidth ();
510 
511  x -= 1 * m_x_tick_font_size * ref.size();
512 
513  Rect view_rect = view.getDrawRect ();
514  float y = + view_rect.getHeight ();
515 
516  view.drawText ( "X Ref:"+ref, x, y, m_x_tick_font_size, 0., 'l', 'b' );
517  }
518  else if (axisModel.getScaleLocation() & PLOTLEFT)
519  {
520  DataView & view = dynamic_cast < DataView & > ( base );
521 
522  float x = 2.;
523  x += m_y_tick_font_size;
524 
525  const Rect & margin_rect = view.getMarginRect ();
526  float y = margin_rect.getY() + 0.2 * m_y_tick_font_size;
527 
528  view.drawText ( "Y Ref:"+ref, x, y, m_y_tick_font_size, 0., 'l', 'b' );
529  }
530 
531 }
532 
533 
534 void
536 drawXMag ( const AxisModelBase & axisModel,
537  ViewBase & base , const std::string & mag )
538 {
539  DataView & view = dynamic_cast < DataView & > ( base );
540 
541  const Rect & margin_rect = view.getMarginRect ();
542  float x = margin_rect.getX() + margin_rect.getWidth ();
543 
544  double pmag = axisModel.getPMag();
545  int i = static_cast<int> (pmag);
546  const string text = String::convert ( i );
547  x -= 0.8 * m_x_tick_font_size * text.size();
548 
549  Rect view_rect = view.getDrawRect ();
550  float y = + view_rect.getHeight ();
551 
552  view.drawText ( "x10", x, y, 0.75 * m_x_tick_font_size, 0., 'l', 'b' );
553 
554  x += 1.25 * m_x_tick_font_size ;
555  y -= 0.5 * m_x_tick_font_size;
556 
557  if (m_sci_note_x) {
558  view.drawText( mag, x, y, 0.75 * m_x_tick_font_size, 0., 'l', 'b' );
559  } else {
560  view.drawText ( text, x, y, 0.75 * m_x_tick_font_size, 0., 'l', 'b' );
561  }
562 }
563 
564 void
566 drawYMag ( const AxisModelBase & axisModel,
567  ViewBase & base, const std::string & mag )
568 {
569  DataView & view = dynamic_cast < DataView & > ( base );
570 
571  float x = 2.;
572  if ( axisModel.getScaleLocation() & PLOTLEFT ) {
573  x += m_y_tick_font_size;
574  }
575  else {
576  x -= m_y_tick_font_size;
577  }
578 
579  const Rect & margin_rect = view.getMarginRect ();
580  float y = margin_rect.getY() + 0.5 * m_y_tick_font_size;
581 
582  view.drawText ( "x10", x, y, m_y_tick_font_size, 0., 'l', 'b' );
583 
584  double pmag = axisModel.getPMag();
585  int i = static_cast < int > ( pmag );
586  const string text = String::convert ( i );
587  x += 1.75 * m_y_tick_font_size ;
588  y -= 0.5 * m_y_tick_font_size;
589 
590  if (m_sci_note_y) {
591  view.drawText ( mag, x, y, m_y_tick_font_size, 0., 'l', 'b' );
592  } else {
593  view.drawText ( text, x, y, m_y_tick_font_size, 0., 'l', 'b' );
594  }
595 
596 }
597 
598 void
601  ViewBase & view,
602  const Range & x_range,
603  const Range & y_range)
604 {
605  const BinaryTransform & t
606  = dynamic_cast< const BinaryTransform & > ( transform );
607  vector< double > xv ( 100 );
608  vector< double > yv ( 100 );
609  Color black ( 0, 0, 0 );
610 
611  xv[0] = x_range.low( );
612  yv[0] = y_range.low( );
613  for( int i = 1; i < 100; i++)
614  {
615  xv[i] = xv[i-1] + ( x_range.high() - x_range.low() )/99;
616  yv[i] = yv[i-1];
617  }
618  t.transform( xv, yv );
619  view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
620 
621 
622  xv[0] = x_range.high( );
623  yv[0] = y_range.low( );
624  for( int i = 1; i < 100; i++)
625  {
626  xv[i] = xv[i-1];
627  yv[i] = yv[i-1] + ( y_range.high() - y_range.low() )/99; ;
628  }
629  t.transform( xv, yv );
630  view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
631 
632 
633  xv[0] = x_range.low( );
634  yv[0] = y_range.high( );
635  for( int i = 1; i < 100; i++)
636  {
637  xv[i] = xv[i-1] + ( x_range.high() - x_range.low() )/99;
638  yv[i] = yv[i-1];
639  }
640 
641  t.transform( xv, yv );
642  view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
643 
644 
645  xv[0] = x_range.low( );
646  yv[0] = y_range.low( );
647  for( int i = 1; i < 100; i++)
648  {
649  xv[i] = xv[i-1];
650  yv[i] = yv[i-1] + ( y_range.high() - y_range.low() )/99;
651  }
652 
653  t.transform( xv, yv );
654  view.drawPolyLine ( xv, yv, Line::Solid, black, 1 );
655 
656 
657 }
658 
659 
660 
661 void AxisRepBase::drawGridLines( const AxisModelBase & axisModelX,
662  const AxisModelBase & axisModelY,
663  TransformBase & transform,
664  ViewBase & view )
665 {
666  Range x_range = axisModelX.getRange( false );
667  Range y_range = axisModelY.getRange( false );
668 
669 
670  const vector< AxisTick > & x_ticks = axisModelX.getTicks();
671  const vector< AxisTick > & y_ticks = axisModelY.getTicks();
672 
673  unsigned int nxpoints = 100;
674  unsigned int nypoints = 100;
675  vector< double > xv(100), yv(100);
676 
677  double user_x, user_y;
678  Color grey( 180, 180, 180 );
679 
680  BinaryTransform & t
681  = dynamic_cast< BinaryTransform & > ( transform );
682 
683  t.validate( x_range, y_range );
684 
685  if ( x_ticks.empty () == true || y_ticks.empty () == true )
686  return;
687 
688 
689  double dx = ( x_range.high() - x_range.low() ) / ( nxpoints - 1 );
690  double dy = ( y_range.high() - y_range.low() ) / ( nypoints - 1 ) ;
691 
692 
693  // Drawing the coordinates of the aligned along y-Axis
694  // i.e.curves for which x = const
695  // Don't draw first tick if it will cover the left edge.
696  for ( unsigned int i = ( x_range.low() == x_ticks[0].value() )?1:0;
697  i < x_ticks.size(); i++ )
698  {
699  user_x = x_ticks[ i ].value();
700 
701  for ( unsigned int j = 0; j < nypoints; j++ )
702  {
703  user_y = y_range.low() + j * dy;
704 
705  xv[ j ] = user_x;
706  yv[ j ] = user_y;
707 
708  }
709 
710  t.transform( xv, yv );
711  view.drawPolyLine ( xv, yv, Line::Dot, grey, 0 );
712 
713  }
714 
715 
716  // Drawing the coordinates of the aligned along x-Axis
717  // i.e.curves for which y = const
718  // Don't draw first tick if it will cover the bottom edge.
719  for ( unsigned int j = ( y_range.low() == y_ticks[0].value() )?1:0;
720  j < y_ticks.size(); j++ )
721  {
722  user_y = y_ticks[ j ].value();
723 
724  for ( unsigned int i = 0; i < nxpoints; i++ )
725  {
726  user_x = x_range.low() + i * dx;
727 
728  xv[ i ] = user_x ;
729  yv[ i ] = user_y ;
730  }
731 
732  t.transform( xv, yv );
733  view.drawPolyLine( xv, yv, Line::Dot, grey, 0 );
734  }
735 
736  return;
737 }
738 
739 void
741 drawXTickLines( const AxisModelBase & axisModelX,
742  const AxisModelBase & axisModelY,
743  const TransformBase & transform,
744  ViewBase & base )
745 {
746  DataView & view = dynamic_cast < DataView & > ( base );
747  AxisLoc loc = axisModelX.getLabelLocation();
748  assert( loc == PLOTBOTTOM || PLOTTOP );
749 
750  const vector< AxisTick > & ticks = axisModelX.getTicks();
751  if ( ticks.empty() == true ) return;
752 
753  vector< double > xv;
754  vector< double > yv;
755 
756  unsigned int size = 4 * ticks.size();
757  xv.reserve( size );
758  yv.reserve( size );
759 
760  const BinaryTransform & t
761  = dynamic_cast< const BinaryTransform & > ( transform );
762 
763  const Rect & view_rect = view.getMarginRect();
764  double tick_length = 0.05 * view_rect.getHeight();
765  tick_length = min ( tick_length, 8. );
766  Range yrange = axisModelY.getRange( false );
767 
768  for ( unsigned int i = 0; i < ticks.size(); i++ )
769  {
770  double user_x_start = ticks[i].value ();
771  double user_x_temp = user_x_start;
772 
773  double user_by_start = yrange.low();
774  double user_ty_start = yrange.high();
775 
776  // transform will change the x value, so we need the temp
777  t.transform ( user_x_start, user_by_start );
778  t.transform ( user_x_temp, user_ty_start );
779 
780  double view_x_start = view.userToDrawXAutoInv ( user_x_start );
781  double view_by_start = view.userToDrawY ( user_by_start );
782  double view_ty_start = view.userToDrawY ( user_ty_start );
783 
784  double view_x_end = view_x_start;
785  double view_by_end = view_by_start - tick_length;
786  double view_ty_end = view_ty_start + tick_length;
787 
788 #ifdef __USE_ISOC99
789  if( isfinite( view_x_start ) &&
790  isfinite( view_by_start ) &&
791  isfinite( view_ty_start ) &&
792  isfinite( view_x_start ) &&
793  isfinite( view_by_end ) )
794 #else
795  if( finite( view_x_start ) &&
796  finite( view_by_start ) &&
797  finite( view_ty_start ) &&
798  finite( view_x_start ) &&
799  finite( view_by_end ) )
800 #endif
801  {
802  xv.push_back( view_x_start );
803  yv.push_back( view_by_start );
804  xv.push_back( view_x_end );
805  yv.push_back( view_by_end );
806 
807  xv.push_back( view_x_start );
808  yv.push_back( view_ty_start );
809  xv.push_back( view_x_end );
810  yv.push_back( view_ty_end );
811  }
812  }
813 
814  view.drawViewLines ( xv, yv, Line::Solid, false, 1 );
815 }
816 
817 void
819 drawYTickLines ( const AxisModelBase & axisModelX,
820  const AxisModelBase & axisModelY,
821  const TransformBase & transform,
822  ViewBase & base )
823 {
824  AxisLoc loc = axisModelY.getLabelLocation ();
825  assert ( loc == PLOTLEFT || loc == PLOTRIGHT );
826 
827  DataView & view = dynamic_cast < DataView & > ( base );
828  const Rect & draw_rect = view.getMarginRect ();
829 
830  double tick_length = 0.05 * draw_rect.getWidth ();
831  tick_length = min ( tick_length, 8. );
832 
833  vector< double > xv;
834  vector< double > yv;
835 
836  const vector< AxisTick > & ticks = axisModelY.getTicks ();
837  unsigned int size = ticks.size ();
838 
839  if ( size == 0 ) return;
840 
841  size *= 4;
842 
843  xv.reserve ( size );
844  yv.reserve ( size );
845 
846  const BinaryTransform & t
847  = dynamic_cast< const BinaryTransform & > ( transform );
848 
849  Range xrange = axisModelX.getRange( false );
850 
851  for ( unsigned int i = 0; i < ticks.size(); i++ )
852  {
853  double user_lx_start = xrange.low();
854  double user_rx_start = xrange.high();
855  double user_y_start = ticks[i].value();
856  double user_y_temp = user_y_start; // for second call to transform
857 
858  // transform modifies its argument, thus we need 2 separate y's
859  t.transform( user_lx_start, user_y_start );
860  t.transform( user_rx_start, user_y_temp );
861 
862  double view_lx_start = view.userToDrawX( user_lx_start );
863  double view_rx_start = view.userToDrawX( user_rx_start );
864  double view_y_start = view.userToDrawY( user_y_start );
865 
866  double view_lx_end = view_lx_start + tick_length;
867  double view_rx_end = view_rx_start - tick_length;
868  double view_y_end = view_y_start;
869 
870 #ifdef __USE_ISOC99
871  if( isfinite( view_lx_start ) &&
872  isfinite( view_y_start ) &&
873  isfinite( view_lx_start ) &&
874  isfinite( view_y_end ) )
875 #else
876  if( finite( view_lx_start ) &&
877  finite( view_y_start ) &&
878  finite( view_lx_start ) &&
879  finite( view_y_end ) )
880 #endif
881  {
882  xv.push_back( view_lx_start );
883  yv.push_back( view_y_start );
884  xv.push_back( view_lx_end );
885  yv.push_back( view_y_end );
886 
887  xv.push_back( view_rx_start );
888  yv.push_back( view_y_start );
889  xv.push_back( view_rx_end );
890  yv.push_back( view_y_end );
891  }
892  }
893 
894  view.drawViewLines ( xv, yv, Line::Solid, false, 1 );
895 }
896 
897 void
899 setFontSize( const AxisModelBase * xAxisModel,
900  const AxisModelBase * yAxisModel,
901  const AxisModelBase * zAxisModel,
902  ViewBase & view )
903 {
904  Rect draw_rect = view.getDrawRect();
905 
906  m_font_size = min( ( draw_rect.getWidth() ) * 0.040, 12.0 );
907  m_font_size = min (m_font_size, 12.0);
908  double one = 1.0;
909  m_font_size = max ( m_font_size, one );
910  setXFontSize ( *xAxisModel, view );
911  setYFontSize ( *yAxisModel, view );
912  if ( zAxisModel != 0 ) setZFontSize ( *zAxisModel, view );
913 }
914 
915 void
917 drawXTickLabels ( const AxisModelBase & axisModelX,
918  const AxisModelBase & axisModelY,
919  const TransformBase & transform,
920  ViewBase & base )
921 {
922  double padding = 1.0;
923 
924  vector < double > xv;
925  vector < double > yv;
926 
927  const vector < AxisTick > & ticks = axisModelX.getTicks ();
928  unsigned int size = ticks.size ();
929  if ( size == 0 ) return;
930 
931  xv.reserve ( size );
932  yv.reserve ( size );
933 
934  Range yrange = axisModelY.getRange( false );
935 
936  for ( unsigned int i = 0; i < size; i++ ){
937  xv.push_back ( ticks[i].value () );
938  yv.push_back ( yrange.low() );
939  }
940 
941  const BinaryTransform & t
942  = dynamic_cast< const BinaryTransform & > ( transform );
943  t.transform ( xv, yv );
944 
945  // Calculate the Y position in view coordinates.
946  DataView & view = dynamic_cast < DataView & > ( base );
947  const Rect & margin = view.getMarginRect ();
948  float y = margin.getY ();
949  float x;
950  char yp = 'b';
951 
952  if ( axisModelX.getScaleLocation() & PLOTBOTTOM ) {
953  y = margin.getY () + margin.getHeight ();
954  yp = 't';
955  }
956 
957  // If scientific notation is needed, calculate mag.
958  string mag="";
959  double ref = 0.;
960  if (m_sci_note_x) {
961  int mid = ticks.size()/2;
962  ref = ticks[mid].value();
963  double range = ticks[mid+1].value()-ref;
964  char cstr[8];
965  sprintf(cstr, "%.0e", range);
966  string str(cstr);
967  string::size_type pos = str.find ( 'e' );
968  mag=string( str, pos + 1 ); // exponent
969  }
970 
971  for ( unsigned int i = 0; i < ticks.size(); i++ )
972  {
973  // In first stage we calculate the tick. This shall help us get
974  // the direction of the tick and using it we shall locate where
975  // to draw the tick labels.
976  double user_x_start = ticks[i].value();
977  double user_y_start = yrange.low();
978 
979  t.transform( user_x_start, user_y_start );
980 
981  double view_x_start = view.userToDrawXAutoInv( user_x_start );
982  double view_y_start = view.userToDrawY( user_y_start );
983 
984  double user_x_end = ticks[i].value ();
985  double user_y_end =
986  yrange.low() + .05 * ( yrange.high() - yrange.low() );
987 
988  t.transform( user_x_end, user_y_end );
989 
990  double view_x_end = view.userToDrawXAutoInv( user_x_end );
991  double view_y_end = view.userToDrawY( user_y_end );
992 
993  // Calculating the unit vector (ux,uy) in the direction of the tick
994  double dx = view_x_end - view_x_start;
995  double dy = view_y_end - view_y_start;
996 
997  double ux = dx / sqrt( dx * dx + dy * dy );
998  double uy = dy / sqrt ( dx * dx + dy * dy );
999 
1000  // Now calculate the x coord of the end point of the tick by
1001  // moving a distance "tick_length" starting from view_x_start
1002  // in the direction of ux. Similarly for y coordinate.
1003  x = view_x_start - ux * padding;
1004  y = view_y_start - uy * padding;
1005 
1006  // Plot the labels now. ( Handle two mode. )
1007  if (m_sci_note_x){
1008  // Draw the difference from reference tick value.
1009  double diff=ticks[i].value()-ref;
1010  // 6 byte should be enough, as small as -1e-99
1011  char pstr[8];
1012  sprintf(pstr, "%.0e", diff);
1013  const std::string str(pstr);
1014  string::size_type pos = str.find ( 'e' );
1015  string m ( str, 0, pos ); // mantessa
1016  string e ( str, pos + 1 ); // exponent
1017  // Is this safe ?
1018  if (e!=mag && m!="0") m+="0";
1019  drawXTickLabel ( m, x, y, view );
1020  }
1021  else {
1022  // Draw the content of the ticks.
1023  drawXTickLabel ( ticks[i].content(), x, y, view );
1024  }
1025  }
1026 
1027  // Draw sct_note reference point or pmag.
1028  if (m_sci_note_x) {
1029  drawXMag( axisModelX, view, mag );
1030  //drawXLabels(axisModelX, view, "X="+ticks[mid].content());
1031  //drawReferencePoint( axisModelX, view, ticks[mid].content());
1032  }
1033 
1034  else if ( axisModelX.needPMag () )
1035  {
1036  // Logarithmic graphs do not need the magnitude written.
1037  if ( axisModelX.isLog () == false ) {
1038  drawXMag ( axisModelX, view );
1039  }
1040  }
1041 }
1042 
1043 void
1045 drawYTickLabels ( const AxisModelBase & axisModelX,
1046  const AxisModelBase & axisModelY,
1047  const TransformBase & transform,
1048  ViewBase & view )
1049 {
1050  double padding = 2.0;
1051 
1052  const vector< AxisTick > & ticks = axisModelY.getTicks ();
1053  unsigned int size = ticks.size ();
1054  if ( size == 0 ) return;
1055 
1056  const BinaryTransform & t
1057  = dynamic_cast< const BinaryTransform & > ( transform );
1058 
1059  Range xrange = axisModelX.getRange( false );
1060 
1061  // If scientific notation is needed, calculate mag.
1062  string mag="";
1063  double ref = 0.;
1064  if (m_sci_note_y) {
1065  int mid = ticks.size()/2;
1066  ref = ticks[mid].value();
1067  double range = ticks[mid+1].value()-ref;
1068  char cstr[8];
1069  sprintf(cstr, "%.0e", range);
1070  string str(cstr);
1071  string::size_type pos = str.find ( 'e' );
1072  mag=string( str, pos + 1 ); // exponent
1073  }
1074 
1075  for ( unsigned int i = 0; i < ticks.size(); i++ )
1076  {
1077  // In first stage we calculate the tick. This shall help us get
1078  // the direction of the tick and using it we shall locate where
1079  // to draw the tick labels.
1080  double user_x_start = xrange.low();
1081  double user_y_start = ticks[i].value();
1082 
1083  t.transform( user_x_start, user_y_start );
1084 
1085  double view_x_start = view.userToDrawX( user_x_start );
1086  double view_y_start = view.userToDrawY( user_y_start );
1087 
1088  double user_x_end
1089  = xrange.low() + .05 * ( xrange.high() - xrange.low() );
1090  double user_y_end = ticks[i].value ();
1091 
1092  t.transform( user_x_end, user_y_end );
1093 
1094  double view_x_end = view.userToDrawX( user_x_end );
1095  double view_y_end = view.userToDrawY( user_y_end );
1096 
1097  // Calculating the unit vector (ux,uy) in the direction of the tick
1098  double dx = view_x_end - view_x_start;
1099  double dy = view_y_end - view_y_start;
1100 
1101  double ux = dx / sqrt( dx * dx + dy * dy );
1102  double uy = dy / sqrt ( dx * dx + dy * dy );
1103 
1104  // Now calculate the x coord of the end point of the tick by
1105  // moving a distance "tick_length" starting from view_x_start
1106  // in the direction of ux. Similarly for y coordinate.
1107  float x = view_x_start - ux * padding;
1108  float y = view_y_start - uy * 1.5;
1109 
1110  // Plot the labels now. ( Handle two mode. )
1111  if (m_sci_note_y){
1112  // Draw the difference from reference tick value.
1113  double diff=ticks[i].value()-ref;
1114  // 6 byte should be enough, as small as -1e-99
1115  char pstr[8];
1116  sprintf(pstr, "%.0e", diff);
1117  const std::string str(pstr);
1118  string::size_type pos = str.find ( 'e' );
1119  string m ( str, 0, pos ); // mantessa
1120  string e ( str, pos + 1 ); // exponent
1121  // Is this safe?
1122  if (e!=mag && m!="0") m+="0";
1123  drawYTickLabel ( m, x, y, view );
1124  }
1125  else {
1126  // Draw the content of the ticks.
1127  drawYTickLabel ( ticks[i].content(), x, y, view );
1128  }
1129  }
1130 
1131 
1132  // Draw pmag.
1133  if (m_sci_note_y) {
1134  drawYMag( axisModelY, view, mag );
1135  }
1136 
1137  else if ( axisModelY.needPMag () ){
1138  // Logarithmic graphs do not need the magnitude written.
1139  if ( axisModelY.isLog () == false ) {
1140  drawYMag ( axisModelY, view );
1141  }
1142  }
1143 }
1144 
1145 void
1147 drawXTickLabel ( const std::string & label, float x, float y, ViewBase & view )
1148 {
1149  char xalign = 'c';
1150  char yalign = 't';
1151  float angle = 0.;
1152  double & font_size = m_x_tick_font_size;
1153 
1154  string::size_type pos = label.find ( 'e' );
1155  if ( pos == string::npos ) {
1156  view.drawText ( label, x, y, m_x_tick_font_size, angle, xalign, yalign );
1157  }
1158  else { // need superscript
1159  double ss_size = 0.9 * font_size;
1160  string m ( label, 0, pos ); // mantessa
1161  string e ( label, pos + 1 ); // exponent
1162  if ( m == "1" ) {
1163  m += "0";
1164  x += 0.25 * font_size; // don't know why this is needed.
1165  y += 0.25 * ss_size;
1166  view.drawText ( m, x, y, font_size, angle, 'r', yalign );
1167 
1168  if ( e[0] == '-' ) {
1169  x -= 0.10 * font_size;
1170  }
1171  y -= 0.5 * ss_size;
1172  view.drawText ( e, x, y, ss_size, angle, 'l', yalign );
1173  }
1174  else { // m != 1
1175  m += "x10";
1176  x += 0.25 * font_size;
1177  y += 0.25 * ss_size;
1178  view.drawText ( m, x, y, font_size, angle, 'r', yalign );
1179 
1180  if ( e[0] == '-' ) {
1181  x -= 0.10 * font_size;
1182  }
1183  y -= 0.5 * ss_size;
1184  view.drawText ( e, x, y, ss_size, angle, 'l', yalign );
1185  }
1186  }
1187 }
1188 
1189 
1190 void
1192 drawYTickLabel ( const std::string & label,
1193  float x, float y,
1194  ViewBase & view )
1195 {
1196  char xalign = 'r';
1197  char yalign = 'c';
1198  float angle = 0.;
1199  double font_size = m_y_tick_font_size;
1200 
1201  string::size_type pos = label.find ( 'e' );
1202  if ( pos == string::npos ) {
1203  view.drawText ( label, x, y, font_size, angle, xalign, yalign );
1204  }
1205 
1206  else { // need superscript
1207  string m ( label, 0, pos ); // mantessa
1208  string e ( label, pos + 1 ); // exponent
1209 
1210  if ( m == "1" ) {
1211  m += "0";
1212  x = x - 0.40 * font_size * e.size();
1213  view.drawText ( m, x, y, font_size, angle, xalign, yalign );
1214 
1215  if ( e[0] == '-' ) {
1216  x -= 0.20 * font_size;
1217  }
1218  y = y - 0.625 * font_size;
1219  view.drawText ( e, x, y, 0.9 * font_size, angle, 'l', yalign );
1220  }
1221  else { // m != '1' and need to leave room for label
1222  m += "x10";
1223  x = x - 0.40 * font_size * e.size();
1224  view.drawText (m, x, y, font_size, angle, xalign, yalign );
1225 
1226  if ( e[0] == '-' ) {
1227  x -= 0.20 * font_size;
1228  }
1229  y = y - 0.625 * font_size;
1230  view.drawText ( e, x, y, 0.9 * font_size, angle, 'l', yalign );
1231  }
1232  }
1233 }
1234 
1235 
1236 void
1238 drawYTickLabels ( const std::vector < AxisTick > & ticks,
1239  const std::vector < float > & xv,
1240  const std::vector < float> & yv,
1241  ViewBase & view)
1242 {
1243  char xalign = 'r';
1244  char yalign = 'c';
1245  float angle = 0.;
1246  double font_size = m_y_tick_font_size;
1247 
1248  const string & alabel = ticks[0].content();
1249  string::size_type pos = alabel.find ( 'e' );
1250  bool sci_notate = pos != string::npos;
1251 
1252  if ( sci_notate == false ) {
1253  for ( unsigned int i = 0; i < ticks.size(); i++ ) {
1254  view.drawText ( ticks[i].content(), xv[i], yv[i],
1255  font_size, angle, xalign, yalign );
1256  }
1257  }
1258  else { // need superscript
1259  bool mixed_m = false;
1260  for ( unsigned int i = 0; i < ticks.size (); i++ ) {
1261  const string & label = ticks[i].content ();
1262  string m ( label, 0, pos ); // mantessa
1263  string e ( label, pos + 1 ); // exponent
1264  mixed_m |= m != "1";
1265  }
1266  if ( mixed_m == true ) {
1267  font_size *= 0.90;
1268  }
1269  for ( unsigned int i = 0; i < ticks.size (); i++ ) {
1270  const string & label = ticks[i].content();
1271  string::size_type pos = alabel.find ( 'e' );
1272  string m ( label, 0, pos );
1273  string e ( label, pos + 1 );
1274  if ( m == "1" ) {
1275  m += "0";
1276  float x = xv[i] - 0.40 * font_size * e.size();
1277  view.drawText ( m, x, yv[i], font_size, angle, xalign, yalign );
1278 
1279  if ( e[0] == '-' ) {
1280  x -= 0.20 * font_size;
1281  }
1282  float y = yv[i] - 0.625 * font_size;
1283  view.drawText ( e, x, y, 0.9 * font_size, angle, 'l', yalign );
1284  }
1285  else { // m != '1' and need to leave room for label
1286  m += "x10";
1287  float x = xv[i] - 0.40 * font_size * e.size();
1288  view.drawText (m, x, yv[i], font_size, angle, xalign, yalign );
1289 
1290  if ( e[0] == '-' ) {
1291  x -= 0.20 * font_size;
1292  }
1293  float y = yv[i] - 0.625 * font_size;
1294  view.drawText ( e, x, y, 0.9 * font_size, angle, 'l', yalign );
1295  }
1296  }
1297  }
1298 }
1299 
1300 void
1302 drawCrossHairs ( double x, double y,
1303  TransformBase & tb,
1304  ViewBase & view )
1305 {
1306 
1307  vector < double > xv ( 4 );
1308  vector < double > yv ( 4 );
1309 
1310 
1311  const BinaryTransform & tf
1312  = dynamic_cast< const BinaryTransform & > ( tb );
1313 
1314  if ( tf.isPeriodic() )
1315  {
1316  const PeriodicBinaryTransform & tp
1317  = dynamic_cast < const PeriodicBinaryTransform & > ( tb );
1318 
1319  double xoffset = tp.xOffset();
1320  double yoffset = tp.yOffset();
1321 
1322  x = tp.moduloSubX( x, xoffset );
1323  y = tp.moduloSubY( y, yoffset );
1324  }
1325 
1326  tf.transform ( x,y );
1327 
1328  xv[0] = m_axis_x_origin;
1329  yv[0] = y;
1330 
1331  xv[1] = m_axis_width + m_axis_x_origin;
1332  yv[1] = y;
1333 
1334  xv[2] = x;
1335  yv[2] = m_axis_height + m_axis_y_origin;
1336 
1337  xv[3] = x;
1338  yv[3] = m_axis_y_origin;
1339 
1340  // Note: m_axis_* is already in the transformed system.
1341  Color grey ( 180, 180, 180 );
1342  view.drawLines ( xv, yv, Line::Solid, grey, 0 );
1343 
1344 }
1345 
1350 void
1352 drawAllXTicks ( const AxisModelBase & axisModelX,
1353  const AxisModelBase & axisModelY,
1354  const TransformBase & transform,
1355  ViewBase & view )
1356 {
1357  drawXTickLines ( axisModelX, axisModelY, transform, view );
1358  drawXTickLabels ( axisModelX, axisModelY, transform, view );
1359 }
1360 
1361 void
1363 drawAllYTicks ( const AxisModelBase & axisModelX,
1364  const AxisModelBase & axisModelY,
1365  const TransformBase & transform,
1366  ViewBase & view )
1367 {
1368  drawYTickLines ( axisModelX, axisModelY, transform, view );
1369  drawYTickLabels ( axisModelX, axisModelY, transform, view );
1370 }
1371 
1372 
1374 {
1375  assert( font != 0 );
1376  if( m_xLabelFont == NULL )
1377  m_xLabelFont = font;
1378  else
1379  {
1380  delete m_xLabelFont;
1381  m_xLabelFont = font;
1382  }
1383 }
1384 
1386 {
1387  return m_xLabelFont;
1388 }
1389 
1390 
1392 {
1393  assert( font != 0 );
1394  if( m_yLabelFont == NULL )
1395  m_yLabelFont = font;
1396  else
1397  {
1398  delete m_yLabelFont;
1399  m_yLabelFont = font;
1400  }
1401 }
1402 
1404 {
1405  return m_yLabelFont;
1406 }
1407 
1408 
1410 {
1411  assert( font != 0 );
1412  if( m_zLabelFont == NULL )
1413  m_zLabelFont = font;
1414  else
1415  {
1416  delete m_zLabelFont;
1417  m_zLabelFont = font;
1418  }
1419 }
1420 
1422 {
1423  return m_zLabelFont;
1424 }
1425 
1427 {
1428  assert( font != 0 );
1429  if( m_titleFont == NULL )
1430  m_titleFont = font;
1431  else
1432  {
1433  delete m_titleFont;
1434  m_titleFont = font;
1435  }
1436 }
1437 
1439 {
1440  return m_titleFont;
1441 }
1442 
1443 void
1445 {
1446  assert ( false );
1447 }

Generated for HippoDraw Class Library by doxygen