Page 1 of 1

Stacked bars with neg values still rendered faulty in 3D

Posted: Thu Jul 23, 2009 9:16 am
by 10553957
Hi

Recently I updated from Tee7Pro to Tee8Pro. There is still a bug (was already there in Tee5! :shock: ) and I have a patch for it, as I have to display bar charts with pos and neg values all the time.
It involves some patches in series.pas and TeEngine.pas.

:idea: I can post them here if you want me to. I have been applying these patches from tee5 upto Tee8 :? and they seem to have no negative impact on the other TChart series. (tested for several years!)

Regards - Hans

Re: Stacked bars with neg values still rendered faulty in 3D

Posted: Thu Jul 23, 2009 1:16 pm
by yeray
Hi Hans,

Yes it would be very kind if you would provide your changes to us. We'll be pleased to see if we can include them asap.

Re: Stacked bars with neg values still rendered faulty in 3D

Posted: Thu Jul 23, 2009 1:34 pm
by 10553957
Here are the patches

Code: Select all


Function TBarSeries.DrawSeriesForward(ValueIndex:Integer):Boolean;
begin
  Case FMultiBar of
    mbNone,
    mbSide,
    mbSideAll: result:=inherited DrawSeriesForward(ValueIndex);
    mbStacked,
    mbSelfStack:
               begin
{$IFDEF HH_PATCH_TC_STACKED}
                 result:=not GetVertAxis.Inverted;
{$else}
                 result:=YValues.Value[ValueIndex]>=YOrigin; { 5.01 }
                 if GetVertAxis.Inverted then result:=not result;
{$endif}
               end;
  else
    result:=(not GetVertAxis.Inverted);
  end;
end;

////////////////////////////////////////////////////////////////

    Procedure DrawAllSeriesValue(ValueIndex:Integer);

{$IFDEF HH_PATCH_TC_STACKED}
// These two functions respectively only draw all the positive values and all the negative values
// this allows the Roofs of the barseries to be placed correctly instead of creating M.G.Escher like charts
      Procedure TryDrawPosSeries(ASeries:TChartSeries);
      begin
        With ASeries do
         if FActive and (ZOrder=TheSeries.ZOrder) and (ValueIndex<Count) and (MandatoryValueList[ValueIndex]>=0.0) then
            DrawValue(ValueIndex)
      end;

      Procedure TryDrawNegSeries(ASeries:TChartSeries);
      begin
        With ASeries do
         if FActive and (ZOrder=TheSeries.ZOrder) and (ValueIndex<Count) and (MandatoryValueList[ValueIndex]<0.0) then
            DrawValue(ValueIndex)
      end;
{$ENDIF}

      { If the ASeries parameter has the same "Z" order than the current
        series, draw the point }
      Procedure TryDrawSeries(ASeries:TChartSeries);
      begin
        With ASeries do
         if FActive and (ZOrder=TheSeries.ZOrder) and (ValueIndex<Count) then
            DrawValue(ValueIndex)
      end;

    var t    : Integer;
        tmp1 : Integer;
        tmp2 : Integer;
    Begin
      tmp1:=SeriesList.IndexOf(TheSeries);
      tmp2:=SeriesCount-1;
{$IFDEF HH_PATCH_TC_STACKED}
// This splits up drawing of series in a negative and a positive phase
// the negative phase is drawn first so the roof tops of negative Bars will
// be overwritten by the bottoms of the positive bars. Also fixes the same
// problem for the area charts
      if ValueIndex<TheSeries.Count then
      begin
        if TheSeries.DrawSeriesForward(ValueIndex) then
        begin
          for t:=tmp2 downto tmp1 do TryDrawNegSeries(Series[t]);
          for t:=tmp1 to tmp2 do TryDrawPosSeries(Series[t]);
        end
        else
        begin
          for t:=tmp2 downto tmp1 do TryDrawPosSeries(Series[t]);
          for t:=tmp1 to tmp2 do TryDrawNegSeries(Series[t]);
        end
      end
      else
      begin
         for t:=tmp1 to tmp2 do TryDrawNegSeries(Series[t]);
         for t:=tmp1 to tmp2 do TryDrawPosSeries(Series[t]);
      end;
{$ELSE}
      if ValueIndex<TheSeries.Count then
      begin
        if TheSeries.DrawSeriesForward(ValueIndex) then
           for t:=tmp1 to tmp2 do TryDrawSeries(Series[t])
        else
           for t:=tmp2 downto tmp1 do TryDrawSeries(Series[t])
      end
      else for t:=tmp1 to tmp2 do TryDrawSeries(Series[t])
{$endif}      
    end;



Re: Stacked bars with neg values still rendered faulty in 3D

Posted: Fri Jul 24, 2009 11:02 am
by yeray
Hi Hans,

First of all I'd like to thank you very much for your fix suggestions.
I've seen that your code improves the result of the stacked bars but, if I'm right, still not for all the situations. I mean, in your sample application, one could still see some bars not drawn correctly if you don't disable BarSeries1. Am I missing something?
Images explain better than words...

