Lazarus

Programming => General => Topic started by: ronhud on September 11, 2018, 12:30:25 pm

Title: multipane controlling logical extent
Post by: ronhud on September 11, 2018, 12:30:25 pm
I have a database TAChart with two panes.   the bottom axis is a Date common to both panes.  The two left axis use different fields.   I set the logical extent for the bottom axis to the last 5% of the data.   The y axis of both panes is being automatically set to the lowest and highest values of the full extent of the data returned by the Query accessing the database - I would like to set them to the highest and lowest values of just the data displayed and have this adjust when panning.   I am using an axistransformation for each pane.  Any help will be appreciated.
Title: Re: multipane controlling logical extent
Post by: wp on September 11, 2018, 07:06:00 pm
Assuming that I understand the question correctly I'd propose to hook into the OnExtentChanging event of the chart and recalculate the y extent based on the datapoints inside the visible x extent:

Code: Pascal  [Select][+][-]
  1. uses
  2.   Math, TAChartUtils, TACustomSeries;
  3.  
  4. procedure TForm1.Chart1ExtentChanging(ASender: TChart);
  5. var
  6.   ext: TDoubleRect;
  7.   i, j: Integer;
  8.   ymin, ymax: Double;
  9.   ser: TChartSeries;
  10.   x, y: Double;
  11. begin
  12.   ext := Chart1.LogicalExtent;
  13.   // Find minimum and maximum y value of all series values for which the data points
  14.   // have an x value in the visible x extent.
  15.   // Convert to graph coordinates because they are needed by the chart's extent.
  16.   ymin := 1E308;
  17.   ymax := -1E308;
  18.   for i:=0 to Chart1.Series.Count-1 do
  19.     if Chart1.Series[i] is TChartSeries then begin
  20.       ser := TChartSeries(Chart1.Series[i]);
  21.       for j:=0 to ser.Count-1 do begin
  22.         x := ser.AxisToGraphX(ser.XValue[j]);
  23.         if InRange(x, ext.a.x, ext.b.x) then begin
  24.           y := ser.AxisToGraphY(ser.YValue[j]);
  25.           ymin := Min(ymin, y);
  26.           ymax := Max(ymax, y);
  27.         end;
  28.       end;
  29.     end;
  30.   ext.a.y := ymin;
  31.   ext.b.y := ymax;
  32.   Chart1.LogicalExtent := ext;
  33. end;

Note that this code converts the data values from "axis units" to "graph units". "Axis" coordinates are the values of your data, "graph" coordinates are the hidden coordinates defined by the axis transformations. This is necessary because the chart's extents are always in "graph" units. This way the effect of the axis transformation is considered correctly.
Title: Re: multipane controlling logical extent
Post by: ronhud on September 11, 2018, 08:25:49 pm
That is what I need - thanks.   I could'nt see how to get the values just for the pane and had not thought of using the x graph coordinates.
Title: Re: multipane controlling logical extent
Post by: ronhud on September 12, 2018, 01:19:13 pm
This sets the chart logical extent but having 2 panes does not seem to work.  I have tried to find some approach that would work but I guess I will have to display 2 separate charts.
Title: Re: multipane controlling logical extent
Post by: wp on September 12, 2018, 04:01:39 pm
Sorry. If I would not have been so lazy to test the paned chart I would not have given you incorrect information.

I am not saying that it is not possible to autoscale the paned charts, but it is definitely more work than using two separate charts. You should add a TChartExtentLink to keep the x axes in sync. Look at the attached demo. There are severl "tricks" in this project:

Title: Re: multipane controlling logical extent
Post by: ronhud on September 14, 2018, 02:39:29 pm
Thanks again.  I have used your two charts code and it looks as good as the two panes version - in fact I prefer it..   I am going to open another question under the heading 'extracting part of a Delphi5 dfm' .   I worked with Delphi5 for several years including post retirement but when I installed Windows 10 on my 32 bit pc the Delphi IDE started to jumble its own screens frequently and would freeze.     I was very glad to find the Lazarus open solution to working in Pascal with such valuable support. 
TinyPortal © 2005-2018