Обновить прямоугольную область на чертеже - PullRequest
0 голосов
/ 15 июля 2010

Я рисую рисунок в области рисования.

Чтобы оптимизировать производительность этого чертежа, я решил перерисовать только внутри действительно необходимой области (области отсечения). Смотрите картинку.

Проблема в том, что я не прибегаю к созданию метода (GetBitmapFromRectangle), который возвращает мне результат пересечения моих путей с отсеченным прямоугольником. Этот метод может быть очень полезен, когда пользователь перемещает (с помощью мыши) пути. В этом случае необходимо перерисовать только прежнюю и текущую перемещенную область пути, а не всю картинку, что в случае сложных картинок может заметно замедлить работу приложения.

Мои тесты показывают, что время вычислений гораздо менее важно, чем время рисования, поэтому мне лучше выполнить больше вычислений, чем больше рисования.

Я хочу нарисовать не все пути, которые пересекают прямоугольник, а на самом деле только пути внутри области отсечения.

альтернативный текст 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;
        }
    }
}

Nota bene

Пример является примером только для демонстрации. В реальном проекте у меня очень сложная графика, а время рисования намного дороже, чем расчетное. Вот почему я хочу не перерисовывать всю картину, а только линии внутри области отсечения!

Ответы [ 3 ]

0 голосов
/ 15 июля 2010

Я бы скопировал существующий код чертежа в метод GetBitmapFromRectangle без каких-либо изменений. Требуемая оптимизация уже сделана за счет уменьшения обновленной области. Существующий код, скопированный в GetBitmapFromRectangle, просто рисует некоторые линии вне границ растрового изображения, это нормально - класс Graphics может справиться с этим. Тестирование каждого примитива рисования на вставку с обтравочным прямоугольником только снижает производительность программы.

0 голосов
/ 20 июля 2010

Вам следует проверить класс GraphicsPath в System.Drawing.Drawing2D.

0 голосов
/ 15 июля 2010

Прежде чем сделать это, я предлагаю протестировать улучшение производительности, выбрав вручную набор и сравнив частоту кадров с отбраковкой и без нее.Возможно, вы обнаружите, что GDI + уже оптимизирует все, что вы рисуете вне области просмотра.

Если вы обнаружите, что это полезно для отбраковки, самый простой подход - найти ограничивающую рамку каждого объекта и проверить на пересечение прямоугольника:

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

В зависимости от типа рисунков, он может иметь высокую частоту ложных попаданий, например, большой полый круг, который обходит область просмотра, но обычно он достаточно хорош для большинства целей.

...