Page 1 of 1

colorgrid takes long time to draw and resize

Posted: Mon May 18, 2015 3:00 pm
by 15669187
Hi,

I am using a colorgrid to generate an image where the number of points can be large (i.e. 1000x1000 or 2000x2000). The color grid takes a long time to generate the plot and also every time I resize the plot it also takes a long time. I recall a version back in 2007 that did this faster. See attached example code.

Code: Select all

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Steema.TeeChart;
using Steema.TeeChart.Styles;
using Steema.TeeChart.Tools;

namespace ColorGridExample
{

	public partial class Form1 : Form
	{
		TChart _chart;
		private ColorGrid _colorGrid;
		private LegendPalette _legendPalette;
		private Color[] _rainbowLowBlackPalette;

		private double _colorBarMax;
		private double _colorBarMin;
		private double _colorBarStep;

		private double[] _xData;
		private double[] _yData;
		private double[] _zData;

		public Form1()
		{
			InitializeComponent();

			_colorBarMax = 0.0;
			_colorBarMin = -50.0;
			_colorBarStep = 5.0;

			SetupColorGrid();
			GenerateData();

			_colorGrid.Add(_xData, _zData, _yData);

			_colorGrid.IrregularGrid = true;
			_legendPalette.Series = _colorGrid;
			_legendPalette.Gradient.Visible = false;
		}

		public void SetupColorGrid()
		{
			this.SuspendLayout();
			this._chart = new Steema.TeeChart.TChart();
			this._chart.Aspect.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
			this._chart.Aspect.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault;
			this._chart.Aspect.View3D = false;
			this._chart.Dock = System.Windows.Forms.DockStyle.Fill;
			this._chart.Location = new System.Drawing.Point(0, 0);
			this._chart.Name = "tChart1";
			this._chart.Size = new System.Drawing.Size(700, 500);
			this._chart.TabIndex = 0;
			this.Controls.Add(this._chart);


			_chart.Header.Visible = false;
			_chart.Legend.Visible = false;
			_chart.Panel.MarginUnits = Steema.TeeChart.PanelMarginUnits.Pixels;
			_chart.Panel.MarginRight = 80;

			_chart.Axes.Bottom.Automatic = false;
			_chart.Axes.Bottom.AutomaticMaximum = false;
			_chart.Axes.Bottom.AutomaticMinimum = false;
			_chart.Axes.Bottom.Increment = 0.2;
			_chart.Axes.Bottom.Maximum = 1.0;
			_chart.Axes.Bottom.Minimum = -1.0;

			_chart.Axes.Left.Automatic = false;
			_chart.Axes.Left.AutomaticMaximum = false;
			_chart.Axes.Left.AutomaticMinimum = false;
			_chart.Axes.Left.Increment = 0.2;
			_chart.Axes.Left.Maximum = 1.0;
			_chart.Axes.Left.Minimum = -1.0;

			this._colorGrid = new ColorGrid();
			this._colorGrid.Pen.Visible = false;
			this._colorGrid.Title = "colorGrid1";
			this._colorGrid.UseColorRange = false;
			this._colorGrid.UsePalette = true;
			this._colorGrid.XStep = 1;

			this._chart.Series.Add(this._colorGrid);

			LoadColorPalette();
			_legendPalette = new LegendPalette(_chart.Chart);

			_legendPalette.Axis = LegendPaletteAxis.laOther;
			_legendPalette.Width = 60;
			_legendPalette.Pen.Visible = false;
			_legendPalette.Series = _colorGrid;

			this.ResumeLayout(false);

			_chart.SizeChanged += new System.EventHandler(this.Chart_SizeChanged);


		}

		private void Chart_SizeChanged(object sender, EventArgs e)
		{
			_chart.AutoRepaint = false;
			_legendPalette.Left = _chart.Width - _legendPalette.Width - 10;
			_legendPalette.Top = (_chart.Height - _legendPalette.Height) / 2;
			_chart.AutoRepaint = true;
			_chart.Refresh();
		}

