Nice Label Algorithm for Charts with minimum ticks

后端 未结 16 2040
清酒与你
清酒与你 2020-11-29 17:07

I need to calculate the Ticklabels and the Tickrange for charts manually.

I know the \"standard\" algorithm for nice ticks (see http://books.google.de/books?id=fvA7

16条回答
  •  迷失自我
    2020-11-29 17:31

    Here's the C++ version. As a bonus you get a function that returns the minimum number of decimal points to display the tick labels on the axis.

    The header file:

    class NiceScale 
    {   public:
    
        float minPoint;
        float maxPoint;
        float maxTicks;
        float tickSpacing;
        float range;
        float niceMin;
        float niceMax;
    
        public:
        NiceScale()
        {   maxTicks = 10;
        }
    
        /**
        * Instantiates a new instance of the NiceScale class.
        *
        * @param min the minimum data point on the axis
        * @param max the maximum data point on the axis
        */
        NiceScale(float min, float max) 
        {   minPoint = min;
            maxPoint = max;
            calculate();
        }
    
        /**
        * Calculate and update values for tick spacing and nice
        * minimum and maximum data points on the axis.
        */
        void calculate() ;
    
        /**
        * Returns a "nice" number approximately equal to range Rounds
        * the number if round = true Takes the ceiling if round = false.
        *
        * @param range the data range
        * @param round whether to round the result
        * @return a "nice" number to be used for the data range
        */
        float niceNum(float range, boolean round) ;
    
        /**
        * Sets the minimum and maximum data points for the axis.
        *
        * @param minPoint the minimum data point on the axis
        * @param maxPoint the maximum data point on the axis
        */
        void setMinMaxPoints(float minPoint, float maxPoint) ;
    
        /**
        * Sets maximum number of tick marks we're comfortable with
        *
        * @param maxTicks the maximum number of tick marks for the axis
        */
        void setMaxTicks(float maxTicks) ;
        int decimals(void);
    };
    

    And the CPP file:

    /**
    * Calculate and update values for tick spacing and nice
    * minimum and maximum data points on the axis.
    */
    void NiceScale::calculate() 
    {
        range = niceNum(maxPoint - minPoint, false);
        tickSpacing = niceNum(range / (maxTicks - 1), true);
        niceMin = floor(minPoint / tickSpacing) * tickSpacing;
        niceMax = ceil(maxPoint / tickSpacing) * tickSpacing;
    }
    
    /**
    * Returns a "nice" number approximately equal to range 
      Rounds the number if round = true Takes the ceiling if round = false.
    *
    * @param range the data range
    * @param round whether to round the result
    * @return a "nice" number to be used for the data range
    */
    float NiceScale::niceNum(float range, boolean round) 
    {   float exponent; /** exponent of range */
        float fraction; /** fractional part of range */
        float niceFraction; /** nice, rounded fraction */
    
        exponent = floor(log10(range));
        fraction = range / pow(10.f, exponent);
    
        if (round) 
        {   if (fraction < 1.5)
                niceFraction = 1;
            else if (fraction < 3)
                niceFraction = 2;
            else if (fraction < 7)
                niceFraction = 5;
            else
                niceFraction = 10;
        } 
        else 
        {   if (fraction <= 1)
                niceFraction = 1;
            else if (fraction <= 2)
                niceFraction = 2;
            else if (fraction <= 5)
                niceFraction = 5;
            else
                niceFraction = 10;
        }
    
        return niceFraction * pow(10, exponent);
    }
    
    /**
    * Sets the minimum and maximum data points for the axis.
    *
    * @param minPoint the minimum data point on the axis
    * @param maxPoint the maximum data point on the axis
    */
    void NiceScale::setMinMaxPoints(float minPoint, float maxPoint) 
    {
        this->minPoint = minPoint;
        this->maxPoint = maxPoint;
        calculate();
    }
    
    /**
    * Sets maximum number of tick marks we're comfortable with
    *
    * @param maxTicks the maximum number of tick marks for the axis
    */
    void NiceScale::setMaxTicks(float maxTicks) 
    {
        this->maxTicks = maxTicks;
        calculate();
    }
    
    // minimum number of decimals in tick labels
    // use in sprintf statement:
    // sprintf(buf, "%.*f", decimals(), tickValue);
    int NiceScale::decimals(void)
    {
        float logTickX = log10(tickSpacing);
        if(logTickX >= 0)
            return 0;
        return (int)(abs(floor(logTickX)));
    }
    

提交回复
热议问题