Recent

Author Topic: Animated chart source  (Read 8452 times)

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Animated chart source
« on: August 30, 2012, 05:45:07 pm »
I have implemented initial version of TCustomAnimatedChartSource
based on the discussion here:
http://forum.lazarus.freepascal.org/index.php/topic,17924.msg100190.html#msg100190.

See "animate" demo since r38443.

Currently, the component only provides a framework for animation,
requiring the user to supply an actual algorithm in OnGetItem handler.
Hence the "custom" name and lack of design-time component.

So, the question is -- is there a good set of "default" animations
which should be implemented in TAnimatedChartSource descendant?
If yes -- what it that set? I'd propose three animations from the demo --
any other suggestions?

Or maybe always requiring user-defined algorithms is good enough?

wp

  • Hero Member
  • *****
  • Posts: 6331
Re: Animated chart source
« Reply #1 on: August 30, 2012, 11:27:36 pm »
Quote
"animate" demo
Nice. I see in the discussion referenced above that there is a need for such effects, but from my point of view the custom event handling would be sufficient.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

greatUnknown

  • New Member
  • *
  • Posts: 19
Re: Animated chart source
« Reply #2 on: September 05, 2012, 07:40:49 pm »
I have a TpolarSeries with a userDefinedChartSource that has the following
OnGetChartDataItem:

Code: [Select]
with AItem do begin
  x := AIndex/100;
  y := AIndex/100;
end;

with  PointsCount := 1700

This gives me a nice spiral to experiment with.

How can I adapt this to use TAAnimatedSource? 

I've tried several options - some did nothing, some gave me a torrent of
various images which were absolutely not what I was looking for 
 For example, I tried this

Code: [Select]
procedure TForm1.OnGetItem(
  ASource: TCustomAnimatedChartSource;
  AIndex: Integer; var AItem: TChartDataItem);
begin
   AItem.Y *= ASource.Count * ASource.Progress;
   AItem.X *= ASource.Count * ASource.Progress;
end;   
 

which gave me a magnificent sequence of Lissajous figures [more
observable at AnimationTime = 10000].

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: Animated chart source
« Reply #3 on: September 05, 2012, 08:28:34 pm »
You have started the topic with exact same subject as the existing one.
I have merged those topics.

Please read the first message and look at the new "animate" demo.


greatUnknown

  • New Member
  • *
  • Posts: 19
Re: Animated chart source
« Reply #4 on: September 05, 2012, 09:09:49 pm »
I've looked at it and tried to modify it as noted in my previous message [9-05 7:40:49 pm].
I can't make it work.

One approach I used that worked was to increment Source.Count on each timer event and
redraw, but this requires me to be able to write to Count.  I can only do this generally by modifying
the original record types - which was the point behind my questions in my previous topic
"Data Structures in TAChart."

I suppose I can modify PointsCount for UserDefinedChartSources, and deal with the Count issue in
other source types by creating a Draw descendent that uses a variable FalseCount [read/write]
instead of Count [read only].  That would probably work in all cases, including those where the
count can truly not be changed.

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: Animated chart source
« Reply #5 on: September 06, 2012, 04:49:30 am »
Try this code:
Code: [Select]
procedure TForm1.OnGetItem(
  ASource: TCustomAnimatedChartSource;
  AIndex: Integer; var AItem: TChartDataItem);
begin
  if ASource.Count * ASource.Progress < AIndex then
    AItem.Y := NaN;
end;

greatUnknown

  • New Member
  • *
  • Posts: 19
Re: Animated chart source
« Reply #6 on: September 06, 2012, 07:16:23 pm »
Code: [Select]
procedure TForm1.OnGetItem(
  ASource: TCustomAnimatedChartSource;
  AIndex: Integer; var AItem: TChartDataItem);
begin
  if ASource.Count * ASource.Progress < AIndex then
    AItem.Y := NaN;
end;

Tried it and get sigFPE error [runError (207)] in [TAGraph]YGraphToImage, line 1509.
It's not the first time I've gotten that error when trying NaN with TPolarGraph.

I'm using Lazarus 1.1 64bit windows, fpc 2.61, SVN 38431  2012-8-30

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: Animated chart source
« Reply #7 on: September 07, 2012, 05:08:30 am »
Quote
error when trying NaN with TPolarGraph.
You are right, I forgot that polar series did not support NaNs.
Should be fixed in r38547.

Note that the extent of polar series will change while animating it.
It is rather hard to fix. I'll think about it -- meanwhile,
fix the extent of your chart with Chart.Extent property.

greatUnknown

  • New Member
  • *
  • Posts: 19
Re: Animated chart source
« Reply #8 on: September 10, 2012, 04:32:37 am »
Thank you for the NaN fix.  Now I can discard all of the workarounds I wrote.

I fixed the extent problem by creating a simple procedure to freeze the extent at
runtime and calling it prior to starting animation.  This would allow drawing different
graphs without calculating maximum extents at design time.

Code: [Select]
procedure TPolarSeries.FreezeExtent;
begin
  with ParentChart, Extent do begin
    XMin := XGraphMin;
    XMax := XGraphMax;
    YMin := YGraphMin;
    YMax := YGraphMax;
    UseXMin := true;
    UseYMin := true;
    UseXMax := true;
    UseYMax := true;
  end;
end;             
........
procedure TForm1.BtnStartStopClick(Sender: TObject);
begin
  if FAnimatedSource.IsAnimating then
    FAnimatedSource.Stop
  else begin
    PolarSeries1.FreezeExtent;
    FAnimatedSource.Start;
  end;
end;   

 

At least with a simple spiral it works.
I also set proportional := true, as per your advice.

Next step is circular and radial axes, which will probably
have to be drawn as part of the polar series instead of
as chart axes.  This should allow them to zoom correctly.

Ask

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 687
Re: Animated chart source
« Reply #9 on: September 10, 2012, 11:57:21 am »
Quote
procedure to freeze the extent at
runtime and calling it prior to starting animation.

Yes, that's correct, although this procedure belongs to your code,
not TPolarSeries. In r38609 have added TChartExtent.FixTo method,
the body of the procedure can now be written as
Code: [Select]
ParentChart.Extent.FixTo(ParentChart.CurrentExtent)
Quote
circular and radial axes, which will probably
have to be drawn as part of the polar series instead of
as chart axes.  This should allow them to zoom correctly.

For now, I agree that it is easier for you to simply draw axis together
with the series.
However, I do not think that this is optimal general solution for TAChart,
so I recommend you to add TPolarSeries descendant instead of modifying
TPolarSeries directly. This way it would be easier for you to keep your changes
while updating TAChart.