Page 1 of 1

How do I optimize the Map series with many polygons?

Posted: Mon Jul 13, 2009 7:02 pm
by 15653258
I am trying to display state information in a chart that is related to the data in a line series. What I want to do is display vertical bars in the background behind the line series that will stretch the full height of the y axis, and change colors as the state changes (if the line series contains tempuratures over time, the vertical bars will change colors as the tempurature passes certain threshholds). I have tried to use a Map series to do this, creating polygons for each state, but I have noticed that the performance of chart tool interactions (dragging of a cursor, etc...) start to degrade at about 100 polygons. It is possible that I could be required to display several of these "State" style series on one chart, with many more than 100 polygons per.

Can anyone tell me...
a. how to optimize the performance of the tool interactions with the Map series or the Map series itself?
b. if there is a better, faster series type that is more suited to this type of application?
c. if this is a candidate for extending a base class? If so, can you point me to an example of how to do this and the best base class to use?
d. if there is a better way to draw polygons to the background of an axis?
e. if there is a option I have not thought of?

Re: How do I optimize the Map series with many polygons?

Posted: Tue Jul 14, 2009 11:45 am
by yeray
Hi Andrew,

A simple example project or a code we could run as-is to reproduce your situation here would be really helpful to understand it.

Is something like that what you are doing?

Code: Select all

public Form1()
        {
            InitializeComponent();
            InitializeChart();
        }

        FastLine fast1;
        Map map1;
        CursorTool cursor1;

        private void InitializeChart()
        {
            tChart1.Aspect.View3D = false;
            tChart1.Legend.Visible = false;

            map1 = new Map(tChart1.Chart);

            fast1 = new FastLine(tChart1.Chart);
            fast1.FillSampleValues(300);

            PolygonList shapes = new PolygonList(map1);
            Polygon poly1;

            double threshold1, threshold2;

            threshold1 = fast1.YValues.Minimum + (fast1.YValues.Maximum - fast1.YValues.Minimum) / 3;
            threshold2 = fast1.YValues.Minimum + (fast1.YValues.Maximum - fast1.YValues.Minimum) / 3 * 2;

            for (int i = 0; i < fast1.Count; i++)
            {
                poly1 = new Polygon(shapes,tChart1.Chart);
                poly1.Add(fast1.XValues.Value[i] - 0.5, fast1.YValues.Minimum);
                poly1.Add(fast1.XValues.Value[i] + 0.5, fast1.YValues.Minimum);
                poly1.Add(fast1.XValues.Value[i] + 0.5, fast1.YValues.Maximum);
                poly1.Add(fast1.XValues.Value[i] - 0.5, fast1.YValues.Maximum);
                map1.Shapes.Add(poly1);
                
                if (fast1.YValues.Value[i] > threshold2)
                {
                    map1.Colors[i] = Color.Red;
                }
                else
                {
                    if (fast1.YValues.Value[i] > threshold1) map1.Colors[i] = Color.Blue;
                    else map1.Colors[i] = Color.Green;
                }
            }

            map1.Pen.Visible = false;

            tChart1.Draw();

            cursor1 = new CursorTool(tChart1.Chart);
            cursor1.XValue = fast1.Count / 2;
            cursor1.YValue = (fast1.YValues.Maximum - fast1.YValues.Minimum) / 2 + fast1.YValues.Minimum;
            //cursor1.FastCursor = true;  //this could help you to improve the cursor movements        
        }

Re: How do I optimize the Map series with many polygons?

Posted: Tue Jul 14, 2009 5:34 pm
by 15653258
Yes, your sample project is almost exactly what I am trying to do.

First of all, I am trying to do this on the web, not a desktop application.
Second, my cursor is actually a ColorLine hooked up to some mouse events (is this something I should change? Can the CursorTool display only a vertical line?)
Next, I was using...

Code: Select all

                polygon = new Polygon(MapSeries.Shapes, MapSeries.Chart);

                polygon.Add(x, maximumY);            
...
                polygon.Color = GetColor(y);
...
                MapSeries.Shapes.Add(polygon);
Is this way less efficient when building the objects than the one you outlined in your post (external PolygonList)? Is there an optimized way?
Finally, I also noticed a long delay (about 1 minute load time, a couple of timeouts) when refreshing the page that is not related to data retrival when creating about 200 polygons. Is this expected?

Re: How do I optimize the Map series with many polygons?

Posted: Wed Jul 15, 2009 9:55 am
by yeray
Hi Andrew,
AndrewP wrote:Yes, your sample project is almost exactly what I am trying to do.

