Recent

Author Topic: zooming and dragging by code  (Read 7641 times)

frederic

  • Full Member
  • ***
  • Posts: 226
zooming and dragging by code
« on: March 25, 2015, 12:50:19 pm »
wp

in the other thread "proper  xaxis'  we have defined a Xaxis minimum and an Xaxis maximum   . By zooming and dragging the area < X-axis min
and /or  > Xaxismax becomes visible .

I want to avoid that and i want to code following setup

I am in the Xzoom mode.When i zoom my mousewheelup then we unzoom .
When for instance a xaxis minimum is reached then there will be no zooming but a panning should start so that the xminimum is not there anymore.   
This means that with the next movement of the mousewheel a zoom step will be done . So panning and zooming will follow after each other; that should be part of the Xzoom operation.

The same setup can be used  for the Xaxismax
When you are in the panningmode this stepwise changing between zooming and panning can be used as well

This all needs panning and zooming ,now by coding

My question is
is this setup correct?
Has this been tried before ( it is rather universal)  or am i trying to re-invent the wheel again.

can i use the code from tatools for that without introducing other problems?

frederic

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: zooming and dragging by code
« Reply #1 on: March 25, 2015, 01:28:05 pm »
Just try, I don't know.

Chart tools do not fully prevent zooming/panning out of the data range (PanDragTool and PanClickTool: LimitToExtent). I would check the OnAfterXXXX events whether the full extent of the chart has been left and bring the extent back into the allowed range. Something like this (not tested...)

Code: [Select]
procedure TForm1.EnsureExtent;
// This procedure makes sure that no edge of the currently visible window ("LogicalExtent") can leave the window defined by the unzoomed/unpanned data range ("FullExtent")
var
  ext, fullext: TDoubleRect;
  delta: Double;
begin
  ext := Chart.LogicalExtent;
  fullext := Chart.GetFullExtent;
  if ext.a.x < fullext.a.x then begin
    delta := ext.b.x - ext.a.x;
    ext.a.x := fullext.a.x;
    ext.b.x := ext.a.x + delta;
  end;
  if ext.b.x > fullext.b.x then begin
    delta := ext.b.x - ext.a.x;
    ext.b.x := fullext.b.x;
    ext.a.x := ext.b.x - delta;
  end;
  // ... the same with the y coordinates...
  Chart.LogicalExtent := ext;
end;

procedure TForm1.MouseWheelZoomToolAfterMouseWheelUp(...);
begin
  // ... your code
  EnsureExtent;
end;
 

frederic

  • Full Member
  • ***
  • Posts: 226
Re: zooming and dragging by code
« Reply #2 on: March 25, 2015, 04:33:10 pm »
wp

Quote
I would check the OnAfterXXXX events whether
What did mean here?

your setup looked a lot less complicated then the mine

for panning it was oke. With zooming however you have to prevent that the correction of ,for instance the maxextent  ,stops long before you have a violation of the minextent .

the corrected code:
Code: [Select]
procedure TForm1.EnsureExtent;
// This procedure makes sure that no edge of the currently visible window ("LogicalExtent") can leave the window defined by the unzoomed/unpanned data range ("FullExtent")
var
  ext: TDoubleRect;
  delta, correctionstepsmin,correctionstepsmax:Double;
  Ffullext,fullwidth:double;
begin
  ext := Chart1.LogicalExtent;
  Ffullext := Chart1.GetFullExtent;
  fullwidth:= Ffullext.b.x  -   Ffullext.a.x ;

  if ext.a.x < Ffullext.a.x then begin
     delta := ext.b.x - ext.a.x;
     ext.a.x := Ffullext.a.x;
    if delta <fullwidth/4 then  // we correct till  we have an overshoot of1/4 the full size
    begin
      memo1.lines.add('minimum violateddelta > fullwidth/4 ') ;
      ext.b.x := Ffullext.a.x + delta;
    end ;//else correctminimum:=false;

  end ;
  if ext.b.x > Ffullext.b.x then begin
  delta := ext.b.x - ext.a.x;
  ext.b.x := Ffullext.b.x;
    if delta < fullwidth/4 then  // we correct till  we have an overshoot of 1/4 the full size
    begin
         memo1.lines.add('maximum violated delta< fullwidth/4') ;
        ext.a.x := Ffullext.b.x - delta;

    end;
  end;

