Stacked area series

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
TestAlways
Advanced
Posts: 228
Joined: Tue Aug 28, 2007 12:00 am
Location: Oregon, USA

Stacked area series

Post by TestAlways » Mon Oct 05, 2009 6:18 pm

I am having a problem with understanding how a stacked area series when working iwth various series.

Here is an image of what I am seeing:

Image

In the data I am working with, at a specific time (X axis) the value (y axis) will instantly go to zero.

This leaves 'holes' in the chart--everything should just shift down.

I can get this to work with two series, but do not know the logic for n series of areas.

The code is pretty simple:

Code: Select all

procedure TForm46.UpdateChart;
var
  I: Integer;
  J: Integer;
  lValue: Double;
  lSrs: TChartSeries;
begin
  Chart1.FreeAllSeries;
  for I := 0 to spnNumSeries.Value-1 do
  begin
    lSrs := CreateSeries;
    for J := 0 to spnNumPoints.Value-1 do
    begin
      lValue := GetValue(I, J);
      if lValue > 0 then
        lSrs.AddXY(J, lValue)
      else
        lSrs.AddNullXY(J, lValue);

      if (lValue > 0) and (GetValue(I, J + 1) = 0) then
        lSrs.AddNullXY(J, 0)
    end;
  end;
end;
A demo project is at:

http://www.tbinc.com/misc/TChartStackedAreaSeries.zip

How can I code this so that it does not have the 'holes'?

Ed Dressel

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Stacked area series

Post by Yeray » Tue Oct 06, 2009 10:22 am

Hi Ed Dressel,

I'm not sure to see how would you expect that to be drawn. Here it is the easiest code I can think to reproduce the problem.
And, commented, there is a line that could solve the problem for this case if you expected that those holes should be painted in the color of the area series above.

Code: Select all

uses series;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Chart1.View3D := false;

  Chart1.AddSeries(TAreaSeries.Create(self));
  Chart1.AddSeries(TAreaSeries.Create(self));

  Chart1[0].AddXY(0,10);
  Chart1[1].AddXY(0,10);

  Chart1[0].AddXY(1,10);
  Chart1[1].AddXY(1,10);
//  Chart1[1].AddXY(1,20);

  Chart1[0].AddNullXY(2,0);
  Chart1[1].AddXY(2,10);

  Chart1[0].AddXY(3,0);
  Chart1[1].AddXY(3,10);


  (Chart1[0] as TAreaSeries).MultiArea := maStacked;

  Chart1.Axes.Left.SetMinMax(0,30);
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

TestAlways
Advanced
Posts: 228
Joined: Tue Aug 28, 2007 12:00 am
Location: Oregon, USA

Re: Stacked area series

Post by TestAlways » Tue Oct 06, 2009 2:01 pm

If I change one number in your code, you solutions works as I would want it to:

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
begin
  Chart1.View3D := false;

  Chart1.AddSeries(TAreaSeries.Create(self));
  Chart1.AddSeries(TAreaSeries.Create(self));

  Chart1[0].AddXY(0,10);
  Chart1[1].AddXY(0,10);

  Chart1[0].AddXY(1,10);
  Chart1[1].AddXY(1,10);
  Chart1[1].AddXY(1,10); // <<---- changed second value  from '20 ' to '10'

  Chart1[0].AddNullXY(2,0);
  Chart1[1].AddXY(2,10);

  Chart1[0].AddXY(3,0);
  Chart1[1].AddXY(3,10);

  (Chart1[0] as TAreaSeries).MultiArea := maStacked;

  Chart1.Axes.Left.SetMinMax(0,30);
end;
And I get how to do this when working with a known number of series. But I don't know how to do this when working with a lot of series (like the demo application I posted a link to in my initial post).

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Stacked area series

Post by Yeray » Wed Oct 07, 2009 8:17 am

Hi Ed Dressel,

Take a look at this modification of your UpdateChart method that seems to work around this issue. Note that I'm simply saving where each series goes to null and I'm duplicating all the other series points over that "special" ones.

Code: Select all

procedure TForm46.UpdateChart;
var
  I: Integer;
  J: Integer;
  lValue: Double;
  lSrs: TChartSeries;
  Stairs: array of TPoint; //X values will store the series index, and Y values will store the value index of the stairs
begin
  Chart1.FreeAllSeries;
  SetLength(Stairs,0);
  for I := 0 to spnNumSeries.Value-1 do
  begin
    lSrs := CreateSeries;
    for J := 0 to spnNumPoints.Value-1 do
    begin
      lValue := GetValue(I, J);
      if lValue > 0 then
        lSrs.AddXY(J, lValue)
      else
        lSrs.AddNullXY(J, lValue);

      if (lValue > 0) and (GetValue(I, J + 1) = 0) then
      begin
        lSrs.AddNullXY(J, 0);
        SetLength(Stairs,Length(Stairs)+1);
        Stairs[Length(Stairs)-1] := Point(I,J);
      end;
    end;
  end;

  for I := 0 to Length(Stairs)-1 do
  begin
    for J := Stairs[I].X+1 to spnNumSeries.Value-1 do
      Chart1[J].AddXY(Stairs[I].Y, Chart1[J].YValue[Stairs[I].Y]);
  end;
end;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

TestAlways
Advanced
Posts: 228
Joined: Tue Aug 28, 2007 12:00 am
Location: Oregon, USA

Re: Stacked area series

Post by TestAlways » Wed Oct 07, 2009 3:59 pm

Nicely done--I though of something like that but wasn't sure it would work and it was not nearly so concise. (A list of objects, I like the array implementation).

For the sake of someone who might reference this, I will mention this: When working with more than two series, there is a problem because the TPoint.Y value (the index of the value in the series) will be off because the value is inserted into the list. The code change below is right towards the end:

Code: Select all

  for I := Length(Stairs)-1 downto 0 do  //<--changed so that it counts down
  begin
    for J := Stairs[I].X+1 to spnNumSeries.Value-1 do
      Chart1[J].AddXY(Stairs[I].Y, Chart1[J].YValue[Stairs[I].Y]);
  end;
end;
Thanks for the help.

Ed Dressel

Post Reply