Recent

Author Topic: Double logarithmic graph not correct  (Read 539 times)

Firebird

  • New Member
  • *
  • Posts: 11
Double logarithmic graph not correct
« on: October 30, 2022, 09:09:47 pm »
I am generating a double logarithmic graph. The graph comes out wrong (see screenshot). The x axis should have only 1 main interval from 1000 to 10000. However, the graph shows 2 intervals: [1000, 3000], [3000, 10000].
How can I avoid that?
BTW: When I enter data with a span from 1000 to 100000
on the x axis, then the resulting 2 intervals [1000, 10000] and [10000, 100000] are properly displayed on the x axis.

wp

  • Hero Member
  • *****
  • Posts: 10644
Re: Double logarithmic graph not correct
« Reply #1 on: October 30, 2022, 11:17:37 pm »
TAChart's axis label selection is sometimes hard to control... If you have specific requirements it is sometimes better to add a TListChartSource, store in it the values at which labels should appear and link this to the Axis.Marks.Source.

Study the attached sample.

Firebird

  • New Member
  • *
  • Posts: 11
Re: Double logarithmic graph not correct
« Reply #2 on: October 31, 2022, 09:27:05 am »
Thank you very much WP, this way it works very well!

wp

  • Hero Member
  • *****
  • Posts: 10644
Re: Double logarithmic graph not correct
« Reply #3 on: November 06, 2022, 07:25:12 pm »
Just committed a new version of TAChart to Laz/main which has a new option "aipInteger" for Axis.Intervals.Options. It forces the labeling algorithm to select only integer labels. Applied to logarithmic charts this means that labels can be forced to be at integer values of the logs of the axis units, i.e. at the powers of 10. Thus, the original issue of this post can be solved easier now: Simply add the options aipInteger and aipGraphCoords to the axes' Intervals.Options. See attached project.

The new code is in the main branch of the Lazarus repository. But I think it is not difficult to add this also to older versions:
  • Make a backup copy of the files TACustomSource.pas and TAIntervalSources.pas in folder components/tachart of your Lazarus installation.
  • Open the file TACustomSource.pas, find the declaration of the type TAxisIntervalParamOption (near the top) and add "aipInteger" to the list. The declaration should look like this finally:
Code: Pascal  [Select][+][-]
  1. type
  2.   TAxisIntervalParamOption = (
  3.     aipGraphCoords,
  4.     aipUseCount, aipUseMaxLength, aipUseMinLength, aipUseNiceSteps,
  5.     aipInteger);  
  • Open the file TAIntervalSources and find the procedure TIntervalChartSource.CalculateIntervals. Replace the body of the procedure by the following code (or add the highlighted lines):
Code: Pascal  [Select][+][-]
  1. procedure TIntervalChartSource.CalculateIntervals(
  2.   AParams: TValuesInRangeParams; out ABestStart, ABestStep: Double);
  3. [...]
  4. begin
  5.   CalcMinMaxCount(minCount, maxCount);
  6.   bestCount := 0;
  7.   if aipInteger in Params.Options then begin
  8.     ABestStart := Int(AParams.FMin);
  9.     ABestStep := 1.0;
  10.     bestCount := Round(AParams.FMax) - round(ABestStart);
  11.     if bestCount <= maxCount then
  12.       exit;
  13.   end;
  14.   if aipUseNiceSteps in Params.Options then begin
  15.     s := AParams.CountToStep(minCount)  * 10;
  16.     while s >= Max(AParams.CountToStep(maxCount), AParams.FMinStep) do begin
  17.       for sv in Params.StepValues do
  18.         TryStep(s * sv, bestCount);
  19.       // We are not required to pick the best count, so any one will do.
  20.       if not (aipUseCount in Params.Options) and (bestCount > 0) then break;
  21.       s *= 0.1;
  22.     end;
  23.   end;
  24.   if (aipInteger in Params.Options) and (bestCount > maxCount) then
  25.     bestCount := 0;
  26.   if bestCount > 0 then
  27.     exit;
  28.   // Either nice steps were not required, or we failed to find one.
  29.   if aipUseCount in Params.Options then
  30.     bestCount := EnsureRange(Params.Count, minCount, maxCount)
  31.   else
  32.     bestCount := minCount;
  33.   ABestStep := (AParams.FMax - AParams.FMin) / bestCount;
  34.   ABestStart := AParams.FMin - ABestStep;
  35. end;
  • Rebuild the IDE: "Tools" > "Build Lazarus with profile...". After a while, when Lazarus restarts, you can use the new feature.

 

TinyPortal © 2005-2018