.Net 绘图裁剪错误

发布于 2024-07-04 07:11:20 字数 740 浏览 6 评论 0原文

GDI+ DrawLines 函数有一个剪切错误,可以通过运行以下 c# 代码来重现。 运行代码时,会出现两条线路径,它们应该是相同的,因为它们都在剪切区域内。 但当设置剪切区域时,不会绘制其中一条线段。

protected override void OnPaint(PaintEventArgs e)
{
   PointF[] points = new PointF[] { new PointF(73.36f, 196), 
             new PointF(75.44f, 32), 
             new PointF(77.52f, 32), 
             new PointF(79.6f, 196), 
             new PointF(85.84f, 196) };

   Rectangle b = new Rectangle(70, 32, 20, 164);         
   e.Graphics.SetClip(b);
   e.Graphics.DrawLines(Pens.Red, points); // clipped incorrectly
   e.Graphics.TranslateTransform(80, 0);
   e.Graphics.ResetClip();
   e.Graphics.DrawLines(Pens.Red, points);
 }

在图形对象上设置抗锯齿模式可以解决此问题。 但这不是真正的解决方案。

有人知道解决方法吗?

GDI+ DrawLines function has a clipping bug that can be reproduced by running the following c# code. When running the code, two line paths appear, that should be identical, because both of them are inside the clipping region. But when the clipping region is set, one of the line segment is not drawn.

protected override void OnPaint(PaintEventArgs e)
{
   PointF[] points = new PointF[] { new PointF(73.36f, 196), 
             new PointF(75.44f, 32), 
             new PointF(77.52f, 32), 
             new PointF(79.6f, 196), 
             new PointF(85.84f, 196) };

   Rectangle b = new Rectangle(70, 32, 20, 164);         
   e.Graphics.SetClip(b);
   e.Graphics.DrawLines(Pens.Red, points); // clipped incorrectly
   e.Graphics.TranslateTransform(80, 0);
   e.Graphics.ResetClip();
   e.Graphics.DrawLines(Pens.Red, points);
 }

Setting the antials mode on the graphics object resolves this. But that is not a real solution.

Does anybody know of a workaround?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

挽袖吟 2024-07-11 07:11:20

代码似乎有什么问题?

好吧,问题应该是……代码应该做什么但它还没有做什么。

当我运行代码时,我看到 2 个红色“尖峰”,我不是故意的吗?

您似乎在剪裁的矩形区域内绘制了第一个尖峰,通过在 Rectangle 声明后添加以下内容进行验证:

e.Graphics.FillRectangle( new SolidBrush( Color.Black ), b );

然后您执行平移,重置剪辑,因此此时我假设 clientRectangle 被用作适当的剪辑区域,然后尝试重新绘制平移的尖峰。 哪里有bug?!?

What appears to be the matter with the code?

OK, the question should be... what should the code do that it doesn't already.

When I run the code, I see 2 red 'spikes' am I not meant to?

You appear to draw the first spike within the clipped rectangle region verified by adding the the following after the declaration of the Rectangle :

e.Graphics.FillRectangle( new SolidBrush( Color.Black ), b );

Then you perform a translation, reset the clip so at this point I assume the clientRectangle is being used as the appropriate clip region and then attempt to redraw the translated spike. Where's the bug?!?

弱骨蛰伏 2024-07-11 07:11:20

错误在于,两条线段应该绘制相同,但事实并非如此,因为在剪切区域内绘制的尖峰完全在剪切区域内,并且不应以任何方式进行剪切,但事实确实如此。 这是一个非常烦人的问题,但会导致任何大量使用绘图线+剪切的软件看起来不专业,因为多边形中可能会出现间隙。

The bug is that both line segments should be drawn identical but they are not because the spike that is drawn within the clipping region is completely within the clipping region and should not be clipped in any way but it is. This is a very annoying but that results in any software that uses drawlines heavily + clipping to look unprofessional because of gaps that can appear in the polygons.

等风来 2024-07-11 07:11:20

看来这是一个已知的错误...

以下代码似乎可以按照您的要求运行:

protected override void OnPaint(PaintEventArgs e)
    {
        PointF[] points = new PointF[] { new PointF(73.36f, 196), 
         new PointF(75.44f, 32), 
         new PointF(77.52f, 32), 
         new PointF(79.6f, 196), 
         new PointF(85.84f, 196) };

        e.Graphics.SmoothingMode =  System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        Rectangle b = new Rectangle(70, 32, 20, 165);
        e.Graphics.SetClip(b);
        e.Graphics.DrawLines(Pens.Red, points); // clipped incorrectly
        e.Graphics.TranslateTransform(80, 0);
        e.Graphics.ResetClip();           
        e.Graphics.DrawLines(Pens.Red, points);
    }

