A long time ago I have written a graph module that covered this nicely. Digging in the grey mass gets the following:
- Determine lower and upper bound of the data. (Beware of the special case where lower bound = upper bound!
- Divide range into the required amount of ticks.
- Round the tick range up into nice amounts.
- Adjust the lower and upper bound accordingly.
Lets take your example:
15, 234, 140, 65, 90 with 10 ticks
- lower bound = 15
- upper bound = 234
- range = 234-15 = 219
- tick range = 21.9. This should be 25.0
- new lower bound = 25 * round(15/25) = 0
- new upper bound = 25 * round(1+235/25) = 250
So the range = 0,25,50,…,225,250
You can get the nice tick range with the following steps:
- divide by 10^x such that the result lies between 0.1 and 1.0 (including 0.1 excluding 1).
- translate accordingly:
- 0.1 -> 0.1
- <= 0.2 -> 0.2
- <= 0.25 -> 0.25
- <= 0.3 -> 0.3
- <= 0.4 -> 0.4
- <= 0.5 -> 0.5
- <= 0.6 -> 0.6
- <= 0.7 -> 0.7
- <= 0.75 -> 0.75
- <= 0.8 -> 0.8
- <= 0.9 -> 0.9
- <= 1.0 -> 1.0
- multiply by 10^x.
In this case, 21.9 is divided by 10^2 to get 0.219. This is <= 0.25 so we now have 0.25. Multiplied by 10^2 this gives 25.
Lets take a look at the same example with 8 ticks:
15, 234, 140, 65, 90 with 8 ticks
- lower bound = 15
- upper bound = 234
- range = 234-15 = 219
- tick range = 27.375
- Divide by 10^2 for 0.27375, translates to 0.3, which gives (multiplied by 10^2) 30.
- new lower bound = 30 * round(15/30) = 0
- new upper bound = 30 * round(1+235/30) = 240
Which give the result you requested ;-).
—— Added by KD ——
Here’s code that achieves this algorithm without using lookup tables, etc…:
double range = ...;
int tickCount = ...;
double unroundedTickSize = range/(tickCount-1);
double x = Math.ceil(Math.log10(unroundedTickSize)-1);
double pow10x = Math.pow(10, x);
double roundedTickRange = Math.ceil(unroundedTickSize / pow10x) * pow10x;
return roundedTickRange;
Generally speaking, the number of ticks includes the bottom tick, so the actual y-axis segments are one less than the number of ticks.