Recent

Author Topic: Problems with extent Ymax < Ymin  (Read 30101 times)

CM630

  • Hero Member
  • *****
  • Posts: 1626
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Problems with extent Ymax < Ymin
« Reply #30 on: May 07, 2013, 03:27:19 pm »
I will examine this further, probably tomorrow, but it just occured to me that usings Extent.FixTo prevents panning in  TChartToolset  from working, while ZOOMing continues to work fine. Is it supposed to work this way?
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13361
Re: Problems with extent Ymax < Ymin
« Reply #31 on: May 07, 2013, 05:15:07 pm »
I don't see this here. Maybe you have set the LimitToExtent options of the panning tool?

CM630

  • Hero Member
  • *****
  • Posts: 1626
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Problems with extent Ymax < Ymin
« Reply #32 on: May 08, 2013, 08:04:49 am »
Indeed, that is the case. I had LimitTo left and right extents. When I removed it, panning started working!
Yet this did not solve my problem, since now I can pan outside the data area of the X scale.
I got the impression, that Extent.FixTo is to be used for setting LogicalExtents, but it occurs that it sets simply Extents.

I tried to replace chart.Extent.FixTo(Extents); with chart.LogicalExtent:= Extents;
but unfortunately it does not work properly (i.e. I set Ymax (coords[4]):= 1000, it sets it to 863,9213749832943), although all my margins are set to 0.
The only idea I have is to enable/disable LimitTo left and right if panning goes outside the values of the X scale or to force them back within the values area. This is quite a clumsy solution.

Here is my procedure:

Code: [Select]
procedure SetLogicalExtent (var Chart:  TChart;const  Value: double;const Index: byte);
var
  Extents: tDoubleRect;
  TempCoord:double;
  PlusMinus:integer=+1;
begin
  Extents:=Chart.LogicalExtent;
  if Index<3 then PlusMinus:=+1 else PlusMinus:=-1;
  if ((Index<3) and (Value<Extents.coords [Index+2])) or ((Index>2) and (Value>Extents.coords [Index-2]))
  then
  begin //Max > Min
     Extents.coords [Index]:= Value;
     if (Index= 1) or (Index=3) then chart.BottomAxis.Inverted:=False;
     if (Index= 2) or (Index=4) then chart.LeftAxis.Inverted:=False;
  end
  else
  begin //Min < Max
    TempCoord:=Extents.coords[Index+PlusMinus*2];
    Extents.coords[Index+PlusMinus*2]:=Value;
    Extents.coords[Index]:=TempCoord;
    if (Index=1) or (Index=3) then chart.BottomAxis.Inverted:=True;
    if (Index=2) or (Index=4) then chart.LeftAxis.Inverted:=True;
  end;
  chart.Extent.FixTo(Extents);  //Works fine this way
  //chart.LogicalExtent:= Extents; //Does not work this way
end; 


« Last Edit: May 08, 2013, 08:38:34 am by paskal »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13361
Re: Problems with extent Ymax < Ymin
« Reply #33 on: May 08, 2013, 05:54:02 pm »
I don't exactly understand what you want to achieve: Zoom and pan, but when zoomed you only want to pan vertically? The panning tools have a property Direction to restrict the panning. Did you try that?
« Last Edit: May 08, 2013, 06:31:37 pm by wp »

CM630

  • Hero Member
  • *****
  • Posts: 1626
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Problems with extent Ymax < Ymin
« Reply #34 on: May 13, 2013, 08:49:36 am »
When I pan/zoom horizonatlly, TAChart autoscales vertically.
This causes several issue:
1. Sometimes I do not want the contents to be autoscaled vertically, but TAChart does not have an option to disable, so I have to set extents.
2. Sometimes I want to autoscale vertically, but  TAChart does it in an unpleasant way, so I have to use my procedures.

I have uploaded a video in Youtube, for some reason it is extremely ugly, but I hope that you can get the idea.
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

CM630

  • Hero Member
  • *****
  • Posts: 1626
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Problems with extent Ymax < Ymin
« Reply #35 on: February 23, 2015, 03:45:12 pm »
Houston, we have a serious problem.
Here is the source:
Code: [Select]
procedure TForm1.FormCreate(Sender: TObject);
var
  TempExtents: TDoubleRect;
