有人在计算轴的最小值和最大值时有一个不错的算法吗?
在为一组给定的数据项创建图表时,我希望能够提供以下算法:
-
集合中的最大(y)值
-
集合中的最小(y)值
-
轴上出现的刻度线数
-
一个必须显示为刻度的可选值(例如,显示ve和-ve值时为零)
算法应返回
-
最大轴值
-
最小的轴值(尽管可以从最大的轴值,间隔大小和刻度数推断出)
-
间隔大小
刻度线应有规律的间隔,大小应为"合理"(例如1、3、5,甚至可能是2.5,但不再有其他无花果)。
可选值的存在将使此值倾斜,但是如果没有该值,则最大的项目应出现在顶部两个刻度线之间,而最小值则位于底部两个刻度线之间。
这是一个与语言无关的问题,但是如果周围有C#/。NET库,那将是捣毁;)
好的,这是我为我们的一个应用程序想到的。请注意,它不会处理您提到的"可选值"方案,因为我们的可选值始终为0,但您修改起来并不难。
数据会不断添加到序列中,因此我们只需检查每个数据点的添加情况即可保持y值的范围为最新;这是非常便宜的并且易于跟踪。最小和最大值相等是特殊情况:间距为0表示不应绘制任何标记。
此解决方案与上述安德鲁的建议没有什么不同,不同之处在于它以某种有点模糊的方式处理了指数乘数的任意分数。
最后,此示例在C#中。希望对您有所帮助。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 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等的进阶选择指数和乘数,这样至少会给您最少的主线数。 (即(最大-最小)/(比例x 10 ^指数)> = minimum_tick_marks)
-
找到适合您范围的指数和乘数的最小整数倍。这将是第一个主要的滴答声。其余的价格变动是由此得出的。
它用于允许任意缩放数据的应用程序,似乎工作良好。
我一直在使用jQuery flot图形库。它是开源的,并且很好地完成了轴/刻度线的生成。我建议您看一下它的代码并从那里捏一些想法。