I'm using the Nice Numbers for Graph Labels algorithm (by Andrew S. Glassner), but on some numbers, e.g.: (min: -206.13 max: 729.02), it returns more Ticks than MAX_TICKS
:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define MARGIN " "
#define MARGIN_LEN 10
#define MAX_TICKS 10
#define NVALUES 10
#define WIDTH 70
static double nice(double range, int round)
{
double exponent;
double fraction;
double nicefrac;
exponent = floor(log10(range));
fraction = range / pow(10, exponent);
if (round) {
if (fraction < 1.5)
nicefrac = 1.0;
else
if (fraction < 3.0)
nicefrac = 2.0;
else
if (fraction < 7.0)
nicefrac = 5.0;
else
nicefrac = 10.0;
} else {
if (fraction <= 1.0)
nicefrac = 1.0;
else
if (fraction <= 2.0)
nicefrac = 2.0;
else
if (fraction <= 5.0)
nicefrac = 5.0;
else
nicefrac = 10.0;
}
return nicefrac * pow(10, exponent);
}
static double calc(double range, int ticks)
{
double tick;
range = nice(fabs(range), 0);
tick = nice(range / (ticks - 1), 1);
return tick;
}
int main(void)
{
double value[NVALUES], min, max, tick, sum;
int ticks, width, wtick, wzero, wcurr;
int i, j;
srand(time(NULL));
for (i = 0; i < NVALUES; i++) {
value[i] = (rand() % 100000) / 100.0 - 250.0;
}
min = max = value[0];
for (i = 0; i < NVALUES; i++) {
if (value[i] < min) min = value[i];
if (value[i] > max) max = value[i];
}
printf("MIN = %.2f | MAX = %.2f\n", min, max);
if (min > 0.0) min = 0.0;
if (max < 0.0) max = 0.0;
tick = calc(max - min, MAX_TICKS);
min = floor(min / tick) * tick;
max = ceil(max / tick) * tick;
ticks = (int)((max - min) / tick);
width = (int)(floor(WIDTH / ticks) * ticks);
wtick = (int)(width / ticks);
wzero = (int)ceil(((0.0 - min) / (max - min)) * width);
printf("MIN = %.2f | MAX = %.2f | TICK = %.2f | TICKS = %d\n", min, max, tick, ticks);
printf("\n" MARGIN);
sum = min;
for (i = 0; i <= ticks; i++) {
printf("%-*.*f", wtick, tick == (int)tick ? 0 : 2, sum);
sum += tick;
}
printf("\n" MARGIN);
for (i = 0; i <= ticks; i++) {
printf("%-*s", wtick, "|");
}
printf("\n");
for (i = 0; i < NVALUES; i++) {
printf("%*.2f ", MARGIN_LEN - 1, value[i]);
wcurr = (int)round(((value[i] - min) / (max - min)) * width);
if (value[i] < 0.0) {
for (j = 0; j < wzero; j++)
printf("%c", j < wcurr ? ' ' : '*');
} else {
for (j = 0; j < wcurr; j++)
printf("%c", j < wzero ? ' ' : '*');
}
printf("\n");
}
return 0;
}
In this example MAX_TICKS = 10
but I get 11
ticks:
MIN = -206.13 | MAX = 729.02
MIN = -300.00 | MAX = 800.00 | TICK = 100.00 | TICKS = 11
-300 -200 -100 0 100 200 300 400 500 600 700 800
| | | | | | | | | | | |
729.02 ********************************************
701.07 ******************************************
-84.62 *****
462.44 ****************************
387.91 ***********************
683.73 *****************************************
631.30 **************************************
146.09 *********
663.66 ****************************************
-206.13 ************
The desired output when MAX_TICKS
= 10
(7
ticks):
How to adjust the algorithm in order to get <= MAX_TICKS
?