我是“图表轴上最佳缩放算法”的作者。它曾经托管在 trollop.org 上,但我最近移动了域/博客引擎。无论如何,我会在这里发布内容,以便于访问。
我一直在为一项任务开发Android图表应用程序,并且在以精美缩放的格式呈现图表时遇到了一些问题。我花了一些时间试图自己创建这个算法,并且非常接近,但最终我在Andrew S. Glassner的一本名为“Graphics Gems,Volume 1”的书中发现了一个伪代码示例。在“图形标签的漂亮数字”一章中给出了这个问题的精彩描述:
当通过计算机创建图形时,需要用“nice”数字标记x轴和y轴:简单的十进制数。例如,如果数据范围是 105 到 543,我们可能希望绘制从 100 到 600 的范围,并每隔 100 个单位放置刻度线。或者,如果数据范围是 2.04 到 2.16,我们可能会绘制一个从 2.00 到 2.20 的范围,刻度间距为 0.05。人类擅长选择这种“好”的数字,但简单的算法却不擅长。朴素的标签选择算法获取数据范围并将其划分为 n 个相等的区间,但这通常会导致丑陋的刻度标签。我们在这里描述了一种生成漂亮图形标签的简单方法。
主要观察结果是,十进制中“最好”的数字是 1、2 和 5,以及这些数字的所有 10 次方的倍数。我们将仅使用这样的数字作为刻度线间距,并将刻度线放在刻度线间距的倍数处...
我使用本书中的伪代码示例在Java中创建以下类:
public class NiceScale {
private double minPoint;
private double maxPoint;
private double maxTicks = 10;
private double tickSpacing;
private double range;
private double niceMin;
private double niceMax;
public NiceScale(double min, double max) {
this.minPoint = min;
this.maxPoint = max;
calculate();
}
private void calculate() {
this.range = niceNum(maxPoint - minPoint, false);
this.tickSpacing = niceNum(range / (maxTicks - 1), true);
this.niceMin =
Math.floor(minPoint / tickSpacing) * tickSpacing;
this.niceMax =
Math.ceil(maxPoint / tickSpacing) * tickSpacing;
}
private double niceNum(double range, boolean round) {
double exponent;
double fraction;
double niceFraction;
exponent = Math.floor(Math.log10(range));
fraction = range / Math.pow(10, 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 * Math.pow(10, exponent);
}
public void setMinMaxPoints(double minPoint, double maxPoint) {
this.minPoint = minPoint;
this.maxPoint = maxPoint;
calculate();
}
public void setMaxTicks(double maxTicks) {
this.maxTicks = maxTicks;
calculate();
}
}
然后,我们可以像这样使用上面的代码:
NiceScale numScale = new NiceScale(-0.085, 0.173);
System.out.println("Tick Spacing:\t" + numScale.getTickSpacing());
System.out.println("Nice Minimum:\t" + numScale.getNiceMin());
System.out.println("Nice Maximum:\t" + numScale.getNiceMax());
然后,它将输出格式良好的数字,以便在您需要为其创建漂亮比例的任何应用程序中使用。=D
Tick Spacing: 0.05
Nice Minimum: -0.1
Nice Maximum: 0.2