Recent

Author Topic: [SOLVED] Logarithmic scale in TAChart  (Read 3320 times)

prema

  • New Member
  • *
  • Posts: 14
[SOLVED] Logarithmic scale in TAChart
« on: March 07, 2017, 11:44:55 am »
Hello there,
I just tried to use the logarithmic scale on Y axis for one of my project. In the design-time the setting of the transformation works quite fine. I see the changes on the axis. But when I load the data and then turn on logarithmic scale I get error saying Floating Point Overload.
In attachment you will find simple test with code. What I do wrong?
Thanks for help
With best regards
Premek
« Last Edit: March 07, 2017, 12:30:45 pm by prema »

prema

  • New Member
  • *
  • Posts: 14
Re: [SOLVED] Logarithmic scale in TAChart
« Reply #1 on: March 07, 2017, 12:31:24 pm »
My mistake. It was not completely clear to me. Each serie in the chart have to have parameter AxisIndexX and AxisIndexY adjusted (default is -1) when you want to use the transformational. So it works now.   ;)

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: Logarithmic scale in TAChart
« Reply #2 on: March 07, 2017, 01:32:03 pm »
You seem to be using CodeTyphoon, I don't know what PilotLogic changed with TAChart. So my answer may be wrong...

What is missing in the logics of your sample is that the series does not "know" on which axes its data are plotted. TAChart supports several axes, and therefore this information is mandatory if transformations are involved. I think, in your case the y axis did not have data and thus tries to plot its default range from -1 to +1 on log scale -- of course, this fails because the logarithm of negative values cannot be calculated.

So, what you must do is to set the AxisIndexY of the line series to the index of the left axis (0 by default). After this modification your program runs without an error.

You may not be happy with the labels, though, I guess. There are several parameters to control label formation, they are grouped in the property Intervals of each axis. The most important parameter in relation to log plots is the option aipGraphcoords which must be ON. The next important one is Tolerance which often must be increased slightly to correctly handle rounding errors from the log numbers to pixels. Checking aipGraphCoords and setting Tolerance to 1 results in some more or less decent labels. You may want to play with the parameters to improve the label positioning. But be warned: some of the gray hair on my head is due to this feature.

If you want a "classical" log scale with marks at the powers of 10 and minor ticks at 2, 3, ... 8, 9 you must add a TListChartSource which you link to the LeftAxis.Marks.Source if the axis transformation is active. You must execute some code to add the correct labels to the chartsource. And you must add code to activate this user-provided labels in case of the log scale, but to keep the automatic built-in label generation in case of lin scale. You must also take care of the user zooming into the chart. For the minor ticks you add a MinorAxis by clicking at "..." next to the "Minors" of the LeftAxis. Turn off the Grid of the minor axis.

All the runtim code is handled here - it assumes that there is a TListChartSource named "LabelsSource"), and that the LeftAxis has a Minor axis.

Code: Pascal  [Select][+][-]
  1. procedure TfrmMain.cbLogChange(Sender: Tobject);
  2. begin
  3.   AxisTransformLog.Enabled := cbLog.Checked;
  4.   if cbLog.Checked then begin
  5.     if chMain.IsZoomed then begin
  6.       with chMain.LeftAxis.Intervals do begin
  7.         Options := Options + [aipGraphCoords];
  8.         Tolerance := 3;
  9.       end;
  10.       chMain.LeftAxis.Marks.Source := nil;
  11.       chMain.LeftAxis.Minors[0].Intervals.Count := 4;
  12.       chMain.LeftAxis.Minors[0].Intervals.Options := [aipUseCount];
  13.     end else begin
  14.       if LabelsSource.Count = 0 then PopulateAxisLabels;
  15.       chMain.LeftAxis.Marks.Source := LabelsSource;
  16.       chMain.LeftAxis.Minors[0].Intervals.Count := 9;
  17.       chMain.LeftAxis.Minors[0].Intervals.Options := [aipUseCount];
  18.     end;
  19.   end else begin
  20.     chMain.LeftAxis.Marks.Source := nil;
  21.     chMain.LeftAxis.Minors[0].Intervals.Count := 4;
  22.     chMain.LeftAxis.Minors[0].Intervals.Options := [aipUseCount];
  23.   end;
  24. end;
  25.  
  26. procedure TfrmMain.chMainExtentChanged(ASender: TChart);
  27. begin
  28.   cbLogChange(nil);
  29. end;
  30.  
  31. procedure TfrmMain.PopulateAxisLabels;
  32. var
  33.   x: Double;
  34. begin
  35.   x := 1e-6;
  36.   LabelsSource.Clear;
  37.   while (x <= 1e6) do begin
  38.     LabelsSource.Add(x, x);
  39.     x := x * 10;
  40.   end;
  41. end;

 

TinyPortal © 2005-2018