		private void LoadColorPalette()
		{
			double minValue = _colorBarMin;
			double maxValue = _colorBarMax;
			double delta = _colorBarMax - _colorBarMin;

			_colorGrid.ClearPalette();
			_rainbowLowBlackPalette = new Color[256];
			int redIndex;
			int greenIndex;
			int blueIndex;
			for (int i = 0; i < 256; i++)
			{
				if (i == 0)
				{
					redIndex = 0;
					greenIndex = 0;
					blueIndex = 0;
				}
				else if (i > 0 && i <= 32)
				{
					redIndex = -255 / 32 * i + 255;
					greenIndex = 0;
					blueIndex = 255;
				}
				else if (i > 32 && i <= 85)
				{
					redIndex = 0;
					greenIndex = (255 / (85 - 32)) * (i - 32);
					blueIndex = 255;

				}
				else if (i > 85 && i <= 143)
				{
					redIndex = 0;
					greenIndex = 255;
					blueIndex = (-255 / (143 - 86)) * (i - 143);
				}
				else if (i > 143 && i <= 199)
				{
					redIndex = (255 / (199 - 143)) * (i - 143);
					greenIndex = 255;
					blueIndex = 0;
				}
				else
				{
					redIndex = 255;
					greenIndex = (-255 / (255 - 199)) * (i - 255);
					blueIndex = 0;
				}
				_rainbowLowBlackPalette[i] = Color.FromArgb(redIndex, greenIndex, blueIndex);

				_colorGrid.AddPalette(((delta / 255.0) * (double)i + minValue), _rainbowLowBlackPalette[i]);
			}
		}

		private void GenerateData()
		{
			var Nx = 50;
			var Ny = 25;
			var Nu = 1001;
			var Nv = 1001;

			_xData = new double[Nu*Nv];
			_yData = new double[Nu*Nv];
			_zData = new double[Nu*Nv];

			var du = 2.0 / (Nu - 1);
			var dv = 2.0 / (Nv - 1);

			int k = 0;
			for (int i=0; i<Nu; i++)
			{
				var v = -1.0 + dv * i;
				for (int j=0; j<Nv; j++)
				{
					var u = -1.0 + du * j;
					var argx = 0.5*Nx*u;
					var argy = 0.5*Ny*v;

					_xData[k] = u;
					_yData[k] = v;
					_zData[k] = 20.0 * Math.Log10(Math.Abs(sinc(argx) * sinc(argy)));
					k++;
				}
			}
		}

		private double sinc(double x)
		{
			if (Math.Abs(x) < 1.0e-7)
			{
				return 1.0;
			}
			else
			{
				return (Math.Sin(Math.PI * x) / (Math.PI * x));
			}
		}

	}
}


namespace ColorGridExample
{
	partial class Form1
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.IContainer components = null;

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing && (components != null))
			{
				components.Dispose();
			}
			base.Dispose(disposing);
		}

		#region Windows Form Designer generated code

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			// 
			// Form1
			// 
			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
			this.ClientSize = new System.Drawing.Size(600, 500);
			
			this.Name = "Form1";
			this.Text = "Form1";
			this.ResumeLayout(false);
		}

		#endregion

	}
}


Re: colorgrid takes long time to draw and resize

Posted: Tue May 19, 2015 10:14 am
by Christopher
Hello,

This is what your application looks like using the present source code and VS2013's profiler:
profile.PNG
profile.PNG (131.98 KiB) Viewed 16689 times
As you can see, the assembly taking up the time here is System.Drawing.dll. I ran a test using the Stopwatch class and found that the application on this relatively old machine runs in 12040 milliseconds, whereas using a version of TeeChart.dll from 2009 the application run in 14420 millseconds. While I agree that over 12 seconds for the chart to render is unacceptable, I'm not entirely sure that older versions of TeeChart would have run significantly quicker. What is more, given that it is the drawing of Lines and Polygons which is taking the time, I'm not sure how to better this performance by doing something other than feeding the chart less lines and polygons to draw. I'll have to have a further think about this.

Re: colorgrid takes long time to draw and resize

Posted: Wed May 20, 2015 2:50 am
by 15669187
I do not get the flat line like you. Also, try resizing the window. I get that the resize takes almost twice as long.
In addition (although it has been a while since I looked at this) I had found that in the past using
this._chart.Aspect.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
ran faster. However, it seems that now it is having minimal improvement.

John

Re: colorgrid takes long time to draw and resize

Posted: Wed May 20, 2015 9:40 am
by Christopher
Hello,

I'm using the latest TeeChart.dll, version 4.1.2015.05140.

