I'm writing a bit of code to display a bar (or line) graph in our software. Everything's going fine. The thing that's got me stumped is labeling the Y axis.
The caller can tell me how finely they want the Y scale labeled, but I seem to be stuck on exactly what to label them in an "attractive" kind of way. I can't describe "attractive", and probably neither can you, but we know it when we see it, right?
So if the data points are:
15, 234, 140, 65, 90
And the user asks for 10 labels on the Y axis, a little bit of finagling with paper and pencil comes up with:
0, 25, 50, 75, 100, 125, 150, 175, 200, 225, 250
So there's 10 there (not including 0), the last one extends just beyond the highest value (234 < 250), and it's a "nice" increment of 25 each. If they asked for 8 labels, an increment of 30 would have looked nice:
0, 30, 60, 90, 120, 150, 180, 210, 240
Nine would have been tricky. Maybe just have used either 8 or 10 and call it close enough would be okay. And what to do when some of the points are negative?
I can see Excel tackles this problem nicely.
Does anyone know a general-purpose algorithm (even some brute force is okay) for solving this? I don't have to do it quickly, but it should look nice.
Click the chart. On the Format tab, click Vertical (Value) Axis in the dropdown list and then click Format Pane. In the Format Axis dialog box, click Axis Options, and then do one or more of the following: Important The following scaling options are available only when a value axis is selected.
A long time ago I have written a graph module that covered this nicely. Digging in the grey mass gets the following:
Lets take your example:
15, 234, 140, 65, 90 with 10 ticks
So the range = 0,25,50,...,225,250
You can get the nice tick range with the following steps:
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With