注意:我已对该行进行了 AntiAlias 处理并将您的剪切区域扩展了 1

看来以下解决方法可能会有所帮助(尽管未经测试) ):

  • 笔的粗度超过一个像素
  • 线条完全水平或垂直
  • 剪切是针对窗口边界而不是剪切矩形

以下是可能/或可能没有帮助的文章列表:

http://www.tech-archive.net/pdf/Archive/Development/microsoft.public.win32.programmer.gdi/2004-08/0350.pdf" tech-archive.net/pdf/Archive/Development/microsoft.public.win32.programmer.gdi/2004-08/0350.pdf
http:// www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.gdi/2004-08/0368.html

或者...

以下也是可能的:

protected override void OnPaint ( PaintEventArgs e )
    {
        PointF[] points = new PointF[] { new PointF(73.36f, 196), 
         new PointF(75.44f, 32), 
         new PointF(77.52f, 32), 
         new PointF(79.6f, 196), 
         new PointF(85.84f, 196) };

        Rectangle b = new Rectangle( 70, 32, 20, 164 );
        Region reg = new Region( b );
        e.Graphics.SetClip( reg, System.Drawing.Drawing2D.CombineMode.Union);
        e.Graphics.DrawLines( Pens.Red, points ); // clipped incorrectly
        e.Graphics.TranslateTransform( 80, 0 );
        e.Graphics.ResetClip();
        e.Graphics.DrawLines( Pens.Red, points );
    }

这有效地使用组合区域进行剪辑/unioned(我认为)与画布/控件的 ClientRectangle 。 由于该区域与矩形不同,因此结果应该是预期的。 添加,可以证明此代码是有效的

e.Graphics.FillRectangle( new SolidBrush( Color.Black ), b );

通过在 setClip() 调用之后 。 这清楚地显示了仅出现在剪切区域中的黑色矩形。

如果无法选择对线路进行抗锯齿处理,这可能是一个有效的解决方法。

希望这可以帮助

It appears that this is a known bug...

The following code appears to function as you requested:

protected override void OnPaint(PaintEventArgs e)
    {
        PointF[] points = new PointF[] { new PointF(73.36f, 196), 
         new PointF(75.44f, 32), 
         new PointF(77.52f, 32), 
         new PointF(79.6f, 196), 
         new PointF(85.84f, 196) };

        e.Graphics.SmoothingMode =  System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        Rectangle b = new Rectangle(70, 32, 20, 165);
        e.Graphics.SetClip(b);
        e.Graphics.DrawLines(Pens.Red, points); // clipped incorrectly
        e.Graphics.TranslateTransform(80, 0);
        e.Graphics.ResetClip();           
        e.Graphics.DrawLines(Pens.Red, points);
    }

Note: I have AntiAlias'ed the line and extended your clipping region by 1

it appears that the following work arounds might help (although not tested):

  • The pen is more than one pixel thick
  • The line is perfectly horizontal or vertical
  • The clipping is against the window boundaries rather than a clip rectangle

The following is a list of articles that might / or then again might not help:

http://www.tech-archive.net/pdf/Archive/Development/microsoft.public.win32.programmer.gdi/2004-08/0350.pdf
http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.gdi/2004-08/0368.html

OR...

the following is also possible:

protected override void OnPaint ( PaintEventArgs e )
    {
        PointF[] points = new PointF[] { new PointF(73.36f, 196), 
         new PointF(75.44f, 32), 
         new PointF(77.52f, 32), 
         new PointF(79.6f, 196), 
         new PointF(85.84f, 196) };

        Rectangle b = new Rectangle( 70, 32, 20, 164 );
        Region reg = new Region( b );
        e.Graphics.SetClip( reg, System.Drawing.Drawing2D.CombineMode.Union);
        e.Graphics.DrawLines( Pens.Red, points ); // clipped incorrectly
        e.Graphics.TranslateTransform( 80, 0 );
        e.Graphics.ResetClip();
        e.Graphics.DrawLines( Pens.Red, points );
    }

This effecivly clips using a region combined/unioned (I think) with the ClientRectangle of the canvas/Control. As the region is difned from the rectangle, the results should be what is expected. This code can be proven to work by adding

e.Graphics.FillRectangle( new SolidBrush( Color.Black ), b );

after the setClip() call. This clearly shows the black rectangle only appearing in the clipped region.

This could be a valid workaround if Anti-Aliasing the line is not an option.

Hope this helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文