views:

179

answers:

2

i am trying to create slider movement graphics. The code explain better this.

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

    }
}

this code works fine put the problem is that it takes to much cpu and automation is not very smooth. is there some other way to achieve same thing put with much less cpu. Thanks for replays

+3  A: 

You should move all of the graphics code in Button1 to your picturebox's paint event, something like this:

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

    }
}
Pondidum
It's the call to CreateGraphics() thats killing you. Andy's suggestion is the way to go because creating a new Graphics object each time is expensive. You could go one step further and encapsulate all this into a UserControl and override the usercontrol's OnPaint method for a couple less stack calls.Also, you should set the controls style or the forms style to DoubleBuffering for less flicker.
Charlie Brown
You might also consider rewriting your rAr function (at least if you will use more points or smaller intervals later) and improve it f.e. using a ringbuffer, but it might not be worth it - drawCurve perhaps eats much more CPU cycles.
schnaader
+2  A: 

(Premature) Optimisations

In addition to the other answers already posted, you are attempting to draw a spline curve through 100 points.

This is probably a bad idea for two reasons: Firstly, fitting a curve to 100 points isn't a particularly fast thing to do under any circumstances. Secondly, as the points are all 1 pixel apart, there is likely to be no visual benefit to using a curve.

Therefore, there are several more things you could do that might improve the speed:

  • Try using a PolyLine rather than a curve,

  • If you need to use a curve, then you probably don't need to use 100 points across 100 pixels of the drawing - using 10 or 20 positions across that width may give you better results, and will significantly reduce the curve-fitting work that .net has to do.

  • You may be able to also remove some intermediate points that lie on the line/curve, so that you have fewer lines to draw. e.g. if you have points at (10,57) (11, 57) (12,57) then you can drop the middle point and just draw a straight line from (10,57) to (12,57).

Wrong Algorithm?

But wait! Before you optimise the code - is it actually the right solution to the problem?

It sounds as if the content is not meant to "change", but simply scroll sideways. In which case, only the new pixels introduced at one side of the image are actually "changing" with each frame - the rest simply move sideways. In that case, you can scroll (move) the region of the graphic that contains the "old" curve image, and then just draw the extra pixel or two that have "scrolled into view". Scrolling in this manner can be achieved in several different ways (e.g. blitting in the graphics, or if the content of the entire window is scrolling, by using windows Form scrolling commands)

In the same way, if the data is not changing, but simply "scrolling", then rebuilding the array for every frame is unnecessarily expensive. Using a circular buffer you could simply add a new point to the "end" of the array and delete one from the beginning without having to reallocate the array or copy all the intervening points at all.

So it's all about using the right tool for the job.

Jason Williams