.Net绘图剪辑错误

时间:2020-03-05 18:40:34  来源:igfitidea点击:

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

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);
 }

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

有人知道解决方法吗?

解决方案

回答

代码似乎有什么关系?

好的,问题应该是……代码应该做哪些尚未实现的事情。

运行代码时,我看不到2个红色的"尖峰"吗?

我们似乎在裁剪矩形区域内绘制了第一个尖峰,通过在teh Rectangle声明之后添加以下代码来验证:

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

然后执行翻译,重置剪辑,以便在这一点上我假设将clientRectangle用作适当的剪辑区域,然后尝试重新排列翻译的尖峰。错误在哪里?!?

回答

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

回答

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

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

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
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 );
    }

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

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

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

如果不能选择"抗锯齿",则这可能是一个有效的解决方法。

希望这可以帮助