gpt4 book ai didi

java - 带有最小刻度的图表的好标签算法

转载 作者:IT老高 更新时间:2023-10-28 20:24:22 25 4
gpt4 key购买 nike

我需要手动计算图表的 Ticklabels 和 Tickrange。

我知道漂亮刻度的“标准”算法(见 http://books.google.de/books?id=fvA7zLEFWZgC&pg=PA61&lpg=PA61&redir_esc=y#v=onepage&q&f=false),我也知道 this Java implementation .

问题是,使用这种算法,刻度“太聪明”了。这意味着,算法决定应该显示多少刻度。我的要求是,总是有 5 个刻度,但这些当然应该是“漂亮的”。天真的方法是获取最大值,除以 5 并乘以刻度数。这里的值 - 当然 - 不是最优的,而且刻度非常难看。

有没有人知道问题的解决方案或有正式算法描述的提示?

最佳答案

我是“Algorithm for Optimal Scaling on a Chart Axis”的作者。它曾经托管在 trollop.org 上,但我最近移动了域/博客引擎。无论如何,我会把内容贴在这里方便访问。

我一直在为一项作业开发一个 Android 图表应用程序,但在以良好缩放的格式呈现图表时遇到了一些问题。我花了一些时间尝试自己创建这个算法并且非常接近,但最后我在 Andrew S. Glassner 的一本名为“Graphics Gems, Volume 1”的书中找到了一个伪代码示例。关于“Nice Numbers for Graph Labels”一章对这个问题进行了很好的描述:

When creating a graph by computer, it is desirable to label the x and y axes with "nice" numbers: simple decimal numbers. For example, if the data range is 105 to 543, we'd probably want to plot the range from 100 to 600 and put tick marks every 100 units. Or if the data range is 2.04 to 2.16, we'd probably plot a range from 2.00 to 2.20 with a tick spacing of 0.05. Humans are good at choosing such "nice" numbers, but simplistic algorithms are not. The naïve label-selection algorithm takes the data range and divides it into n equal intervals, but this usually results in ugly tick labels. We here describe a simple method for generating nice graph labels.

The primary observation is that the "nicest" numbers in decimal are 1, 2, and 5, and all power-of-ten multiples of these numbers. We will use only such numbers for the tick spacing, and place tick marks at multiples of the tick spacing...

我使用本书中的伪代码示例在 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;

/**
* Instantiates a new instance of the NiceScale class.
*
* @param min the minimum data point on the axis
* @param max the maximum data point on the axis
*/
public NiceScale(double min, double max) {
this.minPoint = min;
this.maxPoint = max;
calculate();
}

/**
* Calculate and update values for tick spacing and nice
* minimum and maximum data points on the axis.
*/
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;
}

/**
* Returns a "nice" number approximately equal to range Rounds
* the number if round = true Takes the ceiling if round = false.
*
* @param range the data range
* @param round whether to round the result
* @return a "nice" number to be used for the data range
*/
private double niceNum(double range, boolean round) {
double exponent; /** exponent of range */
double fraction; /** fractional part of range */
double niceFraction; /** nice, rounded fraction */

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);
}

/**
* Sets the minimum and maximum data points for the axis.
*
* @param minPoint the minimum data point on the axis
* @param maxPoint the maximum data point on the axis
*/
public void setMinMaxPoints(double minPoint, double maxPoint) {
this.minPoint = minPoint;
this.maxPoint = maxPoint;
calculate();
}

/**
* Sets maximum number of tick marks we're comfortable with
*
* @param maxTicks the maximum number of tick marks for the axis
*/
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

关于java - 带有最小刻度的图表的好标签算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8506881/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com