begin
  Chart1.Margins.Bottom:=0;
  Chart1.Margins.Left:=0;
  Chart1.Margins.Right:=0;
  Chart1.Margins.Top:=0;
  Chart1LineSeries1.AddXY (2, 3);
  Chart1LineSeries1.Pointer.Visible:=True;
  Chart1LineSeries1.Marks.Visible:=True;
  Chart1LineSeries1.ShowPoints:=True;
  Chart1LineSeries1.Marks.Style:=smsLabel;  //This causes problems
  Chart1LineSeries1.SetText(0,'aaaa');
  TempExtents.coords[1]:=-10;
  TempExtents.coords[2]:=-15;
  TempExtents.coords[3]:=+20;
  TempExtents.coords[4]:=+25;
  Chart1.Extent.FixTo   (TempExtents);
end;                                 
If line Chart1LineSeries1.Marks.Style:=smsLabel; is commented everything is fine and FixTo works properly.
But, when I enable it, FixTo does not work properly for the vertical scale. I set -15 to +25, but actual values are -15 to 31,...
If I have a negative point, the -15 will become -16 or something like this.
Is this a bug of if it is a feature, how am I to override it?





Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13361
Re: Problems with extent Ymax < Ymin
« Reply #36 on: February 23, 2015, 03:50:00 pm »
Please put your code into a compilable demo which I can test immediately - it makes my life easier... Put pas, lfm, lpi and lpr files of the demo into a single zip file which you can upload here, no other files please, in particular no exe and no ppu.

Anyway, your code is pretty much self-contained and it was easy to create a project...

I see the issue. Yes this is caused by the labels attached to the data points.The problem is that the labels are drawn ABOVE the data points. This chart does not take care of the positions where the data points are, it just makes additonal space for the labels. While this behavior makes sense in an auto-scaled chart it is unexpected for a chart with frozen extent. Therefore, I'll look into the sources of TAChart to find the issue.
« Last Edit: February 23, 2015, 03:59:40 pm by wp »

wp

  • Hero Member
  • *****
  • Posts: 13361
Re: Problems with extent Ymax < Ymin
« Reply #37 on: February 23, 2015, 04:13:01 pm »
Ah - nothing to do, it's already there: Series.Marks.AutoMargins = false

CM630

  • Hero Member
  • *****
  • Posts: 1626
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Problems with extent Ymax < Ymin
« Reply #38 on: February 24, 2015, 09:21:22 am »
Thanks, it works!
Now I am trying to handle with the problems caused by that:
 
The max must always be greater than the min. Use the property "Inverted" of the axis if you want to have min and max interchanged.
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13361
Re: Problems with extent Ymax < Ymin
« Reply #39 on: February 24, 2015, 10:46:26 am »
No, as is says: the max must ALWAYS be greater than the min. "Inverted" is intended to invert the drawing direction of an axis, there's nothing else to be done for this purpose. Never exchange max and min to invert the axis.

CM630

  • Hero Member
  • *****
  • Posts: 1626
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Problems with extent Ymax < Ymin
« Reply #40 on: February 26, 2015, 08:09:06 am »
I added some info in the wiki, hopefully it contains no mistakes.



No, as is says: the max must ALWAYS be greater than the min...
Yes, I understand how it works, I am just beating my head how to overcome the troubles that this behaviours creates  %) .


EDIT: Which exactly extents does FixTo set? I thought it sets LogicalExtents, but odd results occur?
« Last Edit: February 26, 2015, 08:25:58 am by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13361
Re: Problems with extent Ymax < Ymin
« Reply #41 on: February 26, 2015, 12:01:43 pm »
Quote from: CM630
Which exactly extents does FixTo set? I thought it sets LogicalExtents, but odd results occur?
The extent you apply it to: For the chart you can only call FixTo for the Chart.Extent which corresponds to the unzoomed window. When you zoom into the chart you modify the LogicalExtent, Or you can assign a DoubleRect to the LogicalExtent. And there is a CurrentExtent which is equal to the LogicalExtent plus the chart's margins translated to graph coordinates. A bit confusing...

Please have a look at the attached demo which plays with various ways to modify the extents and shows their effect.

