manpagez: man pages & more
info mathgl_en
Home | html | info | man
[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.1.3 Animation

Widget classes (mglWindow, mglGLUT) support a delayed drawing, when all plotting functions are called once at the beginning of writing to memory lists. Further program displays the saved lists faster. Resulting redrawing will be faster but it requires sufficient memory. Several lists (frames) can be displayed one after another (by pressing ‘,’, ‘.’) or run as cinema. To switch these feature on one needs to modify function sample:

int sample(mglGraph *gr)
{
  gr->NewFrame();             // the first frame
  gr->Rotate(60,40);
  gr->Box();
  gr->EndFrame();             // end of the first frame
  gr->NewFrame();             // the second frame
  gr->Box();
  gr->Axis("xy");
  gr->EndFrame();             // end of the second frame
  return gr->GetNumFrame();   // returns the frame number
}

First, the function creates a frame by calling NewFrame() for rotated axes and draws the bounding box. The function EndFrame() must be called after the frame drawing! The second frame contains the bounding box and axes Axis("xy") in the initial (unrotated) coordinates. Function sample returns the number of created frames GetNumFrame().

Note, that such kind of animation is rather slow and not well suitable for visualization of running calculations. For the last case one can use Update() function. The most simple case for doing this is running yours calculations firstly in separate thread and later start MathGL window (QT or FLTK) creation.

#include <mgl2/window.h>
mglWindow *gr=NULL;
void *calc(void *)
{
  mglPoint pnt;
  for(int i=0;i<10;i++)   // do calculation
  {
    sleep(2);             // which can be very long
    pnt = mglPoint(2*mgl_rnd()-1,2*mgl_rnd()-1);
    if(gr)            // be sure that window is ready
    {
      gr->Clf();      // make new drawing
      gr->Line(mglPoint(),pnt,"Ar2");
      char str[10] = "i=0";  str[2] = '0'+i;
      gr->Puts(mglPoint(),str);
      gr->Update();   // update window
    }
  }
  exit(0);
}
int main(int argc,char **argv)
{
  static pthread_t thr;
  // first run yours routine in separate thread
  pthread_create(&thr,0,calc,0);
  pthread_detach(thr);
  gr = new mglWindow;
  gr->Run();  return 0;
}

Note, that such method looks as not working for GLUT windows due to limitation of glutMainLoop() function.

Another ways use built-in MathGL feature to run a member function mglDraw::Calc() separate thread, which work only if pthread support is enabled. For this, you just need to use mglDraw class and reimplement its Calc() method.

#include <mgl2/window.h>
class Foo : public mglDraw
{
  mglPoint pnt;  // some result of calculation
public:
  mglWindow *Gr;  // graphics to be updated
  int Draw(mglGraph *gr);
  void Calc();
} foo;
//-----------------------------------------------------
void Foo::Calc()
{
  for(int i=0;i<30;i++)   // do calculation
  {
    sleep(2);             // which can be very long
    pnt = mglPoint(2*mgl_rnd()-1,2*mgl_rnd()-1);
    Gr->Update();         // update window
  }
}
//-----------------------------------------------------
int Foo::Draw(mglGraph *gr)
{
  gr->Line(mglPoint(),pnt,"Ar2");
  gr->Box();
  return 0;
}
//-----------------------------------------------------
int main(int argc,char **argv)
{
  mglWindow gr(&foo,"MathGL examples");
  foo.Gr = &gr;   foo.Run();
  return gr.Run();
}

Finally, you can put the event-handling loop in separate instead of yours code by using RunThr() function instead of Run() one. Unfortunately, such method work well only for FLTK windows and only if pthread support was enabled. Such limitation come from the Qt requirement to be run in the primary thread only. The sample code will be:

#include <mgl2/fltk.h>
int main(int argc,char **argv)
{
  mglFLTK gr("test");     // create window
  gr.RunThr();            // run event loop in separate thread
  for(int i=0;i<10;i++)   // do calculation
  {
    sleep(1);             // which can be very long
    pnt = mglPoint(2*mgl_rnd()-1,2*mgl_rnd()-1);
    gr.Clf();             // make new drawing
    gr.Line(mglPoint(),pnt,"Ar2");
    char str[10] = "i=0"; str[2] = '0'+i;
    gr.Puts(mglPoint(),str);
    gr.Update();          // update window when you need it
  }
  return 0;   // finish calculations and close the window
}

Pictures with animation can be saved in file(s) as well. You can: export in animated GIF, or save each frame in separate file (usually JPEG) and convert these files into the movie (for example, by help of ImageMagic). Let me show both methods.

The simplest methods is making animated GIF. There are 3 steps: (1) open GIF file by StartGIF() function; (2) create the frames by calling NewFrame() before and EndFrame() after plotting; (3) close GIF by CloseGIF() function. So the simplest code for “running” sinusoid will look like this:

#include <mgl2/mgl.h>
int main(int ,char **)
{
  mglGraph gr;
  mglData dat(100);
  char str[32];
  gr.StartGIF("sample.gif");
  for(int i=0;i<40;i++)
  {
    gr.NewFrame();     // start frame
    gr.Box();          // some plotting
    for(int j=0;j<dat.nx;j++)
      dat.a[j]=sin(M_PI*j/dat.nx+M_PI*0.05*i);
    gr.Plot(dat,"b");
    gr.EndFrame();     // end frame
  }
  gr.CloseGIF();
  return 0;
}

The second way is saving each frame in separate file (usually JPEG) and later make the movie from them. MathGL have special function for saving frames – it is WriteFrame(). This function save each frame with automatic name ‘frame0001.jpg, frame0002.jpg’ and so on. Here prefix ‘frame’ is defined by PlotId variable of mglGraph class. So the similar code will look like this:

#include <mgl2/mgl.h>
int main(int ,char **)
{
  mglGraph gr;
  mglData dat(100);
  char str[32];
  for(int i=0;i<40;i++)
  {
    gr.NewFrame();     // start frame
    gr.Box();          // some plotting
    for(int j=0;j<dat.nx;j++)
      dat.a[j]=sin(M_PI*j/dat.nx+M_PI*0.05*i);
    gr.Plot(dat,"b");
    gr.EndFrame();     // end frame
    gr.WriteFrame();   // save frame
  }
  return 0;
}

Created files can be converted to movie by help of a lot of programs. For example, you can use ImageMagic (command ‘convert frame*.jpg movie.mpg’), MPEG library, GIMP and so on.

Finally, you can use mglconv tool for doing the same with MGL scripts (see section Utilities for parsing MGL).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated on March 21, 2014 using texi2html 5.0.

© manpagez.com 2000-2024
Individual documents may contain additional copyright information.