Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

AxisModelLinear.cxx

Go to the documentation of this file.
00001 
00016 #ifdef _MSC_VER
00017 // Include max() and min() missing from MicroSoft Visual C++.
00018 #include "msdevstudio/MSconfig.h"
00019 #endif //_MSC_VER
00020 
00021 #include "AxisModelLinear.h"
00022 
00023 #include "AxisTick.h"
00024 
00025 #include <algorithm>
00026 
00027 #include <cmath>
00028 #include <cstdio>
00029 
00030 using std::abs;
00031 using std::ceil;
00032 using std::floor;
00033 using std::log10;
00034 using std::max;
00035 using std::min;
00036 using std::pow;
00037 using std::string;
00038 using std::vector;
00039 
00040 AxisModelLinear::AxisModelLinear ( AxisLoc label_loc, 
00041                                    AxisLoc scale_loc )
00042   : AxisModelBase ( label_loc, scale_loc )
00043 {    
00044 }
00045 
00046 AxisModelLinear::AxisModelLinear( const AxisModelBase & axis_model )
00047   : AxisModelBase( axis_model )
00048 {
00049 }
00050 
00051 AxisModelLinear::~AxisModelLinear()
00052 {
00053 }
00054 
00055 /* virtual */
00056 AxisModelBase * AxisModelLinear::clone() const
00057 {
00058   return new AxisModelLinear( *this );
00059 }
00060 
00061 bool FLT_EQUAL( double x, double y )
00062 {
00063   return ( abs( x - y ) <= 100.0 *  DBL_EPSILON  );
00064 }
00065 
00066 bool AxisModelLinear::isLog() const 
00067 { 
00068   return false; 
00069 }
00070 
00071 bool AxisModelLinear::needPMag () const
00072 {
00073   return m_use_pmag;
00074 }
00075 
00076 const Range &
00077 AxisModelLinear::adjustValues ( const Range & limit )
00078 {
00079   //Because the low value, the high value, and the length value of the
00080   //range were so frequently used, I added those three fields. There 
00081   //should be an improvement in performance.
00082   double mylow, myhigh;
00083   
00084   //The use of a step field and of a mag field will be explained when
00085   //they are first initialized.
00086   double step, magnitude;
00087   
00088   adjustLogValues();
00089   const int N_NICE = 6;
00090 #ifndef __STDC__
00091   static
00092 #endif
00093     float nice[N_NICE] = { 1.0, 2.0, 2.5,
00094                            4.0, 5.0, 7.5 };
00095 
00096   const Range & init_range = getRange ( false );
00097   double low = init_range.low ();
00098   double high = init_range.high ();
00099   if ( low == high ) {  // all values in same bin
00100     if ( low > 0.0 ) low *= 0.95;
00101     else  low *= 1.05;
00102 
00103     if ( high > 0.0 ) high *= 1.05;
00104     else high *= 0.95;
00105 
00106     setRange ( low, high, low );
00107   }  
00108   //setTickStep();
00109   double range_length;
00110   
00111   int i;
00112   
00113   //double tick_step = getTickStep();
00114   //tick_step /= m_scale_factor;
00115   //myhigh = mylow = floor( low / tick_step ) * tick_step;
00116 
00117   // This increases myhigh so that "myrange" covers the whole range
00118   // and then some.
00119   //while( myhigh <= high ) myhigh += tick_step;
00120   mylow  = low  - 0.05*(high-low);
00121   myhigh = high + 0.05*(high-low);
00122 
00123   range_length = myhigh - mylow;
00124 
00125   // We have now decided on a range.  This tries to move low/high a
00126   // little to end up on a nice number.
00127 
00128   // First checks if either end is near 0.0
00129   if( low >= 0.0 && range_length > ( 1.05 * high ) ) {
00130     Range range ( 0.0, range_length );
00131     setIntersectRange ( range, limit );
00132     return m_range;
00133   }
00134   if( high <= 0.0 && -range_length < ( 1.05 * low ) ) {
00135     Range range ( -range_length, 0.0 );
00136     setIntersectRange ( range, limit );
00137     return m_range;
00138   }
00139 
00140   // magnitude is used to hold the magnitude of the high or low values.
00141 
00142   i = N_NICE - 1;
00143   if( myhigh != 0.0 )
00144     magnitude = ceil( log10( abs( myhigh ) ) );
00145   else
00146     magnitude = ceil( log10( abs( mylow ) ) );
00147   
00148   // What this part does is go through the low, giving it round
00149   // numbers first, but more coarse over time.
00150 
00151   do {
00152     step = nice[i] * pow( 10.0, magnitude );
00153     mylow = floor( low / step ) * step;
00154     myhigh = mylow + 1.05 * range_length;
00155     i--;
00156     if( i < 0 ) {
00157       i = N_NICE - 1;
00158       magnitude--;
00159     }
00160   } while( myhigh < high );
00161 
00162   Range range ( mylow, myhigh, init_range.pos() );  
00163 
00164   setIntersectRange ( range, limit );
00165 
00166   return m_range;
00167 }
00168 
00169 const Range &
00170 AxisModelLinear::adjustLogValues()
00171 {
00172   // This doesn't do jack.
00173   return getRange(false);
00174 }
00175 
00178 Range AxisModelLinear::calcLow ( int parm, bool dragging )
00179 {
00180   startDragging ( dragging );
00181 
00182   double length = m_start_range.length ();
00183   double low = m_start_range.low ();
00184   double high = m_start_range.high ();
00185 
00186   double multiplier = ( parm - 50 ) / 50.0;
00187   double new_low = min ( low + length * multiplier, high );
00188 
00189   if( new_low == m_range.high() ) return m_range;
00190 
00191   return Range ( new_low, high, m_range.pos() );
00192 }
00193 
00196 Range AxisModelLinear::calcHigh ( int parm, bool dragging )
00197 {
00198   startDragging ( dragging );
00199 
00200   double length = m_start_range.length ();
00201   double low = m_start_range.low ();
00202   double high = m_start_range.high ();
00203 
00204   double multiplier = ( parm - 50 ) / 50.0;
00205   double new_high = max ( high + length * multiplier, low );
00206 
00207   if( new_high == m_range.low() ) return m_range;
00208 
00209   return Range ( low, new_high, m_range.pos() );
00210 }

Generated for HippoDraw-1.14.8.5 by doxygen 1.4.3