Recent

Author Topic: Can I get the position and size of an axis title?  (Read 5657 times)

CM630

  • Hero Member
  • *****
  • Posts: 1703
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Can I get the position and size of an axis title?
« Reply #15 on: April 21, 2026, 07:29:22 am »
Indeed, inversion works with Transformations.
But it occurs that GetIndexOfFirstVisibleMark returns a wrong result when a transformation with .Scale ≠ |1|.

Code: Pascal  [Select][+][-]
  1. ...
  2. procedure TForm1.Button1Click(Sender:TObject);
  3. begin
  4.   ChartAxisTransformations1LinearAxisTransform1.Scale := 1; //Returns 1, as it should
  5.   Chart1.Invalidate;
  6.   Application.ProcessMessages;
  7.   ShowMessage (IntToStr(  Chart1.BottomAxis.GetIndexOfFirstVisibleMark));
  8. end;
  9.  
  10. procedure TForm1.Button2Click(Sender:TObject);
  11. begin
  12.   ChartAxisTransformations1LinearAxisTransform1.Scale := 0.1;
  13.   Chart1.Invalidate;
  14.   Application.ProcessMessages ;
  15.   ShowMessage (IntToStr(Chart1.BottomAxis.GetIndexOfFirstVisibleMark)); //Returns 6 instead of 1
  16. end;
  17.  
  18. ...
  19.  
  20.  
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

CM630

  • Hero Member
  • *****
  • Posts: 1703
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Can I get the position and size of an axis title?
« Reply #16 on: May 11, 2026, 03:31:19 pm »
Some changes in TAChartAxis seem to make things better:

Code: Pascal  [Select][+][-]
  1. function TChartAxis.GetIndexOfFirstVisibleMark(aOffset: double = 0; aScale: double=1): Integer;
  2. var
  3.   coord: Integer;
  4. begin
  5.   for Result := 0 to High(FMarkValues) do begin
  6.     coord := FHelper.GraphToImage(FMarkValues[Result].FValue*aScale + aOffset);
  7.     if FHelper.IsInClipRange(coord) then
  8.       exit;
  9.   end;
  10.   Result := -1;
  11. end;
  12.  
  13. function TChartAxis.GetIndexOfLastVisibleMark(aOffset: double = 0; aScale: double=1): Integer;
  14. var
  15.   coord: Integer;
  16. begin
  17.   for Result := High(FMarkValues) downto 0 do begin
  18.     coord := FHelper.GraphToImage(FMarkValues[Result].FValue*aScale + aOffset);
  19.     if FHelper.IsInClipRange(coord) then
  20.       exit;
  21.   end;
  22.   Result := -1;
  23. end;    

Usage:
Code: Pascal  [Select][+][-]
  1.   ShowMessage (IntToStr(Chart1.BottomAxis.GetIndexOfFirstVisibleMark(ChartAxisTransformations1LinearAxisTransform1.Offset,ChartAxisTransformations1LinearAxisTransform1.Scale)));
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

CM630

  • Hero Member
  • *****
  • Posts: 1703
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Can I get the position and size of an axis title?
« Reply #17 on: May 12, 2026, 08:38:48 am »
This should be even better:

