题
有人有计算轴最小值和最大值的不错的算法吗?
当为给定的数据项集创建图表时,我希望能够给出算法:
- 集合中的最大值 (y)
- 集合中的最小值 (y)
- 轴上显示的刻度线数量
- 一个可选值 必须 显示为勾号(例如显示 +ve 和 -ve 值时为零)
该算法应该返回
- 最大轴值
- 最小轴值(尽管可以从最大值、间隔大小和刻度数推断)
- 间隔大小
刻度线应该有规律的间隔并且应该具有“合理”的大小(例如1、3、5,甚至可能是 2.5,但不再是数字)。
可选值的存在会扭曲此值,但如果没有该值,最大的项目应出现在顶部两个刻度线之间,底部两个刻度线之间的最小值应出现。
这是一个与语言无关的问题,但如果有 C#/.NET 库,那就太棒了;)
解决方案
我一直在使用 jQuery 弗洛特 图形库。它是开源的,并且轴/刻度生成非常好。我建议查看它的代码并从中汲取一些想法。
其他提示
好的,这是我为我们的一个应用程序想到的。请注意,它不处理您提到的“可选值”场景,因为我们的可选值始终为 0,但您修改起来应该不难。
数据不断添加到该系列中,因此我们只需通过检查添加的每个数据点来保持 y 值的范围是最新的;这是非常便宜且易于跟踪的。相等的最小值和最大值是特殊情况:间距 0 表示不应绘制任何标记。
这个解决方案与安德鲁上面的建议没有什么不同,只是它以一种稍微笨拙的方式处理指数乘数的一些任意分数。
最后,这个示例是用 C# 编写的。希望能帮助到你。
private float GetYMarkerSpacing()
{
YValueRange range = m_ScrollableCanvas.
TimelineCanvas.DataModel.CurrentYRange;
if ( range.RealMinimum == range.RealMaximum )
{
return 0;
}
float absolute = Math.Max(
Math.Abs( range.RealMinimum ),
Math.Abs( range.RealMaximum ) ),
spacing = 0;
for ( int power = 0; power < 39; ++power )
{
float temp = ( float ) Math.Pow( 10, power );
if ( temp <= absolute )
{
spacing = temp;
}
else if ( temp / 2 <= absolute )
{
spacing = temp / 2;
break;
}
else if ( temp / 2.5 <= absolute )
{
spacing = temp / 2.5F;
break;
}
else if ( temp / 4 <= absolute )
{
spacing = temp / 4;
break;
}
else if ( temp / 5 <= absolute )
{
spacing = temp / 5;
break;
}
else
{
break;
}
}
return spacing;
}
我可以推荐以下内容:
- 设置具有视觉吸引力的最小主线数量。这取决于您所呈现的数据的性质以及您正在绘制的绘图的大小,但 7 是一个相当不错的数字
- 根据 1、2、5、10 等级数选择指数和乘数。这至少会给你最少数量的主要线路。(IE。(最大-最小)/(刻度 x 10^指数) >= 最小刻度标记)
- 找到适合您的范围的指数和乘数的最小整数倍。这将是第一个主要刻度。其余的刻度均由此派生。
这用于允许任意缩放数据的应用程序,并且似乎运行良好。
不隶属于 StackOverflow