inlib
1.2.0
|
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved. 00002 // See the file inlib.license for terms. 00003 00004 #ifndef inlib_sg_axis 00005 #define inlib_sg_axis 00006 00007 #include "../fmath" 00008 00009 namespace inlib { 00010 namespace sg { 00011 00012 class axis { 00013 public: 00014 axis() 00015 :m_min_value(0) 00016 ,m_max_value(0) 00017 ,m_steps(0) 00018 ,m_is_log(false) 00019 {} 00020 virtual ~axis(){} 00021 public: 00022 axis(const axis& a_from) 00023 :m_min_value(a_from.m_min_value) 00024 ,m_max_value(a_from.m_max_value) 00025 ,m_steps(a_from.m_steps) 00026 ,m_is_log(a_from.m_is_log) 00027 {} 00028 axis& operator=(const axis& a_from){ 00029 m_min_value = a_from.m_min_value; 00030 m_max_value = a_from.m_max_value; 00031 m_steps = a_from.m_steps; 00032 m_is_log = a_from.m_is_log; 00033 return *this; 00034 } 00035 public: 00036 bool is_log(bool a_v){ 00037 if(m_is_log==a_v) return false; 00038 m_is_log = a_v; 00039 return true; 00040 } 00041 bool min_value(float a_v) { 00042 if(m_min_value==a_v) return false; 00043 m_min_value = a_v; 00044 return true; 00045 } 00046 bool max_value(float a_v) { 00047 if(m_max_value==a_v) return false; 00048 m_max_value = a_v; 00049 return true; 00050 } 00051 float min_value() const {return m_min_value;} 00052 float max_value() const {return m_max_value;} 00053 bool is_log() const {return m_is_log;} 00054 00055 void adjust_axis() { //from hippodraw. 00056 int axis = 0; 00057 float step; 00058 float mylow, myhigh; 00059 #define N_NICE 4 00060 static const float nice[N_NICE] = { 1.0,2.0,2.5,5.0 }; 00061 00062 if (m_min_value > m_max_value) { 00063 float low = m_min_value; 00064 m_min_value = m_max_value; 00065 m_max_value = low; 00066 } else if (m_min_value == m_max_value) { 00067 float value = m_min_value; 00068 m_min_value = value - 1; 00069 m_max_value = value + 1; 00070 return; 00071 } 00072 00073 //if (m_steps <= 0) { 00074 axis = 1; 00075 m_steps = 10; 00076 //} 00077 00078 // Round the "bin width" to a nice number. 00079 // If this is being done for an axis (ie m_steps was 0 , then 00080 // we don't have to go > *m_max_value. 00081 // 00082 float w = (m_max_value - m_min_value)/((float)m_steps); 00083 float mag = ffloor(flog10(w)); 00084 int i = 0; 00085 do { 00086 step = nice[i] * fpow(10.0,mag); 00087 00088 mylow = ffloor(m_min_value/step) * step; 00089 myhigh = axis==1 ? fceil(m_max_value/step) * step : 00090 mylow + step * m_steps; 00091 00092 i++; 00093 if (i>=N_NICE) { 00094 i = 0; 00095 mag++; 00096 } 00097 } 00098 while ( ( (axis==1) && myhigh < m_max_value) || 00099 ( (axis==0) && myhigh <= m_max_value) ); 00100 00101 float range = myhigh - mylow; 00102 00103 // we now have decided on a range. Try to move 00104 // m_min_value/m_max_value a little 00105 // to end up on a nice number. 00106 // 00107 // first check if either end is near 0.0 00108 if ( !m_is_log && (m_min_value >= 0.0) && 00109 (( (axis==1) && (range>=m_max_value) ) || 00110 ( (axis==0) && (range>m_max_value) )) ) { 00111 m_min_value = 0.0; 00112 m_max_value = range; 00113 return; 00114 } 00115 00116 if ( (( (axis==1) && (m_max_value<=0.0) ) || 00117 ( (axis==0) && (m_max_value<0.0) )) 00118 && (-range<=m_min_value)) { 00119 m_max_value = 0.0; 00120 m_min_value = -range; 00121 return; 00122 } 00123 00124 // try to round *m_min_value. 00125 // correction 00126 if( m_is_log && (m_min_value<=0.0)) { 00127 m_min_value = 1.0; 00128 } 00129 00130 i = N_NICE-1; 00131 mag = myhigh != 0.0 ? fceil(flog10(ffabs(myhigh))) : 00132 fceil(flog10(ffabs(mylow))); 00133 00134 do { 00135 step = nice[i] * fpow(10.0,mag); 00136 mylow = ffloor(m_min_value/step) * step; 00137 myhigh = mylow + range; 00138 i--; 00139 if (i<0) { 00140 i = N_NICE-1; 00141 mag--; 00142 } 00143 } 00144 while (( m_is_log && (mylow <= 0.0) ) || 00145 ( (axis==1) && (myhigh < m_max_value) ) || 00146 ( (axis==0) && (myhigh <= m_max_value) ) ); 00147 00148 m_min_value = mylow; 00149 m_max_value = myhigh; 00150 } 00151 00152 00153 protected: 00154 float m_min_value; 00155 float m_max_value; 00156 int m_steps; 00157 bool m_is_log; 00158 }; 00159 00160 }} 00161 00162 #endif