Code: Pascal  [Select][+][-]
  1. function TChartAxis.GetIndexOfFirstVisibleMark: Integer;
  2. var
  3.   coord: Integer;
  4.   mScale : double = 1;
  5.   mOffset : double = 0;
  6.   i: integer = 0;
  7. begin
  8.   if (FTransformations <> Nil) and (FTransformations.List.Count >0)  then
  9.   begin
  10.     for i:=0 to FTransformations.List.Count - 1 do
  11.       if ((TObject(Transformations.List.Items[i]) is TLinearAxisTransform)) and (TLinearAxisTransform(Transformations.List.Items[i]).Enabled = True) then
  12.       begin
  13.         mScale := mScale * TLinearAxisTransform(Transformations.List.Items[i]).Scale;
  14.         mOffset := mOffset * TLinearAxisTransform(Transformations.List.Items[i]).Scale + TLinearAxisTransform(Transformations.List.Items[i]).Offset;
  15.       end;
  16.   end;
  17.  
  18.   for Result := 0 to High(FMarkValues) do begin
  19.     coord := FHelper.GraphToImage(FMarkValues[Result].FValue*mScale + mOffset);
  20.     if FHelper.IsInClipRange(coord) then
  21.       exit;
  22.   end;
  23.   Result := -1;
  24. end;
  25.  
  26. function TChartAxis.GetIndexOfLastVisibleMark: Integer;
  27. var
  28.   coord: Integer;
  29.   mScale : double = 1;
  30.   mOffset : double = 0;
  31.   i: integer = 0;
  32. begin
  33.   if (FTransformations <> Nil) and (FTransformations.List.Count >0)  then
  34.   begin
  35.     for i:=0 to FTransformations.List.Count - 1 do
  36.       if ((TObject(Transformations.List.Items[i]) is TLinearAxisTransform)) and (TLinearAxisTransform(Transformations.List.Items[i]).Enabled = True) then
  37.       begin
  38.         mScale := mScale * TLinearAxisTransform(Transformations.List.Items[i]).Scale;
  39.         mOffset := mOffset * TLinearAxisTransform(Transformations.List.Items[i]).Scale + TLinearAxisTransform(Transformations.List.Items[i]).Offset;
  40.       end;
  41.   end;
  42.  
  43.   for Result := High(FMarkValues) downto 0 do begin
  44.     coord := FHelper.GraphToImage(FMarkValues[Result].FValue * mScale + mOffset);
  45.     if FHelper.IsInClipRange(coord) then
  46.       exit;
  47.   end;
  48.   Result := -1;
  49. end;  
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13584
Re: Can I get the position and size of an axis title?
« Reply #18 on: May 13, 2026, 12:05:48 am »
Please check out the new version of TChartAxis.GetIndexOfFirst/LastVisibleAxisMark in the Laz/main repository. The issue was that the indices were searched by conversion of the label values from graph to image coordinates, but this is correct only when no axis transform is involved because label values always are in axis coordinates - the conversion from axis to graph coordinates was missing in my old code. The full combination of all involved axis transformations, in the correct order, can be found from the GetTransform method of the axis.

In the attachment you can find a small project which combines a logarithmic and a linear (inverting) axis transformation (it works correctly only with the new TAChart revision).

CM630

  • Hero Member
  • *****
  • Posts: 1703
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Can I get the position and size of an axis title?
« Reply #19 on: May 13, 2026, 07:59:53 am »
Thanks!
The snippet worked fine for me, except that something seemed to be wrong with the project so I opened the form manually.
I expanded it a little, adding Cumulative something (I doubt that I will ever use that, maybe someone else will need it, since it is there), and there is an issue with it, as shown on the image attached.
The extended snippet is also attached.
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13584
Re: Can I get the position and size of an axis title?
« Reply #20 on: May 13, 2026, 11:26:26 am »
TCumulNormDistrAxisTransform is a special transformation for statistical probability data which expands values from the range 0...1 to the range -INF...+INF in a way to linearize a cumulative normal distribution. Due to the transformed negative numbers it cannot be combined with a logarithmic transform. Or, if the log transform would be executed first, the CumulNormDistrTransform would get values outside its domain again (e.g. log(0.001) = -3). In any case, these two transformations cannot be combined in general.

To support the TCumulNormDistrAxisTransform I changed the plotted function to a sigmoid function y= 1/(1+exp(-x)) which ranges between 0 and 1 as required. This transformation results in a highly non-linear density of axis labels, and thus I had to adjust the Axis.Intervals parameters for it.

To see the effect of an AutoScaleTransform I added a second y axis and assigned the function y=x to it.

Unfortunately there were still some bugs in the index finder, for example when the suggested label was outside the range of the transformation. Fixed in new revision.

CM630

  • Hero Member
  • *****
  • Posts: 1703
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Can I get the position and size of an axis title?
« Reply #21 on: May 14, 2026, 10:16:48 am »
GetIndexOfLastVisibleMark returns the mark with the higher value, not the rightmost/topmost. So when the axis is inverted, it returns the leftmost value, not the rightmost. The same with GetIndexOfFirstVisibleMark. I am not sure if this is the intended behaviour, just to make sure.

