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

Generated for HippoDraw Class Library by doxygen