end;         

and that worked

frederic


wp

  • Hero Member
  • *****
  • Posts: 11858
Re: zooming and dragging by code
« Reply #3 on: March 25, 2015, 04:41:51 pm »
Quote
I would check the OnAfterXXXX events whether
What did mean here?

When you are panning/zooming with the scrollbar, then you use the ScrollbarPan/ZoomTools. They have events OnAfterMouseWheelUp/Down where you call the EnsureExtent method. Or, in case of the PanDrag/ZoomTools you use the event OnAfterMouseMove, etc.

and that worked
Fine

frederic

  • Full Member
  • ***
  • Posts: 226
Re: zooming and dragging by code
« Reply #4 on: March 26, 2015, 10:27:54 am »
wp

Strange situation. Yesterday i did test the above code a number of times and it worked perfectly as i reported.
I transferred it to other projects and it was not functioning anymore especially with zooming.

there is  one is issue and that is when you start with the chart in fullextent then the code is stuck .So you need to start with a fraction of the fullextent on an chosen or arbritrary position.

The other applications have charts besides each other ,so not full screen as i tested.

So i decided to retest this morning the project from whch i reported that it was oke.
Same settings ,just start and it didn't function anymore !.........???

any idea where to look after?

frederic


wp

  • Hero Member
  • *****
  • Posts: 11858
Re: zooming and dragging by code
« Reply #5 on: March 26, 2015, 11:04:17 am »
Quote
any idea where to look after?
What else did you change?

frederic

  • Full Member
  • ***
  • Posts: 226
Re: zooming and dragging by code
« Reply #6 on: March 26, 2015, 03:28:37 pm »
wp

In the testproject, i used yesterday to test the code i presented ,nothing(i am awareof) has changed. I copied the EnsureExtent procedure and closed the testproject .This morning i started  it up and ran it.

But of course something must have change to cause this difference in behaviour.
Therefore i looked further and tried rebuild again on the basis of the latest testproject. There is something peculiar happening with the size of the fullextent of the X-axis  while setting of the separation lines of the pane . see the attached screenpicture .I loaded the testproject

frederic

  • Full Member
  • ***
  • Posts: 226
Re: zooming and dragging by code
« Reply #7 on: March 26, 2015, 03:31:00 pm »
oh ,i forgot the printtscreen

frederic

wp

  • Hero Member
  • *****
  • Posts: 11858
Re: zooming and dragging by code
« Reply #8 on: March 26, 2015, 10:48:57 pm »
Mysterious, I do not know why it worked in the old version...

Anyway, it must be related to the "SetLower/UpperSeparatorLines" which sets up the pane infrastructure. The chart displays fine again, if "UpdateAxisLabels" is called at least after the first one of these two methods - just put "UpdateAxisLabels" at the end of "makeChart", that's where I would expect it anyway (in "makechartBtnClick" it is called after the "SetXXXSeparatorLines").

I saw with heaptrc that your program creates a memory leak because the ZoomHistory is not destroyed. Add an OnDestroy handler to the form in which you call "ZoomHistory.Free". (Sorry - this bug was introduced in my own code in the other thread).

Next time when you upload projects please add also the lpi file to the zip package, it is easier for me to start the project if it is complete, and there may be errors in there as well.

[EDIT]
I see now that the old version had a similar issue (a lot of vertical grid lines) which went away after adding "UpdateAxisLabels" to the end of "makechart". I still don't understand how it relates to the "SetXXXSeparatorLines", but I won't investigate much because it is not related directly to TAChart code.
« Last Edit: March 27, 2015, 12:54:20 am by wp »

frederic

  • Full Member
  • ***
  • Posts: 226
Re: zooming and dragging by code
« Reply #9 on: March 27, 2015, 09:05:15 am »
thanks wp,
we investigate further,till next time

frederic

frederic

  • Full Member
  • ***
  • Posts: 226
Re: zooming and dragging by code
« Reply #10 on: March 27, 2015, 04:27:03 pm »
wp

another strange thing ,now the other way round
in my application i changed the code in the procedure 'prepareaxis' by using yhe extentlimit properties and it worked .I could even do  without the 'ensureextent' procedure.

