Page 1 of 1

Unexpected behavior of an Area series

Posted: Mon Dec 12, 2022 5:14 pm
by 16892633
Hi, I'm working on a cash flow chart using TeeChart v36 and C++Builder 11.2 with FMX and FireDAC and I'm having troubles with an area chart that seems to be working bad or may be I have making some mistake, so I need help.

There are six Bar series to show amounts of money on different combinations and two additional Area series to show the balance of the selected Bar. Please see the first 'Bar Series' attached image and keep in mind just one Bar series named 'Pendientes' that is plotted and also just one Area series named 'Pendientes Acum' that is not plotted yet. This first 'Pendientes' series is showing positive and negative amounts of money on their Y-value grouping them by date on X-value. Everything okay until here.

Then I want to show an area chart with the composed balance for each date, with the purpose of to know how the balance is changing through the dates, so I added the other Area 'Pendientes Acum' series, please see the second 'Area Series' attached image, but when I activate their dataset the plotted chart presents two problems that I don't know how to solve:
1. The dates on the X-Value in the horizontal axis are plotted by increasing the money amount instead of increasing the date as in the first Bar series, that is how I need it to have consistency between the two series.
2. It affects the first Bar series modifying their plotting on an unexpected behavior, grouping all bar on a unique point.
I'm attaching a third image with the dataset values of the Area series where is possible the check that the order is by date and not by ascending amount.

May be I'm using a wrong kind of Area chart. Which could be the problem? How could I reach my objective of plot money balances?

Best regards,
Patricio Cerda

Re: Unexpected behavior of an Area series

Posted: Mon Dec 12, 2022 9:21 pm
by yeray
Hello,

Here the simple example I used to test this:

Code: Select all

uses FMXTee.Series, DateUtils;

type TData = record
  date: TDateTime;
  value: Double;
end;

var brutoAcum: array of TData;

procedure TForm1.FormCreate(Sender: TObject);
var i, j, min: Integer;
    tmp: TData;
begin
  SetLength(brutoAcum, 8);
  brutoAcum[0].date:=EncodeDate(2022,12,12);
  brutoAcum[0].value:=-63296000;
  brutoAcum[1].date:=EncodeDate(2022,12,14);
  brutoAcum[1].value:=20640000;
  brutoAcum[2].date:=EncodeDate(2022,12,21);
  brutoAcum[2].value:=39660348;
  brutoAcum[3].date:=EncodeDate(2022,12,23);
  brutoAcum[3].value:=-40225116;
  brutoAcum[4].date:=EncodeDate(2022,12,24);
  brutoAcum[4].value:=-40544208;
  brutoAcum[5].date:=EncodeDate(2022,12,25);
  brutoAcum[5].value:=-45686040;
  brutoAcum[6].date:=EncodeDate(2022,12,28);
  brutoAcum[6].value:=-45686040;
  brutoAcum[7].date:=EncodeDate(2022,12,30);
  brutoAcum[7].value:=-112257256;

  with Chart1 do
  begin
    Color:=clWhite;
    Gradient.Visible:=False;
    Walls.Back.Color:=clWhite;
    Walls.Back.Gradient.Visible:=False;
    Axes.Bottom.SetMinMax(IncDay(brutoAcum[0].date, -1), IncDay(brutoAcum[7].date));
    Axes.Bottom.LabelsAngle:=70;

    with TBarSeries(AddSeries(TBarSeries)) do
    begin
      Title:='Pendientes';
      Color:=TAlphaColors.Red;
      BarWidthPercent:=10;
      XValues.DateTime:=True;

      for i:=0 to Length(brutoAcum)-1 do
      begin
        if i>0 then
           AddXY(brutoAcum[i].date, brutoAcum[i].value-brutoAcum[i-1].value)
        else
           AddXY(brutoAcum[i].date, brutoAcum[i].value);
      end;
    end;

    // Sort data by value
    for i:=0 to Length(brutoAcum)-1 do
    begin
      min:=i;
      for j:=i+1 to Length(brutoAcum)-1 do
      begin
        if brutoAcum[j].value<brutoAcum[min].value then
           min:=j;
      end;
      if i<>min then
      begin
        tmp:=brutoAcum[min];
        brutoAcum[min]:=brutoAcum[i];
        brutoAcum[i]:=tmp;
      end;
    end;

    with TAreaSeries(AddSeries(TAreaSeries)) do
    begin
      Title:='Pendientes Acum';
      Color:=TAlphaColors.Red;
      Transparency:=50;
      Marks.Show;

      for i:=0 to Length(brutoAcum)-1 do
        AddXY(Chart1[0].XValues[i], brutoAcum[i].value);
    end;
  end;
end;
Project1_2022-12-12_22-19-42.png
Project1_2022-12-12_22-19-42.png (43.4 KiB) Viewed 35547 times
I think the issue could be on how do you calculate the XValues for your "Pendientes Acum" TAreaSeries

