Page 1 of 1

Stacked area series

Posted: Mon Oct 05, 2009 6:18 pm
by 10546565
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

Re: Stacked area series

Posted: Tue Oct 06, 2009 10:22 am
by yeray
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;

Re: Stacked area series

Posted: Tue Oct 06, 2009 2:01 pm
by 10546565
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).

Re: Stacked area series

Posted: Wed Oct 07, 2009 8:17 am
by yeray
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;

Re: Stacked area series

Posted: Wed Oct 07, 2009 3:59 pm
by 10546565
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