so i wanted to show it to this forum :
Code: [Select]
procedure TForm1.PrepareAxis;
var
  extent: TDoubleRect;  // needs TAChartUtils
begin
  // Properties of ChartNavScrollbar (can be set also in Object Inspector)
  ChartNavScrollbar1.Align := alBottom;
  ChartNavScrollbar1.Min := 0;
  ChartNavScrollbar1.Max := 1000;  // determines smoothness of zooming
  ChartNavScrollbar1.AutoPageSize := true;  // avoid scrolling past the end of the data
  chart1.prepare;
  // Zoom in such that 5 working days are visible
  Chart1.extentsizelimit.UseXMax:=true;
  Chart1.extentsizelimit.UseXmin:=true;
  Chart1.extentsizelimit.XMax:=ConvertBARNumberToDaysPassed(TOTNUMLINES);
  Chart1.extentsizelimit.Xmin:=0;

  extent.a.X := ConvertBARNumberToDaysPassed(NUM_LINES-200); arbritrary position
  extent.b.X := ConvertBARNumberToDaysPassed(NUM_LINES-1);
  //extent := Chart1.GetFullExtent;  // unzoomed data rectangle
  //extent.a.X := extent.b.X - 1;    // move 5 days before the end of the x axis
  Chart1.LogicalExtent := extent;
  Chart1.Prepare;
end;                   

but this didn't work in the last uploaded project .
I leave it now for the moment and wait for the  lazarus 1.4 release ( which should be there within a month ) .

frederic


wp

  • Hero Member
  • *****
  • Posts: 11858
Re: zooming and dragging by code
« Reply #11 on: March 27, 2015, 05:11:35 pm »
Of course, this cannot work because you have a local variable "extent" which is not initialized properly: you do assign values to the a.x and b.x elements, but the y elements are unassigned. You must call Chart.GetFullExtent first. And you must do this after data are loaded into the series (i.e. after "makeChart") because otherwise the chart does not know the y values...

The sequence of operations in your program for chart creation (data loading -> xaxis creating -> y axis actions -> series creation ...) is a bit weird and probably causes a lot of your trouble.

Why don't you do it like this:
- load file into arrays
- add series to the chart
- construct the x labels
- construct the y panes
- prepare visible window (LogicalExtent)

Be careful with "ExtentSizeLimit". Look at the "Size" in this name: it means that the *Size* of the extent cannot be greater than these limits, but if the extent is smaller it is still possible to pan the logical extent out of the full extent range!

frederic

  • Full Member
  • ***
  • Posts: 226
Re: zooming and dragging by code
« Reply #12 on: March 27, 2015, 10:09:43 pm »
wp
the original reason this sequence was chosen was the requirement to have an x-axis would go beyond the x values of the index and stoch1/stoch2 graphs.
In fact the X-axisseries was created first with an Y value of 0 and now added up with the other series  in the procedure makeXaxis.
PrepareAxis is deleted  and that works and looks far more stable than before!

Quote
Be careful with "ExtentSizeLimit". Look at the "Size" in this name: it means that the *Size* of the extent cannot be greater than these limits, but if the extent is smaller it is still possible to pan the logical extent out of the full extent range

oh, i  misinterpreted this
thanks again we keep learning
frederic



wp

  • Hero Member
  • *****
  • Posts: 11858
Re: zooming and dragging by code
« Reply #13 on: March 27, 2015, 10:24:46 pm »
BTW: What is the xaxisseries for? In my opinion it is not needed,  the axis labels are stored in dedicated ListChartSources (TimeChartSource, DateTimeSource) from which the two bottom axes get them.

Quote
ExtentSizeLimit
You're not alone, I myself got caught in this trap many times.

frederic

  • Full Member
  • ***
  • Posts: 226
Re: zooming and dragging by code
« Reply #14 on: March 28, 2015, 12:21:14 pm »
wp

Quote
BTW: What is the xaxisseries for? In my opinion it is not needed,  the axis labels are stored in dedicated ListChartSources (TimeChartSource, DateTimeSource) from which the two bottom axes get them.

but I want to see the axis labels also beyond the max X-axis value of all the other series.Therefore I constructed this "Ghost- series" .

Code: [Select]
Xaxisseries.AddXY(days, y, s);
but it artificial but i could't find a more elegant way


frederic

 

TinyPortal © 2005-2018