CM630

  • Hero Member
  • *****
  • Posts: 1626
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Problems with extent Ymax < Ymin
« Reply #42 on: February 26, 2015, 03:22:43 pm »
I kind of solved my problems by adding an additional storage for the extents.
I use an additional function, which sets the extents, and if necessary swaps them and inverts the scales, but does not touch the additional storage. Still my control happens to crash, but I will dig more trough it.
I will check you demo, but if I understand you right, I'd better use LogicalExtents[1..4]:=something instead of FixToo.
But the odd thing is that I use FixTo, my minimum X scale is i.e. 1, but both LogicalExtemt.coords[1] and  CurrentExtemt.coords[1] return i.e. 3,xyz which in not even close neither to 1, nor to the other border :o I have no zoom, my chart margins are zeroes, I have no captions on the plot... I am not sure if I had a plot at all.
The bad things is that code is too big, to reproduce it in a simple way.
So as I mentioned I added an additional buffer for the coordinates and stopped reading logical exents, except when an OnChangeExtents event occurs.

Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13361
Re: Problems with extent Ymax < Ymin
« Reply #43 on: February 26, 2015, 04:33:25 pm »
I am pretty sure that you are doing something wrong.

The entire extent thing I must confess is a bit tricky because all the calculations are done during the painting procedure. So, if you initiate an extent change at the wrong place I could be overridden by the original calculation - just a feeling. This could explain why your LogicalExtent returns non-sense results.

Please try to create a simple application which shows the issue.

CM630

  • Hero Member
  • *****
  • Posts: 1626
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Problems with extent Ymax < Ymin
« Reply #44 on: February 27, 2015, 09:22:35 am »
These two functions shall provide the solution. I have made some standalone tests and they seem to be okay, I will report after some more usage:
Code: [Select]
uses
...TAChartUtils...
const
   ExtXmin=1;
   ExtYmin=2;
   ExtXmax=3;
   ExtYmax=4;
...

function  GetExtentsReal (var aChart: TChart): TDoubleRect;
var
  OutputExtents: TDoubleRect;
  SwapExtent: Double;
begin
   OutputExtents:= aChart.LogicalExtent;
   if aChart.BottomAxis.Inverted then
   begin
      SwapExtent:= OutputExtents.coords[ExtXmin];
      OutputExtents.coords[ExtXmin]:= OutputExtents.coords[ExtXmax];
      OutputExtents.coords[ExtXmax]:= SwapExtent;
   end;
   if aChart.LeftAxis.Inverted then
   begin
      SwapExtent:= OutputExtents.coords[ExtYmin];
      OutputExtents.coords[ExtYmin]:= OutputExtents.coords[ExtYmax];
      OutputExtents.coords[ExtYmax]:= SwapExtent;
   end;
   Result:= OutputExtents;
end;

function  SetExtentsReal (var aChart: TChart; aPosition: Integer; Value: Double): Boolean;
var
  OutputExtents: TDoubleRect;
  SwapExtent: Double;
begin
   Result:=False;
   OutputExtents:= GetExtentsReal(aChart);
   OutputExtents.coords[aPosition]:=Value;
   if (OutputExtents.coords[ExtXmin]= OutputExtents.coords[ExtXmax]) or (OutputExtents.coords[ExtYmin]= OutputExtents.coords[ExtYmax])
         then Exit;  //Function does nothing and returns False if equal extents exist.

   if (aPosition=ExtXmin) or (aPosition=ExtXmax) then
     if OutputExtents.coords[ExtXmin]> OutputExtents.coords[ExtXmax] then
        begin
          SwapExtent:= OutputExtents.coords[ExtXmin];
          OutputExtents.coords[ExtXmin]:= OutputExtents.coords[ExtXmax];
          OutputExtents.coords[ExtXmax]:= SwapExtent;
          aChart.BottomAxis.Inverted:=True;
        end
     else
        aChart.BottomAxis.Inverted:=False;

   if (aPosition=ExtYmin) or (aPosition=ExtYmax) then
     if OutputExtents.coords[ExtYmin]> OutputExtents.coords[ExtYmax] then
        begin
          SwapExtent:= OutputExtents.coords[ExtYmin];
          OutputExtents.coords[ExtYmin]:= OutputExtents.coords[ExtYmax];
          OutputExtents.coords[ExtYmax]:= SwapExtent;
          aChart.LeftAxis.Inverted:=True;
        end
     else
        aChart.LeftAxis.Inverted:=False;

   aChart.LogicalExtent:= OutputExtents;
   Result:=True;
end;
             
What I noticed is that when a Chart is put on a form, logical and current extents return nonsense if invoked in the procedure FormCreate procedure.
Should it be this way?
I get no exception, so the Chart is created. Probably some default values for the logical and current extents  are not set?
 
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

 

TinyPortal © 2005-2018