TeEngine.InternalDraw.ApplyMaxMinOffsets in conjuction with

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
davidnovo
Newbie
Newbie
Posts: 15
Joined: Mon Nov 30, 2009 12:00 am

TeEngine.InternalDraw.ApplyMaxMinOffsets in conjuction with

Post by davidnovo » Fri Apr 30, 2010 5:09 pm

In ApplyMaxMinOffsets, you calculate tmpR to see whether to adjust the axis.IMInimum and IMaximum.
In our case, tmpR is always (0,0,0,0). The problem with that is that you are calling Axis.AdjustMaxMinRect(0,0,0,0), probably assuming it will not do anything. But it does. In my case, before this method call, the Axis.MinimumValue is zero, as is the Axis.IMinimum.

However, when calling RecalcAdjustedMinMax, you recalculate IMinimum based on the the "adjusted" IStart value, which is the same as the regular IStart (in my case, pixel 37). However, due to rounding errors that occur when converting from pixel to double, the new IMinimum becomes ~0.002.... This would not be a problem, except that in OnGetNextAxisLabel, I use the Axis.MimimumValue as the basis for my calculations, and return 0 as my first label. When I return 0 as the next label value, DoCustomLabels stops drawing any more labels, because 0<0.002 and LabelInside=False;

see in DoCustomLabels

Code: Select all

        LabelInside:=(tmpValue>=(IMinimum-DifFloat)) and
                     (tmpValue<=(IMaximum+DifFloat));
In short, I made the following changes. Please let me know if they are appropriate and I think you may want to consider them in your release.

Code: Select all

  procedure ApplyMaxMinOffsets;
      var tmpHasOffsets : Boolean;
      begin
        tmpHasOffsets:=(Axis.MaximumOffset<>0) or (Axis.MinimumOffset<>0);

        if tmpHasOffsets then
        [b]begin // begin added by dns[/b]
             if Axis.Horizontal then ApplyOffsets(tmpR.Left,tmpR.Right)
                                else ApplyOffsets(tmpR.Bottom,tmpR.Top);

          Axis.AdjustMaxMinRect(tmpR);

          Axis.CalcRoundScales;

          if tmpHasOffsets then
          with Axis do
               FPosTitle:=InflateAxisPos(FPosLabels,SizeLabels);
    [b]    end;// end added by dns[/b]
      end;

Code: Select all

Procedure TChartAxis.AdjustMaxMinRect(Const Rect:TRect);
var tmpMin : Double;
    tmpMax : Double;

  Procedure RecalcAdjustedMinMax(Pos1,Pos2:Integer);
  var OldStart : Integer;
      OldEnd   : Integer;
  Begin
    OldStart :=IStartPos;
    OldEnd   :=IEndPos;
    Inc(IStartPos,Pos1);
    Dec(IEndPos,Pos2);

    IAxisSize:=IEndPos-IStartPos;

    tmpMin:=CalcPosPoint(OldStart);
    tmpMax:=CalcPosPoint(OldEnd);
  end;

Begin
[b]  // added by dns
  if (rect.Left=0) and (rect.Top=0) and (rect.right=0) and (rect.Bottom=0) then
    exit;[/b]

  with Rect do
  if Horizontal then ReCalcAdjustedMinMax(Left,Right)
                else ReCalcAdjustedMinMax(Top,Bottom);

  InternalCalcPositions;

  IMaximum:=tmpMax;
  IMinimum:=tmpMin;

  if IMinimum>IMaximum then
     SwapDouble(IMinimum,IMaximum);

  InternalCalcRange;
end;

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Re: TeEngine.InternalDraw.ApplyMaxMinOffsets in conjuction with

Post by Narcís » Tue May 04, 2010 2:02 pm

Hi davidnovo,

Thank you very much for your valuable feedback :!:

Could you please attach a simple example project we can run "as-is" to reproduce the circumstances you describe? We will then analize your code modifications and consider them for inclusion.

Thanks in advance.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

davidnovo
Newbie
Newbie
Posts: 15
Joined: Mon Nov 30, 2009 12:00 am

Re: TeEngine.InternalDraw.ApplyMaxMinOffsets in conjuction with

Post by davidnovo » Tue May 04, 2010 3:16 pm

Its very difficult to reproduce, as teh chart has to be exactly the correct size that when rounding from pixel coordinate back to real value in Axis.AdjustMaxMinRect.RecalcAdjustedMinMax that the IMinimum becomes slightly greater than FMinimum, then try to pass FMinimum back in OnGetNextAxisLabel as the next label value. I will try to do it with a simple application. I found it primarily by luck in a much more complicated application.

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Re: TeEngine.InternalDraw.ApplyMaxMinOffsets in conjuction with

Post by Narcís » Fri May 07, 2010 2:02 pm

Hi davidnovo,