First of all, I am trying to do this on the web, not a desktop application.
It would be easier for us to find an acceptable solution for you if we could debug your test application and see what are you exactly doing. Trying to implement an example from your explanations will always be slower and more difficult. That's why we often ask for a simple example project we can run as-is to reproduce the problem here.
AndrewP wrote:Second, my cursor is actually a ColorLine hooked up to some mouse events (is this something I should change? Can the CursorTool display only a vertical line?)
Yes, the cursor tool can be viewed as a vertical line and it allows some other features such as following the mouse or snapping to the points of a series:

Code: Select all

cursor1.Style = CursorToolStyles.Vertical;
cursor1.FastCursor = true;

cursor1.Series = fast1;
cursor1.Snap = true;
AndrewP wrote:Is this way less efficient when building the objects than the one you outlined in your post (external PolygonList)? Is there an optimized way?
Finally, I also noticed a long delay (about 1 minute load time, a couple of timeouts) when refreshing the page that is not related to data retrival when creating about 200 polygons. Is this expected?
It's normal, as more points to draw, it costs more. But you have different option to try to optimize it.
One could be using a cursor tool with fastcursor to true. This will prevent the chart to be repainted every time the cursor is moved.
Another could be changing the map series to rectangles drawn directly to the canvas. Here you have another simple example:

Code: Select all

public Form1()
        {
            InitializeComponent();
            InitializeChart();
        }

        FastLine fast1;
        CursorTool cursor1;
        double threshold1, threshold2;

        private void InitializeChart()
        {
            chartController1.Chart = tChart1;

            tChart1.Aspect.View3D = false;
            tChart1.Legend.Visible = false;
            tChart1.Dock = DockStyle.Fill;

            fast1 = new FastLine(tChart1.Chart);
            fast1.FillSampleValues(500);
            fast1.Color = Color.Orange;

            threshold1 = fast1.YValues.Minimum + (fast1.YValues.Maximum - fast1.YValues.Minimum) / 3;
            threshold2 = fast1.YValues.Minimum + (fast1.YValues.Maximum - fast1.YValues.Minimum) / 3 * 2;

            tChart1.Draw();

            cursor1 = new CursorTool(tChart1.Chart);
            cursor1.XValue = fast1.Count / 2;
            cursor1.YValue = (fast1.YValues.Maximum - fast1.YValues.Minimum) / 2 + fast1.YValues.Minimum;

            cursor1.Style = CursorToolStyles.Vertical;
            cursor1.FastCursor = true;
            cursor1.FollowMouse = true;

            tChart1.Walls.Back.Visible = false;
            tChart1.BeforeDraw += new Steema.TeeChart.PaintChartEventHandler(tChart1_BeforeDraw);
        }

        void tChart1_BeforeDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
        {
            g.Pen.Visible = false;
            int XLeft = fast1.CalcXPos(0);
            int XRight = fast1.CalcXPos(1);
            double XDiff = (double)(XRight-XLeft)/2;
            for (int i = 0; i < fast1.Count; i++)
            {
                if (fast1.YValues.Value[i] > threshold2) g.Brush.Color = Color.Red;
                else g.Brush.Color =(fast1.YValues.Value[i] > threshold1) ? Color.Blue : Color.Green;

                int a = (int)Math.Ceiling(fast1.CalcXPos(i) - XDiff);
                int b = tChart1.Axes.Left.CalcYPosValue(tChart1.Axes.Left.Maximum);
                int c = (int)Math.Ceiling(fast1.CalcXPos(i) + XDiff);
                int d = tChart1.Axes.Left.CalcYPosValue(tChart1.Axes.Left.Minimum);
                g.Rectangle(a, b, c, d);
            }
        }

Re: How do I optimize the Map series with many polygons?

Posted: Tue Jul 21, 2009 9:29 pm
by 15653258
Thnaks for your help thus far. I have implemented the solution you last suggested using Graphics3D in the BeforeDrawSeries event of the chart. I have a behaviour where I change the date ranges on the XAxis. When I perform this action, I observe the attached video.

Re: How do I optimize the Map series with many polygons?

Posted: Tue Jul 21, 2009 9:43 pm
by 15653258
I just uploaded the video. If you need the codec to view the video, it is available for download at http://www.techsmith.com/download/codecs.asp.

In the video, clicking the << button effectively adjusts the time range on the XAxis. The visible colored area over the legend is the problem. That area is a direct result of using the BeforeDrawAxes event to draw the rectangles directly, but I do not understand how. Is it possible that changing the dates ranges on the XAxis before the redraw (we recreate the entire chart, and then redraw the series) is causing this issue (adjusting the XAxis while waiting for data to return to rebuild the series). As you can see, once the redraw occurs all is good.

