MS Chart中的自动间隔精度

15

我目前正在使用.NET中的图表功能,使用 System.Windows.Forms.DataVisualization.Charting.Chart。到目前为止,它看起来非常强大,效果很好。但是,在自动计算间隔方面存在一个巨大问题。我使用了大量的 double 值,在诸如ZedGraph等库中,它可以完美地处理这些值。它可以选择最小/最大/间隔,但在MS Chart中,它可能会选择类似小数精度的206.3334539832作为最小值,并且同样精确的小数位数作为间隔。显然,这看起来相当丑陋。

因此,我尝试简单地将轴格式设置为 {0.00},当图表加载时,它工作得很好。但是,当您放大视图时,需要更高的精度,比如不是2位小数而是4位小数。似乎我要么一直使用9位小数,要么使用一个固定的数字,但这可能会在某些情况下破坏大量的精度。我希望能够根据当前应用的缩放级别自动选择精度。像ZedGraph和Dundas(我相信MS甚至在使用这个!)这样的库通常会选择随着缩放变化而改变的良好值。

有没有办法在缩放框架发生变化时改变间隔的精度?可能是我设置了一些简单的属性,但是很难确定这个东西有数百万的属性(特别是当有大约14个位置表示间隔的概念时)。


2
据我所知,图表控件是基于 Dundas 控件开发的。 微软在一段时间前收购了 Dundas 的数据可视化组件。更多信息请参见此处 - CGK
你的编辑中没有图片吗? - noelicus
@noelicus 抱歉,我现在有了新工作,那些图片在某个时候被删除了(显然这是在 SO 允许上传图片之前)。我暂时已经将编辑内容删除。如果我能找到那些图片的副本,我会更新这个问题的。 - drharris
7个回答

6

当我进行缩放时,我遇到了完全相同的问题。我添加了代码来格式化轴标签并从Paint处理程序中调用它。Axis View对象有一个IsZoomed属性,并且有函数可以获取当前轴界限(GetViewMinimum/Maximum)。除非Max-Min =范围小于1,否则我将Axis LabelStyle.Format设置为“N”。然后,我根据轴范围计算出“F#”的格式并将其设置为格式。

# = Convert.ToInt32(Math.Abs(Math.Log10(range) - .5)) + 1;

非常感谢您指出GetViewMinimum/Maximum!这可能是我正在寻找的函数。我很快就会尝试,如果它适用于我的情况,我将恢复之前的赏金并将其给予您。此外,感谢您提供获取小数位数的代码 - 在WolframAlpha中进行了一些测试后,它似乎生成了完美的小数位数。 - drharris
我忘记回报了,但我终于有时间来实现它了,而且它完美地运行。我仍然认为控件本身应该处理这种类型的逻辑(如果开源项目像ZedGraph可以做到,那么MS/Dundas肯定也可以)。我已经重新启动了这个问题的原始赏金,因为这可以避免让不满意的客户给我带来很多麻烦!只要SO允许我,我就会立即颁发奖励。 - drharris

1

为什么不修改数字格式字符串。

创建格式字符串

string formatString = "{0.00";

识别缩放级别,例如zoomLevel = 2;

formatString = formatString.PadRight(5+zoomLevel, '0');
formatString += "}";

现在在轴图例上使用这种格式。使用字符串构建器或更好的方式修改格式字符串。


问题在于“缩放级别”含义不大。比例尺并不总是相同的,有时X轴范围可能为100-120,而其他时候则为0-4000。此外,用户可以自行选择缩放窗口,意味着没有明确的方法来确定需要格式化的小数位数。理论上是一个好答案,但它与这里的对象模型不匹配。 - drharris

1

在尝试使用图表控件后,我无法找到一个简单的解决方案来解决您的问题。但是以下内容可能会有所帮助:

您是否考虑过自己设置轴的最大和最小值?如果将实际的最大和最小值舍入到最接近的合理“圆”数(5、10、0.5、0.01),这应该会使计算出的间隔更加友好。

我知道这不是一个理想的解决方案,但通过仔细选择最大和/或最小值,您可以确保间隔是“更好”的数字。如果您的轴范围可以被2、5和10整除,那么它应该会产生相当好的间隔。


我尝试过自己设置最小值和最大值,但这些图表用于分析,一旦你缩放到自定义区域,它就会失去漂亮的整数并回到这种不希望的行为。此外,将最小值设置为-10有时会导致-10.00000023或类似的结果。所以,你已经完成了一半;它确实修复了初始显示,但随着所有缩放的发生,这并不是解决问题的完整方案。不过很高兴听到我不是唯一一个遇到这个问题的人! - drharris

0
为了以最小的代价提供结果,您可以使用指数科学格式。

如果这是一个仅由科学家使用的内部应用程序,那将是很棒的!然而,我们的用户群从大学教授到农民都有,教一些人阅读指数格式几乎是不可能的。此外,使用科学数字并不能解决太多小数位数的问题(如2.6666684583e-4)。 - drharris
只需使用 string.Format("{0:e2}", 123.456789)。还可以尝试应用自定义转换器格式。 - gabba

0
你可以附加到自定义事件。 从那里,你可以修改x轴上的标签:
var xAxisLabels = chart1.ChartAreas[0].AxisX.CustomLabels;
...
xAxisLabels[0].Text = ...

设置最小值和最大值:

 chart1.ChartAreas[0].AxisX.Maximum = ...;

等等。


0

您可以根据数据集动态更新最大值和最小值。每次用户缩放时,您可以对每个点进行FOREACH操作并获取统计信息,然后根据此设置最大值和最小值。


代码?如何检测用户缩放?如何仅在缩放活动期间检索窗口中的点? - drharris

0

设置轴的IntervalOffset有助于解决问题,以下是一个示例:

Private Sub chMap_AxisViewChanged(sender As System.Object, e As System.Windows.Forms.DataVisualization.Charting.ViewEventArgs) Handles chMap.AxisViewChanged
  'the grid ticks are rounded values
  e.Axis.IntervalOffset = -e.Axis.ScaleView.ViewMinimum
End Sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接