I could not understand what you have done in that example, but I cannot change the parameters of the transformations during runtime.
So here is what I did (maybe rather funny than useful):

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs,StdCtrls,
  9.   Types, math,
  10.   TAGraph,TASeries,TATools,TATransformations, TAChartAxis, TACustomSource;
  11.  
  12. type
  13.  
  14.   { TForm1 }
  15.  
  16.   TForm1 = class(TForm)
  17.     Button1:TButton;
  18.     Chart1:TChart;
  19.     Chart1LineSeries1:TLineSeries;
  20.     Chart1LineSeries2:TLineSeries;
  21.     ChartAxisTransformationsBottom:TChartAxisTransformations;
  22.     AutoBottom:TAutoScaleAxisTransform;
  23.     AutoLeft:TAutoScaleAxisTransform;
  24.     CumuBottom:TCumulNormDistrAxisTransform;
  25.     CumulLeft:TCumulNormDistrAxisTransform;
  26.     LogarithmBottom:TLogarithmAxisTransform;
  27.     LogarithmLeft:TLogarithmAxisTransform;
  28.     LinearBottom:TLinearAxisTransform;
  29.     ChartAxisTransformationsLeft:TChartAxisTransformations;
  30.     LinearLeft:TLinearAxisTransform;
  31.     procedure Button1Click(Sender:TObject);
  32.     procedure FormCreate(Sender:TObject);
  33.   private
  34.  
  35.   public
  36.  
  37.   end;
  38.  
  39. var
  40.   Form1: TForm1;
  41.  
  42. implementation
  43.  
  44. {$R *.lfm}
  45.  
  46. { TForm1 }
  47.  
  48.  
  49. procedure HighlightFirstAndLastAxisLabels(Axis: TChartAxis);
  50.  
  51.   procedure DrawLabelBorder(AIndex: Integer; AColor: TColor);
  52.   var
  53.     R: TRect;
  54.     vt: TChartValueText;
  55.   begin
  56.     if AIndex = -1 then
  57.       exit;
  58.     vt := Axis.Value[AIndex];
  59.     if Length(vt.FPolygon) = 0 then
  60.       exit;
  61.     R.TopLeft := vt.FPolygon[0];
  62.     R.BottomRight := vt.FPolygon[2];
  63.     Types.InflateRect(R, 4, 2);
  64.  
  65.     Axis.Drawer.SetPenParams(psSolid, AColor);
  66.     Axis.Drawer.Rectangle(R);
  67.   end;
  68.  
  69. begin
  70.   Axis.Drawer.SetBrushParams(bsClear, clNone);
  71.   // Find first label which is on the axis and mark it by a green border
  72.   DrawLabelBorder(Axis.GetIndexOfFirstVisibleMark, clLime);
  73.   // Find last label which is on the axis and mark it by a red border
  74.   DrawLabelBorder(Axis.GetIndexOfLastVisibleMark, clRed);
  75. end;
  76.  
  77. procedure TForm1.FormCreate(Sender: TObject);
  78. var
  79.   i: Integer;
  80.   x, y: Double;
  81. begin
  82.   for i := -100 to 100 do
  83.   begin
  84.     x := i / 10;
  85.     y := 1.0 / (1.0 + exp(-x));
  86.     Chart1LineSeries1.AddXY(x, y);
  87.     Chart1LineSeries2.AddXY(x, x);
  88.   end;
  89. end;
  90.  
  91. procedure TForm1.Button1Click(Sender:TObject);
  92. begin
  93.   Randomize;
  94.   LinearLeft.Enabled :=  RandomRange(0, 2) = 1;
  95.   LinearBottom.Enabled :=  RandomRange(0, 2) = 1;
  96.   LogarithmLeft.Enabled :=  RandomRange(0, 2) = 1;
  97.   LogarithmBottom.Enabled :=  RandomRange(0, 2) = 1;
  98.   AutoLeft.Enabled :=  RandomRange(0, 2) = 1;
  99.   AutoBottom.Enabled :=  RandomRange(0, 2) = 1;
  100.   if not LogarithmLeft.Enabled  then
  101.     CumulLeft.Enabled  :=  RandomRange(0, 2) = 1;
  102.   if not LogarithmBottom.Enabled then
  103.     CumuBottom.Enabled :=  RandomRange(0, 2) = 1;
  104.  
  105.   LinearLeft.Scale := (Random(2) * 2 - 1) {plus or minus} * Random * (100 - 0.01) + 0.01;
  106.   LinearLeft.Offset := Random * (100 - 0.01) + 0.01;
  107.  
  108.   LinearBottom.Scale := (Random(2) * 2 - 1) {plus or minus} * Random * (100 - 0.01) + 0.01;
  109.   LinearBottom.Offset := Random * (100 - 0.01) + 0.01;
  110.   Chart1.Invalidate;
  111.   Application.ProcessMessages;
  112.   HighlightFirstAndLastAxisLabels (chart1.AxisList[0]);
  113.   HighlightFirstAndLastAxisLabels (chart1.AxisList[1]);
  114. end;
  115.  
  116. end.
  117.  
  118.  