It would be really helpful. If you can find a consistent way to reproduce the issue we will be very interested in knowing it and checking if your code modifications help solving it.

Thanks in advance.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

davidnovo
Newbie
Newbie
Posts: 15
Joined: Mon Nov 30, 2009 12:00 am

Re: TeEngine.InternalDraw.ApplyMaxMinOffsets in conjuction with

Post by davidnovo » Fri May 07, 2010 2:27 pm

Hello,

They absolutely do help, because it fixed my problem :-) I am just wondering if that could cause other problems.

To reproduce, I would just set up a chart where the # of pixels of the axis is not equally divisible by the axis range. You have to find a size where the start pixel returns a value slightly greater than FMinimum. Then, in OnGetNextAxisLabel, you just return FMinimum as the starting label.

I am not sure when I will have time to try and set this up, but I will try.

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Re: TeEngine.InternalDraw.ApplyMaxMinOffsets in conjuction with

Post by Narcís » Mon May 10, 2010 9:31 am

Hi davidnovo,

Thanks for your feedback. Ok, using code below I get a chart similar to what you described. Am I in the right way? However, it's unclear to me what I should do in the OnGetNextAxisLabel event. Can you please elaborate on that?

Code: Select all

uses Series;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Chart1.Width:=800;
  Chart1.Height:=600;

  Chart1.AddSeries(TLineSeries.Create(Self));
  Chart1[0].FillSampleValues;

  Chart1.Draw;
end;

procedure TForm1.Chart1GetNextAxisLabel(Sender: TChartAxis;
  LabelIndex: Integer; var LabelValue: Double; var Stop: Boolean);
begin
  if Sender = Chart1.Axes.Bottom then
  begin
    LabelValue:=Sender.Minimum;
  end;
end;

procedure TForm1.Chart1AfterDraw(Sender: TObject);
var range: Double;
    length: Integer;
    division: Double;
begin
  range:=Chart1.Axes.Bottom.Maximum - Chart1.Axes.Bottom.Minimum;
  length:=Chart1.Axes.Bottom.IAxisSize;
  division:=length/range;

  With Chart1.Title.Text do
  begin
    Clear;
    Add('Axis length: ' + IntToStr(length));
    Add('Axis range: ' + FloatToStr(range));
    Add('Axis length/range: ' + FloatToStr(division));
  end;
end;
Thanks in advance.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

dave novo
Newbie
Newbie
Posts: 25
Joined: Tue Oct 23, 2007 12:00 am

Re: TeEngine.InternalDraw.ApplyMaxMinOffsets in conjuction with

Post by dave novo » Tue May 18, 2010 6:56 pm

Hi Narcis,

That is exactly correct. When you pass back the label value as sender.Minimum, it checks to make sure the value that you passed back was >Iminimum or else it stops drawing the labels. the problem I has was that sender.minumum was 0.0 but IMimimum was 0.02 because AdjustMaxMinRect was being called with (0,0,0,0). If you look at AdjustMaxMinRect, it calls RecalcAdjustMinMax with (0,0) in this case which calls calcPosPoint. CalcPosPoint seems to be returning a rounded value. So even though the AdjustMaxMinRect was being called with (0,0,0,0) the IMinimum was being returned slightly differently from what it was before and returning sender.Minimum from GetNextLabelValue was stopping all the rest of teh labels from being drawn because sender.Minimum<sender.IMinimum

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Re: TeEngine.InternalDraw.ApplyMaxMinOffsets in conjuction with

Post by Narcís » Wed May 19, 2010 10:17 am

Hi dave,

Thanks for the info. Does this solve the problem for you or what I should do to get IMinium=0.02? I have debugged code above and I get IMinimum=0.

Thanks in advance.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

dave novo
Newbie
Newbie
Posts: 25
Joined: Tue Oct 23, 2007 12:00 am

Re: TeEngine.InternalDraw.ApplyMaxMinOffsets in conjuction with

Post by dave novo » Wed May 19, 2010 7:00 pm

Hello.

I did not debug into CalcPosPoint to see under what conditions it rounds to a different value than IMinimum. The problem was fixed for me by not calling ApplyOffsets if the offsets were (0,0). I do not know how to recreate an exact example where CalcPosPoint returns a slightly different IMinimum than the FMinimum :D. Best I can do is what I have done, is walk you through the code path, so you can see that it is potentially possible if CalcPosPoint returns a slightly different value ....

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Re: TeEngine.InternalDraw.ApplyMaxMinOffsets in conjuction with

Post by Narcís » Thu May 20, 2010 8:33 am

Hi dave,

The only place where I think this can occur is in CalcPosPoint, at this line:

Code: Select all

    tmp:=tmp*IRange/IAxisSize;
And the option for this occurring I guess is very specific to certain chart and/or axis dimensions and possibly a combination of certain values. Could you export problematic chart into a *.tee file so that we can load and debug it here?

Thanks in advance.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Post Reply