Using a more modern machine, I get the following results:
TeeChart.dll 4.1.2015.05140 (14/05/2015): draw, 6658ms. resize, 6358ms
TeeChart.dll 3.5.3700.30574 (17/02/2009): draw, 8188ms. resize, 6770ms

In both versions of TeeChart the most called TeeChart function is the same:

TeeChart.dll 4.1.2015.05140:
v2015.PNG
v2015.PNG (15.73 KiB) Viewed 16670 times
TeeChart.dll 3.5.3700.30574:
v3.PNG
v3.PNG (14.3 KiB) Viewed 16655 times
what is more, the Steema.TeeChart.Styles.Custom3DGrid.SearchValue function is identical in both versions. I have added a further improvement to ColorGrid performance to our database with id=1215 so that further attention can be given to this area.

Re: colorgrid takes long time to draw and resize

Posted: Wed May 20, 2015 1:18 pm
by 15669187
When I drag the corner of the window to resize it, the redraw takes almost twice as long than the initial rendering.
Do you notice this on your computer?

Re: colorgrid takes long time to draw and resize

Posted: Wed May 20, 2015 1:41 pm
by Christopher
johnf wrote:When I drag the corner of the window to resize it, the redraw takes almost twice as long than the initial rendering.
Do you notice this on your computer?
The code I used to produce the figures I mentioned in my last post is in the ticket id=1215. Using that code, are your results different in magnitude?

Re: colorgrid takes long time to draw and resize

Posted: Thu May 21, 2015 2:51 am
by 15669187
Hi Christopher,

Thanks for the reply. How are you getting the times to draw and resize?
Where in the profiling report are you looking?
Picture1.png
Picture1.png (303.21 KiB) Viewed 16658 times
John

Re: colorgrid takes long time to draw and resize

Posted: Thu May 21, 2015 10:49 am
by Christopher
Hi John,

No, I couldn't find a global timer for the TeeChart painting operation either within the profiler, so in the code I used to reproduce the issue, present in the ticket id=1215 I mentioned, I had to use .NET framework Stopwatch.

Re: colorgrid takes long time to draw and resize

Posted: Fri May 22, 2015 1:31 pm
by 15669187
Hi Christopher,

Where did you place the calls to the stopwatch?

John

Re: colorgrid takes long time to draw and resize

Posted: Fri May 22, 2015 2:44 pm
by Christopher
Hello John,

Here's the code I used:

