2010-07-15 139 views
0

我在绘图区域上绘制图形。更新图形中的矩形区域

为了优化绘图的性能,我决定只在真正必要的区域(剪切区域)内重绘。看到图片。

问题是我没有建立一个方法(GetBitmapFromRectangle),它返回我的路径与剪切矩形的交集结果。 当用户移动(使用鼠标)路径时,此方法可能非常有用。在这种情况下,只需要重新绘制前一个和当前移动的路径区域 - 而不是整个图像,以便在复杂图像的情况下可以明显减慢应用程序的性能。

我的测试表明,计算时间不像绘图那么重要,所以我最好多进行一次绘图。

我想绘制不是与矩形相交的整个路径,但实际上只有剪切区域内的的路径

alt text http://lh5.ggpht.com/_1TPOP7DzY1E/TD7T0jNU-wI/AAAAAAAADUM/YxaQu4hANpU/s800/Capture1.gif

换句话说,我需要一个方法,将使红色区域PINK里面的蓝色线条。

下面是代码:

using System.Drawing; 
using System.Windows.Forms; 

namespace WindowsApplication38 
{ 
    public partial class Form1 : Form 
    { 
     Point center; 
     int radius, penWidth; 

     public Form1() 
     { 
      InitializeComponent(); 
      center = new Point(50, 50); 
      radius = 100; 
      penWidth = 5; 
      this.ResizeRedraw = true; 
     } 

     protected override void OnPaint(PaintEventArgs e) 
     { 
      base.OnPaint(e); 

      e.Graphics.Clear(this.BackColor); 

      e.Graphics.DrawImage(
       GetBitmapFromRectangle(e.ClipRectangle), 
       e.ClipRectangle.Location); 

      // 
      // INITIAL DRAWING METHOD 
      //    
      Pen p = new Pen(Color.Blue, penWidth); 
      // draw O 
      e.Graphics.DrawEllipse(p, center.X - radius, center.Y - radius, radius * 2, radius * 2); 
      // draw X 
      Point[] line1 = new Point[] { new Point(0, 0), new Point(this.Width, this.Height) }; 
      Point[] line2 = new Point[] { new Point(this.Width, 0), new Point(0, this.Height) }; 
      e.Graphics.DrawLines(p, line1); 
      e.Graphics.DrawLines(p, line2); 
      p.Dispose(); 
     } 

     private Bitmap GetBitmapFromRectangle(Rectangle rect) 
     { 
      Bitmap bmp = new Bitmap(rect.Width, rect.Height); 
      Graphics g = Graphics.FromImage(bmp); 
      if (rect != this.DisplayRectangle) 
       g.Clear(Color.Red); 
      else 
       g.Clear(this.BackColor); 

      // Draw ONLY! the intersetion between drawing and rectangle... 
      // How to ??? 

      return bmp; 
     } 
    } 
} 

诺塔好处

的示例仅是为了演示的目的样品。在真实的项目中,我有非常复杂的图形,并且绘图时间比计算时间要昂贵得多。这就是为什么我不想重绘所有的绘画,但只有裁剪区域内的线条!

回答

0

在做这件事之前,我建议通过手动剔除集合并比较有或无剔除帧速率来测试性能改进。您可能会发现GDI +已经优化了您在视口外绘制的任何内容。

如果你发现这是有帮助的扑杀,最简单的方法是找到每个对象为矩形相交的边框和测试:

bool intersect = left1 < right2 && left2 < right1 && top1 < bottom2 && top2 < bottom1. 

根据图纸的种类,这可能有一个虚假命中率高,比如围绕视口的大型空心圆圈,但通常对大多数目的来说足够好。

+0

也许,但是我会使用GetBitmapFromRectangle(...)来更新图形,例如在图形中使用鼠标移动图形元素。 – serhio 2010-07-15 09:58:48

+0

你的“代码”左边没有任何意义。看看提供的例子,你如何应用你的测试? – serhio 2010-07-15 10:14:48

+1

你知道“找到边框”的含义吗?在椭圆的情况下,'left1 = center。X - 半径; right1 = center.X + radius; top1 = center.Y - 半径; bottom1 = center.Y + radius;'和'(left/right/top/bottom)2'对应于剪辑区域。在投票回答你不明白的人之前,你可能想给他们一个解决你的问题的机会。 – 2010-07-15 10:23:57

0

我会将现有的绘图代码复制到GetBitmapFromRectangle方法中,而不做任何更改。所需的优化已通过减少更新区域完成。复制到GetBitmapFromRectangle的现有代码只是在位图边界之外绘制一些行,这是可以的 - Graphics类可以处理这个问题。测试每个绘图基元的裁剪矩形只会降低程序的性能。

+0

不同意。图形平行(或更差的弯曲)线所有面板宽度和一个苗条的垂直剪辑矩形。 而且,经过我的测试,绘图时间需要更多的计算。 – serhio 2010-07-15 09:49:47

+0

如果您的实际绘图更加复杂,这会使您感到惊讶。在这种情况下,您需要一些特定于算法的数学运算 - 例如Marcelo Cantos所示的简单测试。但是如果不查看实际的绘图代码,这是不可能的。 – 2010-07-15 10:00:49

+0

我给出的代码接近我使用的代码。我只需要获得上面代码中的交集路径。 – serhio 2010-07-15 10:02:35

-1

您应该查看System.Drawing.Drawing2D中的GraphicsPath类。

+0

GraphicsPath真的是GDI +做你需要的唯一方法。 – pmcilreavy 2010-07-21 07:23:51