Re: Unexpected behavior of an Area series

Posted: Wed Dec 14, 2022 1:19 pm
by 16892633
Thanks Yeray for your reply, but I'm not sure that if I did explain well the problem.

I think you are sorting 'brutoAcum' ascending by it ammount of money, that is exactly my problem because it is not what I expect. What I want is that the Area series with BrutoAcum values be sorted by Date, so it would be plotted consistent with Bar series.

I can see on your simple example chart an Area series with a irregular line at the top instead of a continuos line on my image sent before, but with exactly the same values with the same order from the first to the last one, starting by -112257255 that correspond to the Dec30th 2022, not to the Dec12th 2022 as shows you chart. This specific value must be the last one on the time line.

Moreover, the form of your chart is not the correct one because does not reflex the real accumulated values for this sample dataset. Let me show the expected (correct) chart made with Excel, attached here.

If you want I can send a little C++Builder project for you to check the same but using data from a FireDac dataset.

Best regards,
Patricio Cerda

Re: Unexpected behavior of an Area series

Posted: Wed Dec 14, 2022 2:16 pm
by yeray
Hello,

then you just don't need to sort the array.
Project1_2022-12-14_15-11-28.png
Project1_2022-12-14_15-11-28.png (36.11 KiB) Viewed 35507 times
Here the modified example:

Code: Select all

uses FMXTee.Series, DateUtils;

type TData = record
  date: TDateTime;
  value: Double;
end;

var brutoAcum: array of TData;

procedure TForm1.FormCreate(Sender: TObject);
var i, j, min: Integer;
    tmp: TData;
    bar: TBarSeries;
    area: TAreaSeries;
begin
  SetLength(brutoAcum, 8);
  brutoAcum[0].date:=EncodeDate(2022,12,12);
  brutoAcum[0].value:=-63296000;
  brutoAcum[1].date:=EncodeDate(2022,12,14);
  brutoAcum[1].value:=20640000;
  brutoAcum[2].date:=EncodeDate(2022,12,21);
  brutoAcum[2].value:=39660348;
  brutoAcum[3].date:=EncodeDate(2022,12,23);
  brutoAcum[3].value:=-40225116;
  brutoAcum[4].date:=EncodeDate(2022,12,24);
  brutoAcum[4].value:=-40544208;
  brutoAcum[5].date:=EncodeDate(2022,12,25);
  brutoAcum[5].value:=-45686040;
  brutoAcum[6].date:=EncodeDate(2022,12,28);
  brutoAcum[6].value:=-45686040;
  brutoAcum[7].date:=EncodeDate(2022,12,30);
  brutoAcum[7].value:=-112257256;

  with Chart1 do
  begin
    Color:=clWhite;
    Gradient.Visible:=False;
    Walls.Back.Color:=clWhite;
    Walls.Back.Gradient.Visible:=False;
    View3D:=False;
    Axes.Bottom.SetMinMax(IncDay(brutoAcum[0].date, -1), IncDay(brutoAcum[7].date));
    Axes.Bottom.LabelsAngle:=70;

    area:=TAreaSeries(AddSeries(TAreaSeries));
    bar:=TBarSeries(AddSeries(TBarSeries));

    with area do
    begin
      Title:='Pendientes Acum';
      Color:=TAlphaColors.Red;
      Transparency:=50;
      Marks.Show;
      YOrigin:=0;
      UseYOrigin:=True;
      AreaLinesPen.Hide;
    end;

    with bar do
    begin
      Title:='Pendientes';
      Color:=TAlphaColors.Red;
      BarWidthPercent:=10;
      XValues.DateTime:=True;
    end;

    for i:=0 to Length(brutoAcum)-1 do
    begin
      area.AddXY(brutoAcum[i].date, brutoAcum[i].value);

      if i>0 then
         bar.AddXY(brutoAcum[i].date, brutoAcum[i].value-brutoAcum[i-1].value)
      else
         bar.AddXY(brutoAcum[i].date, brutoAcum[i].value);
    end;
  end;
end;

Re: Unexpected behavior of an Area series

Posted: Thu Dec 15, 2022 4:33 pm
by 16892633
Dear Yeray,

Thank you again, finally I do it work successfully taking data directly from the Dataset.

One more thing please: could you show me how can access to the Series\Format\UseOrigin property at runtime in C++ Builder?
In your sample Delphi code you showed it but I can't find it on C++ Builder. Also the YOrigin value that I want to set at runtime also.

Best regards,
Patricio Cerda

Re: Unexpected behavior of an Area series

Posted: Fri Dec 16, 2022 8:43 am
by yeray
Hello,

This works for me:

Code: Select all

  area->YOrigin=0;
  area->UseYOrigin=true;