Is it possible to clear / hide the drawing that I have done (via Graphics3D) when adjusting the date range on the XAxis, effectivley wiping the slate clean, and then waiting for the series to redraw?

This operation will be very difficult to put into a sample app, and I cannot send the entire app (too many installation steps and dependencies). I hope the video will suffice.

Re: How do I optimize the Map series with many polygons?

Posted: Tue Jul 21, 2009 10:22 pm
by 15653258
Not sure if this is related, but the rectangles have a transparency set and every time I click the "<<" and then the ">>" button (effectively moving the time range back, and then forward to the original time range) the transparency gets darker (the drawing seems to overwrite the last drawn items, resulting in what looks like a darker color, or less transparency).

Re: How do I optimize the Map series with many polygons?

Posted: Wed Jul 22, 2009 8:33 am
by 10050769
Hello AndrewP,

I couldn't reproduce your problem here. Please, you could send us code of button <<, because we can reproduce the problem here. If is not possible to send code, please explain exactly what do the button because we try to solve the problem.

Thanks.

Re: How do I optimize the Map series with many polygons?

Posted: Wed Jul 22, 2009 3:06 pm
by 15653258
Is it possible to clear / hide the drawing that I have done (via Graphics3D) when adjusting the date range on the XAxis, effectivley wiping the slate clean, and then waiting for the series to redraw?

Re: How do I optimize the Map series with many polygons?

Posted: Wed Jul 22, 2009 3:27 pm
by 15653258
Uploading a sample app.

Re: How do I optimize the Map series with many polygons?

Posted: Thu Jul 23, 2009 8:28 am
by 10050769
Hello Andrew,

I I do not understand your problem because the video leaves a brown rectangle and here we see the applicaciĆ³ you have send and not appears rectangle.
Is this the problem? If the problem isn't it, please you could explain exactly what is your problem?

Thanks,

Re: How do I optimize the Map series with many polygons?

Posted: Thu Jul 23, 2009 4:01 pm
by 15653258
Yes, the problem is the color that appears outside of the chart area (white area where data is displayed). It appears brown on the video, and differing color on the sample I uploaded yesterday. I think what I need is a way to clear all the drawing I have done via Graphics3D when I click those buttons. I that possible?

Re: How do I optimize the Map series with many polygons?

Posted: Fri Jul 24, 2009 8:16 am
by 10050769
Hello Andrew,

I couldn't reproduce your probleme here. In the application that you send: you can see rectangle brown or different color? Please, check sample that you send appears this rectangle. If appears, please you could say what is your version of TeeChartFor .Net ?

Thanks,

Re: How do I optimize the Map series with many polygons?

Posted: Fri Jul 24, 2009 3:34 pm
by 15653258
I have uploaded one more video, just now. This one is of the problem in the sample app that I uploaded a few days ago. As you can clearly see as indicated by the mouse movements, there are areas of color outside of the chart axis area (where data is usually displayed) that should not be there. As you can see by the TeeChart dll attached to my sample project, I am using the latest .Net version. You can feel free to continue to troubleshoot this issue, but I am putting this issue on hold for the time being. I have chosen to go with another solution not related to Graphics3D.

Re: How do I optimize the Map series with many polygons?

Posted: Mon Jul 27, 2009 1:31 pm
by narcis
Hi AndrewP,

Implementing the BeforeDrawAxes event in your project as below solves the problem.

Code: Select all

        private void tChart1_BeforeDrawAxes(object sender, Steema.TeeChart.Drawing.Graphics3D g)
        {
					g.Pen.Visible = false;
					int XLeft = fast1.CalcXPos(0);
					int XRight = fast1.CalcXPos(1);
					double XDiff = (double)(XRight - XLeft) / 2;
					for (int i = 0; i < fast1.Count; i++)
					{
						if (fast1.YValues.Value[i] > threshold2) g.Brush.Color = Color.Red;
						else g.Brush.Color = (fast1.YValues.Value[i] > threshold1) ? Color.Blue : Color.Green;

						int a = (int)Math.Ceiling(fast1.CalcXPos(i) - XDiff);
						int b = tChart1.Axes.Left.CalcYPosValue(tChart1.Axes.Left.Maximum);
						int c = (int)Math.Ceiling(fast1.CalcXPos(i) + XDiff);
						int d = tChart1.Axes.Left.CalcYPosValue(tChart1.Axes.Left.Minimum);

						Rectangle chartRect = tChart1.Chart.ChartRect;
						Rectangle rect = new Rectangle(a, b, c-a, d-b);
						if (chartRect.IntersectsWith(rect))
						{
							g.Rectangle(a, b, c, d);	
						}						
					}
        }
Hope this helps!