更新绘图中的矩形区域

发布于 2024-09-10 15:00:25 字数 2496 浏览 3 评论 0原文

我在绘图区域上画一幅画。

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

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

我的测试表明,计算时间远不如绘图时间重要,因此我最好执行更多计算而不是更多绘图。

我不想绘制与矩形相交的整个路径,而是仅绘制剪切区域内部的路径。

替代文本 http://lh5.ggpht.com/ _1TPOP7DzY1E/TD7T0jNU-wI/AAAAAAAADUM/YxaQu4hANpU/s800/Capture1.gif

换句话说,我需要一种方法来使红色区域内的蓝线变成粉红色

这是代码:

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

Nota bene

该示例仅用于演示目的。在实际项目中,我有非常复杂的图形,绘图时间比计算时间要贵得多。这就是为什么我不想重绘所有绘画,而只想重绘剪切区域内的线条!

I paint a drawing on a drawing area.

In order to optimize the performance of that drawing I decided to redraw only inside the really necessary region(clipping region). See the picture.

The problem is that I don't arrive to build a method(GetBitmapFromRectangle) that returns me the result of intersection of my paths with the clipping rectangle.
This method could be very useful when the user moves(with the mouse) paths. In that case there is need to repaint only the former and current moved path area - and not the whole picture, that in case of complex pictures can visibly slow down the application performance.

My tests shows that the calculation time is much less important that the drawing one, so I'd better perform more calculations that more drawing.

I want to draw not the entire paths that intersects the rectangle, but really only the paths inside the clipping region.

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

In other words, I need a method that will make the BLUE lines inside the red area PINK.

Here is the code:

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

Nota bene

The example is a sample for demo purpose only. In the real project I have very complex graphic, and the drawing time is much more expensive that the calculation one. This why I want to not redraw all the painting, but only the lines inside the clipping region!

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

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

发布评论

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

评论(3

情深如许 2024-09-17 15:00:25

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

如果您发现剔除有帮助,最简单的方法是找到每个对象的边界框并测试矩形相交:

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

根据绘图的类型,这可能会有很高的错误命中率,例如大空心围绕视口的圆圈,但它通常足以满足大多数用途。

Before doing this, I suggest testing the performance improvement by manually culling the set and comparing frame rates with and without culling. You may find that GDI+ already optimises anything you draw outside the viewport.

If you find that it is helpful to cull, the simplest approach is to find the bounding box of each object and test for rectangle intersection:

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

Depending on the type of drawings, this may have a high rate of false hits, such as a large hollow circle that goes around the viewport, but it usually does well enough for most purposes.

妄想挽回 2024-09-17 15:00:25

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

I would copy existing drawing code to GetBitmapFromRectangle method without any changes. Required optimization is already done by reducing the updated area. Existing code, copied to GetBitmapFromRectangle, just draws some lines outside of the bitmap bounds, this is OK - Graphics class can handle this. Testing every drawing primitive for intersiction with clipping rectangle only reduces the program performance.

白馒头 2024-09-17 15:00:25

您应该查看 GraphicsPath 类系统.绘图.Drawing2D。

You should check out the GraphicsPath class in System.Drawing.Drawing2D.

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