Графика Производительность проблемы с графикой - PullRequest
1 голос
/ 19 июля 2009

Я пытаюсь создать графику движения слайдера. Код объясняет лучше это.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace temp
{

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private System.Drawing.Graphics g;
        private System.Drawing.Pen pen1 = new System.Drawing.Pen(Color.Black, 1F);

        //timer for animation
        private void Form1_Load(object sender, EventArgs e)
        {
            Timer a = new Timer();
            a.Interval = 60;
            a.Tick += new EventHandler(a_Tick);
            a.Start();
        }

        void a_Tick(object sender, EventArgs e)
        {
            button1_Click(this, null);

        }

        //draws randomly generated point array.
        int cnt = 0;
        private void button1_Click(object sender, EventArgs e)
        {
            rAr();
            g = pictureBox1.CreateGraphics();

            g.Clear(Color.Violet);
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.DrawCurve(pen1, points2);
            cnt++;
        }

        Random r = new Random();
        Point[] p = new Point[100];
        Point[] points2 = new Point[100];
        int c = 4;
        //fills new random point array
        private void rAr()
        {
            points2.CopyTo(p, 0);
            int cc = 1;
            for (int i = points2.Length - 1; i > 0; i--)
            {
                points2[i - 1] = new Point(100 - cc, p[i].Y);
                cc++;
            }
            points2[99] = new Point(100, r.Next(1, 50));
        }

    }
}

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

Ответы [ 2 ]

7 голосов
/ 19 июля 2009

(преждевременные) оптимизации

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

Это, вероятно, плохая идея по двум причинам: во-первых, подгонка кривой к 100 точкам не особенно быстрая вещь при любых обстоятельствах. Во-вторых, поскольку все точки расположены на расстоянии 1 пиксель, использование кривой, вероятно, не принесет никакой пользы.

Следовательно, вы можете сделать еще несколько вещей, которые могут улучшить скорость:

  • Попробуйте использовать PolyLine, а не кривую,

  • Если вам нужно использовать кривую, то вам, вероятно, не нужно использовать 100 точек на 100 пикселях чертежа - использование 10 или 20 позиций по этой ширине может дать вам лучшие результаты и значительно уменьшит работа по подгонке кривой, которую должен выполнить .net.

  • Вы также можете удалить некоторые промежуточные точки, которые лежат на линии / кривой, чтобы у вас было меньше линий для рисования. например если у вас есть точки в (10,57) (11, 57) (12,57), то вы можете опустить среднюю точку и просто провести прямую линию от (10,57) до (12,57).

Неправильный алгоритм?

Но подождите! Прежде чем оптимизировать код - действительно ли это правильное решение проблемы?

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

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

Так что все дело в использовании правильного инструмента для работы.

3 голосов
/ 19 июля 2009

Вы должны переместить весь графический код в Button1 в событие рисования вашего Picturebox, примерно так:

   private void button1_Click(object sender, EventArgs e)
    {
        rAr();
        pictureBox1.Invalidate();
        cnt++;
    }

private void picturebox1_Paint(object sender PaintEventArgs e)
{
    using graphics g = e.Graphics()
    {
          g.Clear(Color.Violet);
          g.PixelOffsetMode = PixelOffsetMode.HighQuality;
          g.SmoothingMode = SmoothingMode.HighQuality;
          g.DrawCurve(pen1, points2);

    }
}
...