// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_data_axis #define tools_data_axis #include "mathf" namespace tools { class data_axis { public: data_axis():m_min_value(0),m_max_value(0),m_is_log(false){} virtual ~data_axis(){} public: data_axis(const data_axis& a_from) :m_min_value(a_from.m_min_value) ,m_max_value(a_from.m_max_value) ,m_is_log(a_from.m_is_log) {} data_axis& operator=(const data_axis& a_from){ m_min_value = a_from.m_min_value; m_max_value = a_from.m_max_value; m_is_log = a_from.m_is_log; return *this; } public: bool set_is_log(bool a_v) {if(m_is_log==a_v) return false;m_is_log = a_v;return true;} bool set_min_value(float a_v) {if(m_min_value==a_v) return false;m_min_value = a_v;return true;} bool set_max_value(float a_v) {if(m_max_value==a_v) return false;m_max_value = a_v;return true;} #ifdef tools_data_axis //g4tools backcomp : bool is_log(bool a_v) {if(m_is_log==a_v) return false;m_is_log = a_v;return true;} bool min_value(float a_v) {if(m_min_value==a_v) return false;m_min_value = a_v;return true;} bool max_value(float a_v) {if(m_max_value==a_v) return false;m_max_value = a_v;return true;} #endif float min_value() const {return m_min_value;} float max_value() const {return m_max_value;} bool is_log() const {return m_is_log;} void adjust() { //from hippodraw. int _axis = 0; float step; float mylow, myhigh; int N_NICE = 4; static const float nice[/*N_NICE*/4] = { 1.0,2.0,2.5,5.0 }; if (m_min_value > m_max_value) { float low = m_min_value; m_min_value = m_max_value; m_max_value = low; } else if (m_min_value == m_max_value) { float value = m_min_value; m_min_value = value - 1; m_max_value = value + 1; return; } //if (m_steps <= 0) { //if letting the if and m_steps as a field, twice this function do not give the same result. _axis = 1; unsigned int m_steps = 10; //} // Round the "bin width" to a nice number. // If this is being done for an axis (ie m_steps was 0 , then // we don't have to go > *m_max_value. // float w = (m_max_value - m_min_value)/((float)m_steps); float mag = ffloor(flog10(w)); int i = 0; do { step = nice[i] * fpow(10.0,mag); mylow = ffloor(m_min_value/step) * step; //myhigh = _axis==1 ? fceil(m_max_value/step) * step : mylow + step * m_steps; myhigh = fceil(m_max_value/step) * step; //quiet Coverity. i++; if (i>=N_NICE) {i = 0;mag++;} } while ( ( (_axis==1) && (myhigh < m_max_value)) || ( (_axis==0) && (myhigh <= m_max_value)) ); float range = myhigh - mylow; // we now have decided on a range. Try to move // m_min_value/m_max_value a little // to end up on a nice number. // // first check if either end is near 0.0 if ( !m_is_log && (m_min_value >= 0.0) && (( (_axis==1) && (range>=m_max_value) ) || ( (_axis==0) && (range>m_max_value) )) ) { m_min_value = 0.0; m_max_value = range; return; } if ( (( (_axis==1) && (m_max_value<=0.0) ) || ( (_axis==0) && (m_max_value<0.0) )) && (-range<=m_min_value)) { m_max_value = 0.0; m_min_value = -range; return; } // try to round *m_min_value. // correction if( m_is_log && (m_min_value<=0.0)) m_min_value = 1.0; i = N_NICE-1; mag = myhigh != 0.0 ? fceil(flog10(ffabs(myhigh))) : fceil(flog10(ffabs(mylow))); do { step = nice[i] * fpow(10.0,mag); mylow = ffloor(m_min_value/step) * step; myhigh = mylow + range; i--; if (i<0) { i = N_NICE-1; mag--; } } while (( m_is_log && (mylow <= 0.0) ) || ( (_axis==1) && (myhigh < m_max_value) ) || ( (_axis==0) && (myhigh <= m_max_value) ) ); m_min_value = mylow; m_max_value = myhigh; } protected: float m_min_value; float m_max_value; //int m_steps; bool m_is_log; }; } #endif