Before any change (I've only added checkboxes to the legend, clicked btTestYears and zoomed a little bit):
Image
We can see many errors.

Note that disabling the first series the result is improved:
Image

Then, after applying your code, the result is better in the first case:
Image

And perfect when disabling the first series:
Image

If I'm not wrong, there still remains something. So, I'll add the issue to the wish list to be revised asap to implement a fix that would solve all situations, if possible.

Of course, you code will help our developers to find the best solution.

Re: Stacked bars with neg values still rendered faulty in 3D

Posted: Fri Jul 24, 2009 11:58 am
by 10553957
Yes, it would be very nice if it got fixed. I have been hammering on this since tee4 or tee5 if I remember correctly. :arrow: For now, as an intermediate patch I suggest you implement my patch "as is". It won't break any code for your customers, and fixes about 100% of my stacked bars trouble :) .

Regards - Hans

Re: Stacked bars with neg values still rendered faulty in 3D

Posted: Mon Jul 27, 2009 8:01 am
by 10553957
I seem to be unable to reproduce your screenshots. Did you apply both patches?

1 patch in Series.pas:
TBarSeries.DrawSeriesForward

2 patches in TeEngine.pas,
introducing TryDrawPosSeries and TryDrawNegSeries
And the code for calling them from within TryDrawSeries

Regards - Hans

Re: Stacked bars with neg values still rendered faulty in 3D

Posted: Mon Jul 27, 2009 8:31 am
by yeray
Hi Hans,

Following your suggestions I have:

At Series.pas:

Code: Select all

Function TBarSeries.DrawSeriesForward(ValueIndex:Integer):Boolean;
begin
  Case FMultiBar of
    mbNone,
    mbSide,
    mbSideAll: result:=inherited DrawSeriesForward(ValueIndex);
  else
    result:=(not GetVertAxis.Inverted);
  end;
end;
At TeEngine.pas:

Code: Select all

    { Draw one single point (ValueIndex) for all Series }
    Procedure DrawAllSeriesValue(ValueIndex:Integer);

      { If the ASeries parameter has the same "Z" order than the current
        series, draw the point }
      Procedure TryDrawPosSeries(ASeries:TChartSeries);
      begin
        With ASeries do
         if FActive and (ZOrder=TheSeries.ZOrder) and (ValueIndex<Count) and (MandatoryValueList[ValueIndex]>=0.0) then
            DrawValue(ValueIndex)
      end;

      Procedure TryDrawNegSeries(ASeries:TChartSeries);
      begin
        With ASeries do
         if FActive and (ZOrder=TheSeries.ZOrder) and (ValueIndex<Count) and (MandatoryValueList[ValueIndex]<0.0) then
            DrawValue(ValueIndex)
      end;

    var t    : Integer;
        tmp1 : Integer;
        tmp2 : Integer;
    Begin
      tmp1:=SeriesList.IndexOf(TheSeries);
      tmp2:=SeriesCount-1;

      // This splits up drawing of series in a negative and a positive phase
      // the negative phase is drawn first so the roof tops of negative Bars will
      // be overwritten by the bottoms of the positive bars. Also fixes the same
      // problem for the area charts
      if ValueIndex<TheSeries.Count then
      begin
        if TheSeries.DrawSeriesForward(ValueIndex) then
        begin
          for t:=tmp2 downto tmp1 do TryDrawNegSeries(Series[t]);
          for t:=tmp1 to tmp2 do TryDrawPosSeries(Series[t]);
        end
        else
        begin
          for t:=tmp2 downto tmp1 do TryDrawPosSeries(Series[t]);
          for t:=tmp1 to tmp2 do TryDrawNegSeries(Series[t]);
        end
      end
      else
      begin
         for t:=tmp1 to tmp2 do TryDrawNegSeries(Series[t]);
         for t:=tmp1 to tmp2 do TryDrawPosSeries(Series[t]);
      end;
    end;
And the following code added to your application still shows a bad result:

Code: Select all

procedure TForm1.FormCreate(Sender: TObject);
begin
  BarSeries1.Clear;
  BarSeries2.Clear;
  BarSeries3.Clear;
  BarSeries2.Add(-5);
  BarSeries3.Add(-5);
end;

Re: Stacked bars with neg values still rendered faulty in 3D

Posted: Mon Jul 27, 2009 10:37 am
by 10553957
Hi

Changing the line

Code: Select all

<snip>
      if ValueIndex<TheSeries.Count then
      begin
        if TheSeries.DrawSeriesForward(ValueIndex) then
        begin
          for t:=tmp2 downto tmp1 do
            TryDrawNegSeries(Series[t]);
<snip>
into

Code: Select all

<snip>
      if True then
      begin
        if TheSeries.DrawSeriesForward(ValueIndex) then
        begin
          for t:=tmp2 downto tmp1 do
            TryDrawNegSeries(Series[t]);
<snip>
in routine DrawAllSeriesValue(ValueIndex:Integer); seems to fix this particular problem, but I am unsure whether this breaks any other code. Down here it looks great, also for your sample.

Regards - Hans

Re: Stacked bars with neg values still rendered faulty in 3D

Posted: Mon Jul 27, 2009 1:33 pm
by yeray
Hi Hans,

Thank you again for our interest on the bug tracking and fixing.
Your code seems to work fine for stacked bars but it brakes the result for mbSide and mbStacked100 with negative values.

I've incremented the issue tracking ticket to be fixed asap (TV52014308). It seems that the appropriate solution should be really near.