I am developing a chart and graph library and am having trouble developing an algorithm.

**This is not a homework assignment for a student. See my open source project: https://github.com/eddieios/CoreChart

The algorithm is to space the Y axis labels in a given coordinate graphical space. It should space the labels at about 50 pixels apart, but have no less than 5 labels. All data points are assumed to be positive integers. The labels should be multiples of 5 (so as to have nice clean numbers). The last label can be smaller or larger than the maximum possible value, but it should be the closer of the two. The algorithm inputs are 1) the maximum possible value from the chart data, 2) the height of the graphical space. The output is a list of labels and their vertical positions.

For example:

  • Maximum possible chart value = 79
  • Height of graphical space = 200

Output would be:

  • Label: 0, Vertical Position: 0
  • Label: 20, Vertical Position: 50
  • Label: 40, Vertical Position: 100
  • Label: 60, Vertical Position: 150
  • Label: 80, Vertical Position: 200

I have written the following code (Obj-C). But I'm having trouble handling end-cases. For example, if the maxValue = 39, then the labels are set 5 apart. The optimal case here would be to set labels 10 apart. There's something about I'm deciding how many labels there should be that isn't working for all cases.

int maxValue = 39;
float graphHeight = 259.0f;

int numLevels = (int)(graphHeight / 50.0f);

float offset = (int)(maxValue / (float)numLevels);
offset /= 5;
offset = (float)((int)(offset + 0.5));
offset *= 5;

CGFloat stepY = graphHeight * ((float)offset/maxValue);

for (int i = 0; i <= numLevels; i++) {
    NSLog(@"label %f position %f", i*offset, i*stepY);
  • $\begingroup$ Look at gnuplot or the plotting library of asymptote. $\endgroup$ – vonbrand Feb 19 '13 at 12:45
  • $\begingroup$ I think this should be on Stack Overflow. $\endgroup$ – Raphael Feb 20 '13 at 6:59

One possible approach which does not require any hairy arguments is to come up with a "nicety" measure, find a range of offsets, and choose the best one. Usually rounding errors are accounted for by taking a $\pm 1$ (in your case $\pm 5$) modification from the starting point. In your case, you would calculate the nicety measure for both $5$ and $10$, and if your nicety measure is reasonable, choose $10$ over $5$.

| cite | improve this answer | |
  • $\begingroup$ Interesting. What is a nicety measure and how do you come up with one and choose the best one? The code above does the +-5 but is flawed because there is no "choosing the best one" algorithm. $\endgroup$ – Ed Chin Feb 21 '13 at 15:42
  • $\begingroup$ Seems like you would choose between the number of steps in the range. The inputs would be the min and max that fit that graphical space. I guess you would test each number of steps in that range and determine which gives the tightest bounding box. One additional complexity is that you might find the optimal solution is not a bounding box, but one that bounds slightly less than the largest number in chart's range (I.e., one datapoint peaks above the chart slightly) $\endgroup$ – Ed Chin Feb 21 '13 at 15:48
  • $\begingroup$ A nicety measure is a way of quantifying which solutions are better. The idea is that you generate a small set of solutions, and then decide somehow which one is better, without having to explicitly "solve" for the best solution. $\endgroup$ – Yuval Filmus Feb 21 '13 at 23:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.