As I did it gradually, I saw no issues, except the one I just mentioned.
I will see what will happen when I get to multiple axises...

Also, again, I had to open the .pas file manually, after adding the project (just FYI).
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13584
Re: Can I get the position and size of an axis title?
« Reply #22 on: May 14, 2026, 01:07:10 pm »
GetIndexOfLastVisibleMark returns the mark with the higher value, not the rightmost/topmost. So when the axis is inverted, it returns the leftmost value, not the rightmost. The same with GetIndexOfFirstVisibleMark. I am not sure if this is the intended behaviour, just to make sure.
Wasn't this your intention in one of the previous posts?

Also, again, I had to open the .pas file manually, after adding the project (just FYI).
This is because of a recent change in the Laz/main project file, I should save all projects with the option "Maximize compatibility of project files (lpi, lps)".

Code: Pascal  [Select][+][-]
  1.   if not LogarithmLeft.Enabled  then
  2.     CumulLeft.Enabled  :=  RandomRange(0, 2) = 1;
  3.   if not LogarithmBottom.Enabled then
  4.     CumuBottom.Enabled :=  RandomRange(0, 2) = 1;
  5.  
The cumulative normal distribution transform is very nitpicking on parameters. It only accepts input arguments in the range 0 ... 1. There normally combinations with any other transform in which this range is left can fail.

Code: Pascal  [Select][+][-]
  1.   LinearLeft.Scale := (Random(2) * 2 - 1) {plus or minus} * Random * (100 - 0.01) + 0.01;
  2.   LinearLeft.Offset := Random * (100 - 0.01) + 0.01;
  3.  
  4.   LinearBottom.Scale := (Random(2) * 2 - 1) {plus or minus} * Random * (100 - 0.01) + 0.01;
  5.   LinearBottom.Offset := Random * (100 - 0.01) + 0.01;
  6.  
Random linear transformation parameters together with a log transform? This will not work in general, because the log transform can only operate on positive numbers

I don't see what you want to prove with these experiments.


CM630

  • Hero Member
  • *****
  • Posts: 1703
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Can I get the position and size of an axis title?
« Reply #23 on: May 14, 2026, 02:37:08 pm »
GetIndexOfLastVisibleMark returns the mark with the higher value, not the rightmost/topmost. So when the axis is inverted, it returns the leftmost value, not the rightmost. The same with GetIndexOfFirstVisibleMark. I am not sure if this is the intended behaviour, just to make sure.
Wasn't this your intention in one of the previous posts?

We started from Inverted was not usable with more than one scale, so we went to using transformations, but GetIndexOfLast(First)VisibleMark were not working with transformations. At some place there was some mess and it if was not possible to tell if GetIndexOFirstVisibleMark is on the left or on the right and if it is linked to the minimum or the maximum value.
So let's leave things as they are for now and see when the path will go to...?

I don't see what you want to prove with these experiments.
When scale and offset vary, the number of marks varies too (sometimes there is one mark only). I just wanted to see if something goes wrong when the number of marks changes.
Personally I will not use anything except linear and log scale.
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

CM630

  • Hero Member
  • *****
  • Posts: 1703
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Can I get the position and size of an axis title?
« Reply #24 on: May 22, 2026, 03:10:59 pm »
Maybe some TRY is needed in TATransformations?
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13584
Re: Can I get the position and size of an axis title?
« Reply #25 on: May 22, 2026, 05:48:14 pm »
Can you try to provide a small sample project reproding the issue? Better than hide it by a silent try-except.

CM630

  • Hero Member
  • *****
  • Posts: 1703
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Can I get the position and size of an axis title?
« Reply #26 on: May 30, 2026, 11:59:11 am »
I will try do it next week. The entire project is public anyway, but it is also absolutely messy.
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

