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:
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