Code: Select all

                private Stopwatch watch = new Stopwatch();
		private ColorGrid _colorGrid;
		private LegendPalette _legendPalette;
		private Color[] _rainbowLowBlackPalette;

		private double _colorBarMax;
		private double _colorBarMin;
		private double _colorBarStep;

		private double[] _xData;
		private double[] _yData;
		private double[] _zData;


		private void InitializeChart()
		{
			_colorBarMax = 0.0;
			_colorBarMin = -50.0;
			_colorBarStep = 5.0;

			watch.Reset();
			watch.Start();

			tChart1.AfterDraw += TChart1_AfterDraw;

			SetupColorGrid();
			GenerateData();

			_colorGrid.Add(_xData, _zData, _yData);

      _colorGrid.IrregularGrid = true;
			_legendPalette.Series = _colorGrid;
			_legendPalette.Gradient.Visible = false;
		}

		private void TChart1_AfterDraw(object sender, Graphics3D g)
		{
			watch.Stop();
			label1.Text = watch.ElapsedMilliseconds.ToString();
		}

		public void SetupColorGrid()
		{
			this.SuspendLayout();
			this.tChart1.Aspect.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
			this.tChart1.Aspect.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault;
			this.tChart1.Aspect.View3D = false;


			tChart1.Header.Visible = false;
			tChart1.Legend.Visible = false;
			tChart1.Panel.MarginUnits = Steema.TeeChart.PanelMarginUnits.Pixels;
			tChart1.Panel.MarginRight = 80;

			tChart1.Axes.Bottom.Automatic = false;
			tChart1.Axes.Bottom.AutomaticMaximum = false;
			tChart1.Axes.Bottom.AutomaticMinimum = false;
			tChart1.Axes.Bottom.Increment = 0.2;
			tChart1.Axes.Bottom.Maximum = 1.0;
			tChart1.Axes.Bottom.Minimum = -1.0;

			tChart1.Axes.Left.Automatic = false;
			tChart1.Axes.Left.AutomaticMaximum = false;
			tChart1.Axes.Left.AutomaticMinimum = false;
			tChart1.Axes.Left.Increment = 0.2;
			tChart1.Axes.Left.Maximum = 1.0;
			tChart1.Axes.Left.Minimum = -1.0;

			this._colorGrid = new ColorGrid();
			this._colorGrid.Pen.Visible = false;
			this._colorGrid.Title = "colorGrid1";
			this._colorGrid.UseColorRange = false;
			this._colorGrid.UsePalette = true;
			this._colorGrid.XStep = 1;

			this.tChart1.Series.Add(this._colorGrid);

			LoadColorPalette();
			_legendPalette = new LegendPalette(tChart1.Chart);

			_legendPalette.Axis = LegendPaletteAxis.laOther;
			_legendPalette.Width = 60;
			_legendPalette.Pen.Visible = false;
			_legendPalette.Series = _colorGrid;

			this.ResumeLayout(false);

			tChart1.SizeChanged += new System.EventHandler(this.Chart_SizeChanged);


		}

		private void Chart_SizeChanged(object sender, EventArgs e)
		{
			watch.Reset();
			watch.Start();
			tChart1.AutoRepaint = false;
			_legendPalette.Left = tChart1.Width - _legendPalette.Width - 10;
			_legendPalette.Top = (tChart1.Height - _legendPalette.Height) / 2;
			tChart1.AutoRepaint = true;
			tChart1.Refresh();
		}

		private void LoadColorPalette()
		{
			double minValue = _colorBarMin;
			double maxValue = _colorBarMax;
			double delta = _colorBarMax - _colorBarMin;

			_colorGrid.ClearPalette();
			_rainbowLowBlackPalette = new Color[256];
			int redIndex;
			int greenIndex;
			int blueIndex;
			for (int i = 0; i < 256; i++)
			{
				if (i == 0)
				{
					redIndex = 0;
					greenIndex = 0;
					blueIndex = 0;
				}
				else if (i > 0 && i <= 32)
				{
					redIndex = -255 / 32 * i + 255;
					greenIndex = 0;
					blueIndex = 255;
				}
				else if (i > 32 && i <= 85)
				{
					redIndex = 0;
					greenIndex = (255 / (85 - 32)) * (i - 32);
					blueIndex = 255;

				}
				else if (i > 85 && i <= 143)
				{
					redIndex = 0;
					greenIndex = 255;
					blueIndex = (-255 / (143 - 86)) * (i - 143);
				}
				else if (i > 143 && i <= 199)
				{
					redIndex = (255 / (199 - 143)) * (i - 143);
					greenIndex = 255;
					blueIndex = 0;
				}
				else
				{
					redIndex = 255;
					greenIndex = (-255 / (255 - 199)) * (i - 255);
					blueIndex = 0;
				}
				_rainbowLowBlackPalette[i] = Color.FromArgb(redIndex, greenIndex, blueIndex);

				_colorGrid.AddPalette(((delta / 255.0) * (double)i + minValue), _rainbowLowBlackPalette[i]);
			}
		}

		private void GenerateData()
		{
			var Nx = 50;
			var Ny = 25;
			var Nu = 1001;
			var Nv = 1001;

			_xData = new double[Nu * Nv];
			_yData = new double[Nu * Nv];
			_zData = new double[Nu * Nv];

			var du = 2.0 / (Nu - 1);
			var dv = 2.0 / (Nv - 1);

			int k = 0;
			for (int i = 0; i < Nu; i++)
			{
				var v = -1.0 + dv * i;
				for (int j = 0; j < Nv; j++)
				{
					var u = -1.0 + du * j;
					var argx = 0.5 * Nx * u;
					var argy = 0.5 * Ny * v;

					_xData[k] = u;
					_yData[k] = v;
					_zData[k] = 20.0 * Math.Log10(Math.Abs(sinc(argx) * sinc(argy)));
					k++;
				}
			}
		}

		private double sinc(double x)
		{
			if (Math.Abs(x) < 1.0e-7)
			{
				return 1.0;
			}
			else
			{
				return (Math.Sin(Math.PI * x) / (Math.PI * x));
			}
		}
The calls to the instance of Stopwatch "watch" are on lines 21, 22, 38, 39, 95 and 96.