CM630

  • Hero Member
  • *****
  • Posts: 1703
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Can I get the position and size of an axis title?
« Reply #27 on: June 04, 2026, 12:39:28 pm »
So this is the code that crashes when the app is closed:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs,StdCtrls,TAGraph,TATools,TATransformations;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     procedure FormCreate(Sender:TObject);
  16.   private
  17.     Chart1 : TChart;
  18.     FAxisTransformations : array of TChartAxisTransformations;
  19.     FLinearAxisTransform : array of TLinearAxisTransform;
  20.     FLogarithmAxisTransform : array of TLogarithmAxisTransform;
  21.   public
  22.  
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TForm1 }
  33.  
  34. procedure TForm1.FormCreate(Sender:TObject);
  35. var
  36.   i: integer = 0;
  37. begin
  38.   Chart1 := TChart.Create(Self);
  39.   Chart1.Parent := Self;
  40.  
  41.   SetLength(FAxisTransformations,2); //A TAChart has 2 axises when created.
  42.   SetLength(FLogarithmAxisTransform,2);
  43.   SetLength(FLinearAxisTransform,2);
  44.  
  45.   for i := 0 to high(FAxisTransformations) do
  46.   begin
  47.     FAxisTransformations[i] := TChartAxisTransformations.Create(self);
  48.       FLinearAxisTransform[i] := TLinearAxisTransform.Create(FAxisTransformations[i]);
  49.       FLinearAxisTransform[i].Enabled := True;
  50.     FLogarithmAxisTransform[i] := TLogarithmAxisTransform.Create(FAxisTransformations[i]);
  51.       FLogarithmAxisTransform[i].Enabled := False;
  52.  
  53.     FAxisTransformations[i].List.Add(FLinearAxisTransform[i]);
  54.     FAxisTransformations[i].List.Add(FLogarithmAxisTransform[i]);
  55.   end;  //for i
  56.  
  57.  
  58.   FLinearAxisTransform[1].Scale := 0.01;
  59. end;
  60.  
  61. end.

But this code does not work anyway (FLinearAxisTransform[1].Scale := 0.01; is not applied).

On the other hand this code seems to works and so far it does not crash:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender:TObject);
  2. var
  3.   i: integer = 0;
  4. begin
  5.   Chart1 := TChart.Create(Self);
  6.   Chart1.Parent := Self;
  7.  
  8.   SetLength(FAxisTransformations,2); //A TAChart has 2 axises when created.
  9.   SetLength(FLogarithmAxisTransform,2);
  10.   SetLength(FLinearAxisTransform,2);
  11.  
  12.   for i:=0 to high (FAxisTransformations) do
  13.   begin
  14.     FAxisTransformations[i]     := TChartAxisTransformations.Create(Chart1);
  15.       FLinearAxisTransform[i]   := TLinearAxisTransform.Create(FAxisTransformations[i]);
  16.       FLinearAxisTransform[i].Transformations := FAxisTransformations[i];
  17.       FLinearAxisTransform[i].Enabled := True;
  18.  
  19.       FLogarithmAxisTransform[i] := TLogarithmAxisTransform.Create(FAxisTransformations[i]);
  20.       FLogarithmAxisTransform[i].Transformations := FAxisTransformations[i];
  21.       FLogarithmAxisTransform[i].Enabled := false;
  22.  
  23.       Chart1.AxisList[i].Transformations := FAxisTransformations[i];
  24.   end;
  25.  
  26.   FLinearAxisTransform[1].Scale := 0.01;
  27. end;  
  28.  

So maybe there is no issue here.

EDIT:
This code seems to work, but it crashes:

Code: Pascal  [Select][+][-]
  1.   for i := 0 to high(FAxisTransformations) do
  2.   begin
  3.     FAxisTransformations[i] := TChartAxisTransformations.Create(self);
  4.       FLinearAxisTransform[i] := TLinearAxisTransform.Create(FAxisTransformations[i]);
  5.       FLinearAxisTransform[i].Enabled := True;
  6.     FLogarithmAxisTransform[i] := TLogarithmAxisTransform.Create(FAxisTransformations[i]);
  7.       FLogarithmAxisTransform[i].Enabled := False;
  8.  
  9.     FAxisTransformations[i].List.Add(FLinearAxisTransform[i]);
  10.     FAxisTransformations[i].List.Add(FLogarithmAxisTransform[i]);
  11.  
  12.     Chart1.AxisList[i].Transformations := FAxisTransformations[i];
  13.   end;  //for i
