【问题标题】:What are the hard bounds for drawing coordinates in GDI+?在 GDI+ 中绘制坐标的硬边界是什么?
【发布时间】:2011-03-28 23:08:52
【问题描述】:

我正在渲染一条插值曲线:

e.Graphics.DrawLines(new Pen(Color.Red), _interpolationPoints.ToArray());

有时会引发 OverflowException。

_interpolationPoints 数组的检查显示了一些非常大的科学计数法值,例如{X = 0.0 Y = -1.985174E+10}

我怀疑 Y = -1.985174E+10 是 GDI+ 无法处理的值。很好,但是我可以绘制的最大/最小 X 和 Y 值是多少,从而限制数据(并警告用户)而不是在绘制期间捕获溢出异常?是否记录了这些限制?

例如,我想做这样的事情:

if (yVal < float.MinValue || yval > float.MaxValue) 
      throw new OverflowException("Interpolation value too large to be rendered.");

在 _interpolationPoints 数组的填充过程中并停止该过程。 (float mix/max 顺便说一句不起作用。我仍然得到异常。)

【问题讨论】:

  • 非常感谢。有趣的是,关于这些限制的信息很少。当然,我不是第一个编写代码以在 GDI+ 中绘制插值并且需要捕捉边缘值的人。
  • @Vulcan:请务必查看下面的答案。上面的问题仅包含无法完成的想法。例如。 float.MaxValue 不是对限制的有效测试!
  • 我确实也查看了答案和文章。

标签: c# .net gdi+ drawing limit


【解决方案1】:

好的,我需要知道,所以我逐步测试并提出了这些限制:

positive:    1,073,741,951
negative:   -1,073,741,760

我使用的代码如下所示:

int lastGoodVal = 0;
for (int i = -1073000000; i > -1073832999; i -= 1)
{
    g.DrawLine(Pens.Blue, new Point(0,0), new Point(0, i));
    lastGoodVal = i;
}

上面的循环是最终测试,步长为 1,通过早期测试建立的一系列负值。如您所见,lastGoodVal 保存最后一次成功的绘制迭代,因此我将用作常量的真正限制。

我试图将这些数字与 .NET 原语中的值相关联,但不能。每个限制都接近 2^30 的值,但并不完全正确。任何其他见解将不胜感激。

我也只测试了 DrawLine 方法。 API 中的其他函数可能存在不同的限制,但我还没有机会探索。

此外,在完成此实验并在谷歌上搜索值 1073741951 后,我遇到了与我的发现相关的this article。我还在某种 Mono 代码存档中 found this 提到了与浮动限制的接近但不完全相关的相关性。

【讨论】:

    【解决方案2】:

    仅供参考 - 我通过一个简单的 2D 绘图实现遇到了这种情况。当我在图像上放大得太远时,相应的像素位置远离显示区域并导致 Graphics.DrawLine 抛出溢出异常。所以很自然地,我添加了一个检查以确保值在上面 Paul 定义的范围内。有趣的是,虽然当 Y 值变得太大(但小于建议的正值 1,073,741,951)时,结果线从按预期绘制(到大于我最后一个合理点的 Y 像素位置)到被绘制(到顶部窗口)。

    经过进一步调查,我发现 8,388,607 (0x7FFFFF) 的值可以正确绘制线,而 8,388,608 (0x800000) 的值会反转线。

    看起来这里使用了带符号的 24 位值。

    【讨论】:

    • +1 有趣的观察,但我不太确定这是一个签名/未签名的问题。 0x7FFFFF0x800000 的值确实代表了 24 位数据,但没有“接近”溢出或有符号/无符号问题发挥作用的边界。这些 HEX 值看起来更像:0xFFFFFF0xFFFFFE 等。我也不熟悉任何具有 24 位架构的系统......我猜这是内部设置的半任意边界,也许是出于性能原因的调整。
    【解决方案3】:

    我没有听说过 DrawLines() 或任何其他 GDI 绘图函数的具体限制。为什么不使用 e.ClipRectangle 作为约束?

    无论如何都不需要在可见区域之外绘制点。只要确保只有两个点都在外面的线被丢弃。

    【讨论】:

    • +1 我认为您的最后一条评论很关键:Just make sure that only lines are discarded that have both points outside. 我记得当我为多项式和线性回归进行曲线拟合和显示时遇到了这个问题。连接这些拟合端点的线通常会超出我在答案中列出的范围,并且除了异常处理之外,没有内置的方法来处理错误。异常处理导致了可怕的性能问题,正如您所提到的,我不得不使用自定义代码检查并丢弃那些有问题的行。
    猜你喜欢
    • 2010-12-19
    • 2021-05-26
    • 1970-01-01
    • 2019-08-13
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 2014-03-24
    • 2014-05-15
    相关资源
    最近更新 更多