« Last Edit: June 04, 2026, 12:44:36 pm by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13584
Re: Can I get the position and size of an axis title?
« Reply #28 on: June 04, 2026, 02:51:02 pm »
Yes, adding elements to collections or collection-like classes in TAChart is not always intuitive. I remember that I once wrote a wiki about it some years ago: https://wiki.lazarus.freepascal.org/TAChart_Runtime_FAQ#How_to_add_an_axis_transformation?

I think the problem with
Code: Pascal  [Select][+][-]
  1.     FAxisTransformations[i].List.Add(FLinearAxisTransform[i]);
  2.  
is that it does not set the Transformations element of the AxisTransform. This is done in the setter SetTransformations of TChartAxisTransform:
Code: Pascal  [Select][+][-]
  1. procedure TAxisTransform.SetTransformations(AValue: TChartAxisTransformations);
  2. begin
  3.    if FTransformations = AValue then exit;
  4.   if FTransformations  <> nil then
  5.     FTransformations.List.Remove(Self);
  6.   FTransformations := AValue;
  7.   if FTransformations <> nil then
  8.     FTransformations.List.Add(Self);
  9. end;
I really recommend to use the following code for adding elements to the ChartTransformations:
Code: Pascal  [Select][+][-]
  1.     FLinearAxisTransform[i].Transformations := FAxisTransformations[i];

CM630

  • Hero Member
  • *****
  • Posts: 1703
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Can I get the position and size of an axis title?
« Reply #29 on: June 10, 2026, 11:00:33 am »
I am trying to set the extents using transformations.

Code: Pascal  [Select][+][-]
  1. procedure SetAxisMinMax(aAxis: TChartAxis; aBottom_Left : Double; aTop_Right: Double);
  2. var
  3.   mExtents: TDoubleRect;
  4.   debdo : double = 0;
  5. begin
  6.   mExtents := TChart(TChartAxis(aAxis).GetChart).LogicalExtent;
  7.  
  8.   if (aAxis.Alignment = calTop) or (aAxis.Alignment = calBottom) then
  9.   begin //X axis
  10.     mExtents.coords[ord(ExtXmin)] := min(aBottom_Left,aTop_Right);
  11.     mExtents.coords[ord(ExtXmax)] := max(aBottom_Left,aTop_Right);
  12.   end
  13.   else
  14.   begin //Y axis
  15.     mExtents.coords[ord(ExtYmin)] := min(aBottom_Left,aTop_Right);
  16.     mExtents.coords[ord(ExtYmax)] := max(aBottom_Left,aTop_Right);
  17.  
  18. {    mExtents.coords[ord(ExtYmin)] := aBottom_Left;
  19.     mExtents.coords[ord(ExtYmax)] := aTop_Right;}
  20.   end;
  21.  
  22.   TChart(TChartAxis(aAxis).GetChart).LogicalExtent := mExtents;
  23.  
  24.   if (aAxis.Transformations = nil) or (aAxis.Transformations.List.Count = 0)
  25.     then exit;
  26.   if (aBottom_Left > aTop_Right) then
  27.   begin
  28.     debdo := TLinearAxisTransform(aAxis.Transformations.List[0]).Scale;
  29.     TLinearAxisTransform(aAxis.Transformations.List[0]).Scale := - abs(TLinearAxisTransform(aAxis.Transformations.List[0]).Scale);
  30.     debdo := TLinearAxisTransform(aAxis.Transformations.List[0]).Scale;
  31.     TLinearAxisTransform(aAxis.Transformations.List[0]).Enabled := true;
  32.   end;
  33.   TChart(TChartAxis(aAxis).GetChart).Invalidate;
  34.   TChart(TChartAxis(aAxis).GetChart).Update;
  35.   Application.ProcessMessages;
  36. end;  

The first time I execute  SetAxisMinMax(Chart1.LeftAxis,-1,-5); on the Y (left) scale I get Top= -1; Bottom = 1 (the scales are inverted, but the values are wrong).
The second time I execute the same I get Top= + 1; Bottom = +5. :o

I am doing something wrong?
« Last Edit: June 10, 2026, 11:02:38 am by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

 

TinyPortal © 2005-2018