* 3D samples::
* Dual samples::
* More samples::
-* C/Fortran interface::
-* MathGL and PyQt::
* Hints::
* FAQ::
@end menu
MathGL library can be used by several manners. Each has positive and negative sides:
@itemize @bullet
@item
-@emph{The using of MathGL library features for creating graphical window (requires FLTK or GLUT libraries).}
+@emph{Using of MathGL library features for creating graphical window (requires FLTK, Qt or GLUT libraries).}
Positive side is the possibility to view the plot at once and to modify it (rotate, zoom or switch on transparency or lighting) by hand or by mouse. Negative sides are: the need of X-terminal and limitation consisting in working with the only one set of data at a time.
+
@item
@emph{Direct writing to file in bitmap or vector format without creation of graphical window.}
Positive aspects are: batch processing of similar data set (for example, a set of resulting data files for different calculation parameters), running from the console program (including the cluster calculation), fast and automated drawing, saving pictures for further analysis (or demonstration). Negative sides are: the usage of the external program for picture viewing. Also, the data plotting is non-visual. So, you have to imagine the picture (view angles, lighting and so on) before the plotting. I recommend to use graphical window for determining the optimal parameters of plotting on the base of some typical data set. And later use these parameters for batch processing in console program.
+
@item
@emph{Drawing in memory with the following displaying by other graphical program.}
-In this case the programmer has more freedom in selecting the window libraries (not only FLTK or GLUT), in positioning and surroundings control and so on. I recommend to use such way for ``settled'' programs.
+In this case the programmer has more freedom in selecting the window libraries (not only FLTK, Qt or GLUT), in positioning and surroundings control and so on. I recommend to use such way for ``settled'' programs.
+
+@item
+@emph{Using FLTK or Qt widgets provided by MathGL}
+
+Here one can use a set of standard widgets which support export to many file formats, copying to clipboard, handle mouse and so on.
@end itemize
+MathGL drawing can be created not only by object oriented languages (like, C++ or Python), but also by pure C or Fortran-like languages. The usage of last one is mostly identical to usage of classes (except the different function names). But there are some differences. C functions must have argument HMGL (for graphics) and/or HMDT (for data arrays) which specifies the object for drawing or manipulating (changing). Fortran users may regard these variables as integer. So, firstly the user has to create this object by function mgl_create_*() and has to delete it after the using by function mgl_delete_*().
+@c Also, all arguments of C function have to be defined. So there are several functions with practically identical names doing practically the same. But some of them have simplified interface for the quick plotting and some of them have access to all plotting parameters for manual tunning.
+
Let me consider the aforesaid in more detail.
@menu
* Using MathGL window::
* Drawing to file::
+* Animation::
* Drawing in memory::
* Using QMathGL::
+* MathGL and PyQt::
@end menu
The ``interactive'' way of drawing in MathGL consists in window creation with help of class @code{mglWindow} or @code{mglGLUT} (see @ref{Widget classes}) and the following drawing in this window. There is a corresponding code:
@verbatim
- int sample(mglGraph *gr)
- {
- gr->Rotate(60,40);
- gr->Box();
- return 0;
- }
- //-----------------------------------------------------
- int main(int argc,char **argv)
- {
- mglWindow gr(0,sample,"MathGL examples");
- return gr.Run();
- }
+#include <mgl/window.h>
+int sample(mglGraph *gr)
+{
+ gr->Rotate(60,40);
+ gr->Box();
+ return 0;
+}
+//-----------------------------------------------------
+int main(int argc,char **argv)
+{
+ mglWindow gr(sample,"MathGL examples");
+ return gr.Run();
+}
+@end verbatim
+Here function @code{sample} is defined. This function does all drawing. Other function @code{main} is entry point function for console program. For compilation, just execute the command
+@verbatim
+gcc test.cpp -lmgl-wnd -lmgl
@end verbatim
-Here function @code{sample} is defined. This function does all drawing. Other function @code{main} is entry point function for console program.
Alternatively you can create yours own class inherited from class @code{mglDraw} and re-implement the function @code{Draw()} in it:
@verbatim
- class Foo : public mglDraw
- {
- public:
- int Draw(mglGraph *gr);
- };
- //-----------------------------------------------------
- int Foo::Draw(mglGraph *gr)
- {
- gr->Rotate(60,40);
- gr->Box();
- return 0;
- }
- //-----------------------------------------------------
- int main(int argc,char **argv)
- {
- mglDraw foo;
- mglWindow gr(0,&foo,"MathGL examples");
- return gr.Run();
- }
+#include <mgl/window.h>
+class Foo : public mglDraw
+{
+public:
+ int Draw(mglGraph *gr);
+};
+//-----------------------------------------------------
+int Foo::Draw(mglGraph *gr)
+{
+ gr->Rotate(60,40);
+ gr->Box();
+ return 0;
+}
+//-----------------------------------------------------
+int main(int argc,char **argv)
+{
+ Foo foo;
+ mglWindow gr(&foo,"MathGL examples");
+ return gr.Run();
+}
+@end verbatim
+Or use pure C-functions:
+@verbatim
+#include <mgl/mgl_cf.h>
+int sample(HMGL gr)
+{
+ mgl_rotate(gr,60,40,0);
+ mgl_box(gr);
+}
+int main(int argc,char **argv)
+{
+ HMGL gr;
+ gr = mgl_create_graph_qt(sample,"MathGL examples",0);
+ return mgl_qt_run();
+/* generally I should call mgl_delete_graph() here,
+ * but I omit it in main() function. */
+}
@end verbatim
The similar code can be written for @code{mglGLUT} window (function @code{sample()} is the same):
@verbatim
- int main(int argc,char **argv)
- {
- mglGLUT gr(sample,"MathGL examples");
- return 0;
- }
+#include <mgl/glut.h>
+int main(int argc,char **argv)
+{
+ mglGLUT gr(sample,"MathGL examples");
+ return 0;
+}
@end verbatim
The rotation, shift, zooming, switching on/off transparency and lighting can be done with help of tool-buttons (for @code{mglWindow}) or by hot-keys: @samp{a}, @samp{d}, @samp{w}, @samp{s} for plot rotation, @samp{r} and @samp{f} switching on/off transparency and lighting. Press @samp{x} for exit (or closing the window).
-In this example function @code{sample} rotates axes (@code{Rotate()}, @pxref{Transformation matrix}) and draws the bounding box (@code{Box()}). Drawing procedure is separated in a function since it will be used on demand when window canvas needs to be redrawn. Widget classes (@code{mglWindow}, @code{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 @samp{,}, @samp{.}) or run as cinema. To switch these feature on one needs to modify function @code{sample}:
+In this example function @code{sample} rotates axes (@code{Rotate()}, @pxref{Transformation matrix}) and draws the bounding box (@code{Box()}). Drawing is placed in separate function since it will be used on demand when window canvas needs to be redrawn.
+
+@c ------------------------------------------------------------------
+@node Drawing to file, Animation, Using MathGL window, Basic usage
+@subsection Drawing to file
+
+Another way of using MathGL library is the direct writing of the picture to the file. It is most usable for plot creation during long calculation or for using of small programs (like Matlab or Scilab scripts) for visualizing repetitive sets of data. But the speed of drawing is much higher in comparison with a script language.
+
+The following code produces a bitmap PNG picture:
+@verbatim
+#include <mgl/mgl.h>
+int main(int ,char **)
+{
+ mglGraph gr;
+ gr.Alpha(true); gr.Light(true);
+ sample(&gr); // The same drawing function.
+ gr.WritePNG("test.png"); // Don't forget to save the result!
+ return 0;
+}
+@end verbatim
+ For compilation, you need only libmgl library not the one with widgets
+@verbatim
+gcc test.cpp -lmgl
+@end verbatim
+This can be important if you create a console program in computer/cluster where X-server (and widgets) is inaccessible.
+
+The only difference from the previous variant (using windows) is manual switching on the transparency @code{Alpha} and lightning @code{Light}, if you need it. The usage of frames (see @ref{Animation}) is not advisable since the whole image is prepared each time. If function @code{sample} contains frames then only last one will be saved to the file. In principle, one does not need to separate drawing functions in case of direct file writing in consequence of the single calling of this function for each picture. However, one may use the same drawing procedure to create a plot with changeable parameters, to export in different file types, to emphasize the drawing code and so on. So, in future I will put the drawing in the separate function.
+
+The code for export in vector EPS file looks the same:
@verbatim
- int sample1(mglGraph *gr, void *)
- {
- 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 GetNumFrame(); // returns the frame number
- }
+#include <mgl/mgl.h>
+int main(int ,char **)
+{
+ mglGraph gr;
+ gr.Light(true);
+ sample(&gr); // The same drawing function.
+ gr.WriteEPS("test.eps"); // Don't forget to save the result!
+ return 0;
+}
+@end verbatim
+The difference from the previous one is using other function @code{WriteEPS()} for EPS format instead of function @code{WritePNG()}. Also, there is no switching on of the plot transparency @code{Alpha} since EPS format does not support it.
+
+@c ------------------------------------------------------------------
+@node Animation, Drawing in memory, Drawing to file, Basic usage
+@subsection Animation
+
+Widget classes (@code{mglWindow}, @code{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 @samp{,}, @samp{.}) or run as cinema. To switch these feature on one needs to modify function @code{sample}:
+@verbatim
+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
+}
@end verbatim
First, the function creates a frame @code{NewFrame()} for rotated axes and draws the bounding box. After the frame drawing the function @code{EndFrame()} @strong{must be} called! The second frame contains the bounding box and axes @code{Axis("xy")} in the initial (unrotated) coordinates. Function @code{sample} returns the number of created frames @code{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 @code{Update()} function. The most simple case for doing this is to use @code{mglDraw} class and reimplement its @code{Calc()} method.
@verbatim
- class Foo : public mglDraw
- {
- mglPoint pnt; // some result of calculation
- public:
- mglGraph *Gr; // graphics to be updated
- int Draw(mglGraph *gr);
- void Calc();
- } foo;
- //-----------------------------------------------------
- int 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)
- {
- mglDraw foo;
- mglWindow gr(0,&foo,"MathGL examples");
- foo.Gr = &gr; foo.Run();
- return gr.Run();
- }
+#include <mgl/window.h>
+class Foo : public mglDraw
+{
+ mglPoint pnt; // some result of calculation
+public:
+ mglGraph *Gr; // graphics to be updated
+ int Draw(mglGraph *gr);
+ void Calc();
+} foo;
+//-----------------------------------------------------
+int 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();
+}
@end verbatim
-@c ------------------------------------------------------------------
-@node Drawing to file, Drawing in memory, Using MathGL window, Basic usage
-@subsection Drawing to file
-Another way of using MathGL library is the direct picture writing to file. It is most usable for plot creating during calculation or for using of small programs (like Matlab or Scilab scripts) for visualizing repetitive sets of data. But the speed of drawing is much higher in comparison with a script language.
+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 following code produces a bitmap PNG picture:
+The simplest methods is making animated GIF. There are 3 steps: (1) open GIF file by @code{StartGIF()} function; (2) create the frames by calling @code{NewFrame()} before and @code{EndFrame()} after plotting; (3) close GIF by @code{CloseGIF()} function. So the simplest code for ``running'' sinusoid will look like this:
@verbatim
- int main(int ,char **)
- {
- mglGraph gr;
- gr.Alpha(true);
- gr.Light(true); gr.Light(0,mglPoint(1,0,-1));
- sample(&gr,NULL); // The same drawing function.
- gr.WritePNG("test.png"); // Don't forget to save the result!
- return 0;
- }
+#include <mgl/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;
+}
@end verbatim
-The only difference from the previous (using windows) variant is manual switching the transparency @code{Alpha} and lightning @code{Light} on, if the plot requires it. The using of frames is not advisable since the whole image is prepared each time. If function @code{sample} contains frames then each frame will be saved to a separate file. In principle, one does not need to separate drawing functions in case of direct file writing in consequence of the single calling of this function for each picture. However, one may use the same drawing procedure to create a plot with changed parameters, to export in different file types, to emphasize the drawing code and so on. So, in future I will put the drawing in separate function.
-The code for export in vector EPS file looks the same:
+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 @code{WriteFrame()}. This function save each frame with automatic name @samp{frame0001.jpg, frame0002.jpg} and so on. Here prefix @samp{frame} is defined by @var{PlotId} variable of @code{mglGraph} class. So the similar code will look like this:
@verbatim
- int main(int ,char **)
- {
- mglGraph gr;
- gr.Light(true); gr.Light(0,mglPoint(1,0,-1));
- sample(&gr,NULL); // The same drawing function.
- gr.WriteEPS("test.eps"); // Don't forget to save the result!
- return 0;
- }
+#include <mgl/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;
+}
@end verbatim
-The difference from the previous one is using other function @code{WriteEPS()} for EPS format instead of function @code{WritePNG()}. Moreover, there is no switching of the plot transparency @code{Alpha} since EPS format does not support it. Possibly I shall include transparency in future by program emulation.
+
+Created files can be converted to movie by help of a lot of programs. For example, you can use ImageMagic (command @samp{convert frame*.jpg movie.mpg}), MPEG library, GIMP and so on.
+
+Finally, you can use @code{mglconv} tool for doing the same with MGL scripts (@pxref{Utilities}).
@c ------------------------------------------------------------------
-@node Drawing in memory, Using QMathGL, Drawing to file, Basic usage
+@node Drawing in memory, Using QMathGL, Animation, Basic usage
@subsection Drawing in memory
The last way of MathGL using is the drawing in memory. Class @code{mglGraph} allows one to create a bitmap picture in memory. Further this picture can be displayed in window by some window libraries (like wxWidgets, FLTK, Windows GDI and so on). For example, the code for drawing in wxWidget library looks like:
@verbatim
- void MyForm::OnPaint(wxPaintEvent& event)
- {
- int w,h,x,y;
- GetClientSize(&w,&h); // size of the picture
- mglGraph gr(w,h);
-
- gr.Alpha(true); // draws something using MathGL
- gr.Light(true); gr.Light(0,mglPoint(1,0,-1));
- sample(&gr,NULL);
-
- wxImage img(w,h,gr.GetBits(),true);
- ToolBar->GetSize(&x,&y); // gets a height of the toolbar if any
- wxPaintDC dc(this); // and draws it
- dc.DrawBitmap(wxBitmap(img),0,y);
- }
+void MyForm::OnPaint(wxPaintEvent& event)
+{
+ int w,h,x,y;
+ GetClientSize(&w,&h); // size of the picture
+ mglGraph gr(w,h);
+
+ gr.Alpha(true); // draws something using MathGL
+ gr.Light(true);
+ sample(&gr,NULL);
+
+ wxImage img(w,h,gr.GetBits(),true);
+ ToolBar->GetSize(&x,&y); // gets a height of the toolbar if any
+ wxPaintDC dc(this); // and draws it
+ dc.DrawBitmap(wxBitmap(img),0,y);
+}
@end verbatim
The drawing in other libraries is most the same.
For example, FLTK code will look like
@verbatim
- void Fl_MyWidget::draw()
- {
- mglGraph gr(w(),h());
- gr.Alpha(true); // draws something using MathGL
- gr.Light(true); gr.Light(0,mglPoint(1,0,-1));
- sample(&gr,NULL);
- fl_draw_image(gr.GetBits(), x(), y(), gr.GetWidth(), gr.GetHeight(), 3);
- }
+void Fl_MyWidget::draw()
+{
+ mglGraph gr(w(),h());
+ gr.Alpha(true); // draws something using MathGL
+ gr.Light(true);
+ sample(&gr,NULL);
+ fl_draw_image(gr.GetBits(), x(), y(), gr.GetWidth(), gr.GetHeight(), 3);
+}
@end verbatim
Qt code will look like
@verbatim
- void MyWidget::paintEvent(QPaintEvent *)
- {
- mglGraph gr(w(),h());
- gr.Alpha(true); // draws something using MathGL
- gr.Light(true); gr.Light(0,mglPoint(1,0,-1));
- sample(&gr,NULL);
-
- // Qt don't support RGB format as is. So, let convert it to BGRN.
- const uchar *bb = gr.GetBits();
- register long i, w=gr.GetWidth(), h=gr.GetHeight();
- *buf = new uchar[4*w*h];
- for(i=0;i<w*h;i++)
- {
- (*buf)[4*i] = bb[3*i+2];
- (*buf)[4*i+1] = bb[3*i+1];
- (*buf)[4*i+2] = bb[3*i];
- (*buf)[4*i+3] = 255;
- }
- QPixmap pic = QPixmap::fromImage(QImage(*buf, w, h, QImage::Format_RGB32));
-
- QPainter paint;
- paint.begin(this); paint.drawPixmap(0,0,pic); paint.end();
- delete []buf;
- }
+void MyWidget::paintEvent(QPaintEvent *)
+{
+ mglGraph gr(w(),h());
+
+ gr.Alpha(true); // draws something using MathGL
+ gr.Light(true); gr.Light(0,mglPoint(1,0,-1));
+ sample(&gr,NULL);
+
+ // Qt don't support RGB format as is. So, let convert it to BGRN.
+ long w=gr.GetWidth(), h=gr.GetHeight();
+ unsigned char *buf = new uchar[4*w*h];
+ gr.GetBGRN(buf, 4*w*h)
+ QPixmap pic = QPixmap::fromImage(QImage(*buf, w, h, QImage::Format_RGB32));
+
+ QPainter paint;
+ paint.begin(this); paint.drawPixmap(0,0,pic); paint.end();
+ delete []buf;
+}
@end verbatim
@c ------------------------------------------------------------------
-@node Using QMathGL, , Drawing in memory, Basic usage
+@node Using QMathGL, MathGL and PyQt, Drawing in memory, Basic usage
@subsection Using QMathGL
-MathGL have several interface widgets for different widget libraries. There are QMathGL for Qt, Fl_MathGL for FLTK in MathGL v.1.8. These classes provide control which display MathGL graphics. Unfortunately there is no uniform interface for widget classes because all libraries have slightly different set of functions, features and so on. However the usage of MathGL widgets is rather simple. Let me show it on the example of QMathGL.
+MathGL have several interface widgets for different widget libraries. There are QMathGL for Qt, Fl_MathGL for FLTK. These classes provide control which display MathGL graphics. Unfortunately there is no uniform interface for widget classes because all libraries have slightly different set of functions, features and so on. However the usage of MathGL widgets is rather simple. Let me show it on the example of QMathGL.
First of all you have to define the drawing function or inherit a class from @code{mglDraw} class. After it just create a window and setup QMathGL instance as any other Qt widget:
@verbatim
- int main(int argc,char **argv)
- {
- QApplication a(argc,argv);
- QMainWindow *Wnd = new QMainWindow;
- Wnd->resize(650,480); // for fill up the QMGL, menu and toolbars
- Wnd->setWindowTitle(title);
- // here I allow to scroll QMathGL -- the case
- // then user want to prepare huge picture
- QScrollArea *scroll = new QScrollArea(Wnd);
-
- // Create and setup QMathGL
- QMathGL *QMGL = new QMathGL(Wnd);
- QMGL->setPopup(popup); // if you want to setup popup menu for QMGL
- QMGL->setDraw(sample, NULL);
- // or use QMGL->setDraw(foo); for instance of class Foo:public mglDraw
- QMGL->update();
-
- // continue other setup (menu, toolbar and so on)
- makeMenu();
- scroll->setWidget(QMGL);
- Wnd->setCentralWidget(scroll);
- Wnd->show();
- return a.exec();
- }
+#include <QApplication>
+#include <QMainWindow>
+#include <QScrollArea>
+#include <mgl/qt.h>
+int main(int argc,char **argv)
+{
+ QApplication a(argc,argv);
+ QMainWindow *Wnd = new QMainWindow;
+ Wnd->resize(810,610); // for fill up the QMGL, menu and toolbars
+ Wnd->setWindowTitle("QMathGL sample");
+ // here I allow to scroll QMathGL -- the case
+ // then user want to prepare huge picture
+ QScrollArea *scroll = new QScrollArea(Wnd);
+
+ // Create and setup QMathGL
+ QMathGL *QMGL = new QMathGL(Wnd);
+//QMGL->setPopup(popup); // if you want to setup popup menu for QMGL
+ QMGL->setDraw(sample);
+ // or use QMGL->setDraw(foo); for instance of class Foo:public mglDraw
+ QMGL->update();
+
+ // continue other setup (menu, toolbar and so on)
+ scroll->setWidget(QMGL);
+ Wnd->setCentralWidget(scroll);
+ Wnd->show();
+ return a.exec();
+}
+@end verbatim
+
+@c ------------------------------------------------------------------
+@node MathGL and PyQt, , Using QMathGL, Basic usage
+@subsection MathGL and PyQt
+
+Generally SWIG based classes (including the Python one) are the same as C++ classes. However, there are few tips for using MathGL with PyQt. Below I place a very simple python code which demonstrate how MathGL can be used with PyQt. This code is mostly written by Prof. Dr. Heino Falcke. You can just copy it to a file @code{mgl-pyqt-test.py} and execute it from python shell by command @code{execfile("mgl-pyqt-test.py")}
+
+@verbatim
+from PyQt4 import QtGui,QtCore
+from mathgl import *
+import sys
+app = QtGui.QApplication(sys.argv)
+qpointf=QtCore.QPointF()
+
+class hfQtPlot(QtGui.QWidget):
+ def __init__(self, parent=None):
+ QtGui.QWidget.__init__(self, parent)
+ self.img=(QtGui.QImage())
+ def setgraph(self,gr):
+ self.buffer='\t'
+ self.buffer=self.buffer.expandtabs(4*gr.GetWidth()*gr.GetHeight())
+ gr.GetBGRN(self.buffer,len(self.buffer))
+ self.img=QtGui.QImage(self.buffer, gr.GetWidth(),gr.GetHeight(),QtGui.QImage.Format_ARGB32)
+ self.update()
+ def paintEvent(self, event):
+ paint = QtGui.QPainter()
+ paint.begin(self)
+ paint.drawImage(qpointf,self.img)
+ paint.end()
+
+BackgroundColor=[1.0,1.0,1.0]
+size=100
+gr=mglGraph()
+y=mglData(size)
+#y.Modify("((0.7*cos(2*pi*(x+.2)*500)+0.3)*(rnd*0.5+0.5)+362.135+10000.)")
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+x=mglData(size)
+x.Modify("x^2");
+
+def plotpanel(gr,x,y,n):
+ gr.SubPlot(2,2,n)
+ gr.SetXRange(x)
+ gr.SetYRange(y)
+ gr.AdjustTicks()
+ gr.Axis()
+ gr.Box()
+ gr.Label("x","x-Axis",1)
+ gr.Label("y","y-Axis",1)
+ gr.ClearLegend()
+ gr.AddLegend("Legend: "+str(n),"k")
+ gr.Legend()
+ gr.Plot(x,y)
+
+
+gr.Clf(BackgroundColor[0],BackgroundColor[1],BackgroundColor[2])
+gr.SetPlotFactor(1.5)
+plotpanel(gr,x,y,0)
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+plotpanel(gr,x,y,1)
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+plotpanel(gr,x,y,2)
+y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
+plotpanel(gr,x,y,3)
+
+gr.WritePNG("test.png","Test Plot")
+
+qw = hfQtPlot()
+qw.show()
+qw.setgraph(gr)
+qw.raise_()
@end verbatim
@node Advanced usage, Data handling, Basic usage, Examples
@section Advanced usage
-Now I show several non-obvious features of MathGL: several subplots in a single picture, curvilinear coordinates, text printing and so on. Generally you may miss this section at first reading, but I don't recommend it.
+Now I show several non-obvious features of MathGL: several subplots in a single picture, curvilinear coordinates, text printing and so on. Generally you may miss this section at first reading.
@menu
* Subplots::
-* Axis and grids::
+* Axis and ticks::
* Curvilinear coordinates::
-* Text printing example::
-* Animation::
+* Colorbars::
+* Ternary axis::
+* Text features::
+* Cutting sample::
@end menu
@c ------------------------------------------------------------------
-@node Subplots, Axis and grids, , Advanced usage
+@node Subplots, Axis and ticks, , Advanced usage
@subsection Subplots
-Let me demonstrate possibilities of axes transformation. MathGL has the following functions: @code{SubPlot}, @code{InPlot}, @code{Aspect} and @code{Rotate} (@pxref{Transformation matrix}). The order of their calling is strictly determined. First, one changes the position of axes in image area (functions @code{SubPlot} and @code{InPlot}). After that one may rotate the plot (function @code{Rotate}). Finally, one may change aspects of axes (function @code{Aspect}). The following code illustrates the aforesaid it:
+Let me demonstrate possibilities of plot positioning and rotation. MathGL has a set of functions: @code{SubPlot}, @code{InPlot}, @code{Title}, @code{Aspect} and @code{Rotate} and so on (see @ref{Transformation matrix}). The order of their calling is strictly determined. First, one changes the position of plot in image area (functions @code{SubPlot}, @code{InPlot} and @code{MultiPlot}). Secondly, you can add the title of plot by @code{Title} function. After that one may rotate the plot (function @code{Rotate}). Finally, one may change aspects of axes (function @code{Aspect}). The following code illustrates the aforesaid it:
@verbatim
- int sample(mglGraph *gr, void *)
- {
- gr->SubPlot(2,2,0);
- gr->Box();
- gr->Puts(mglPoint(-1,1.1,1),"Just box","rL");
- gr->InPlot(0.2,0.5,0.7,1);
- gr->Box();
- gr->Puts(mglPoint(0,1.2,1),"InPlot example");
-
- gr->SubPlot(2,2,1);
- gr->Rotate(60,40);
- gr->Aspect(1,1,1);
- gr->Box();
- gr->Puts(mglPoint(1,1,1.5),"Rotate only","rR");
-
- gr->SubPlot(2,2,2);
- gr->Rotate(60,40);
- gr->Aspect(1,1,2);
- gr->Box();
- gr->Puts(mglPoint(0,0,2),"Aspect and Rotate");
-
- gr->SubPlot(2,2,3);
- gr->Rotate(60,40);
- gr->Aspect(1,2,2);
- gr->Box();
- gr->Puts(mglPoint(0,0,1.5),"Aspect in other direction");
- return 0;
- }
+int sample(mglGraph *gr)
+{
+ gr->SubPlot(2,2,0); gr->Box();
+ gr->Puts(mglPoint(-1,1.1),"Just box",":L");
+ gr->InPlot(0.2,0.5,0.7,1,false); gr->Box();
+ gr->Puts(mglPoint(0,1.2),"InPlot example");
+ gr->SubPlot(2,2,1); gr->Title("Rotate only");
+ gr->Rotate(50,60); gr->Box();
+ gr->SubPlot(2,2,2); gr->Title("Rotate and Aspect");
+ gr->Rotate(50,60); gr->Aspect(1,1,2); gr->Box();
+ gr->SubPlot(2,2,3); gr->Title("Aspect in other direction");
+ gr->Rotate(50,60); gr->Aspect(1,2,2); gr->Box();
+ return 0;
+}
@end verbatim
-Here I used function @code{Puts} for printing the text in arbitrary position of picture (@pxref{Text printing}). Text coordinates and size are connected with axes. However, text coordinates may be everywhere, including the outside the bounding box. I shall show its features later in @xref{Text printing example}.
+Here I used function @code{Puts} for printing the text in arbitrary position of picture (see @ref{Text printing}). Text coordinates and size are connected with axes. However, text coordinates may be everywhere, including the outside the bounding box. I'll show its features later in @ref{Text features}.
@float
-@image{../png/sample1, 7cm}
+@image{../png/aspect, 11cm}
@caption{Example of several subplots on the single picture.}
@end float
+More complicated sample show how to use most of positioning functions:
+@verbatim
+int sample(mglGraph *gr)
+{
+ gr->SubPlot(3,2,0); gr->Title("StickPlot");
+ gr->StickPlot(3, 0, 20, 30); gr->Box("r"); gr->Puts(mglPoint(0),"0","r");
+ gr->StickPlot(3, 1, 20, 30); gr->Box("g"); gr->Puts(mglPoint(0),"1","g");
+ gr->StickPlot(3, 2, 20, 30); gr->Box("b"); gr->Puts(mglPoint(0),"2","b");
+ gr->SubPlot(3,2,3,""); gr->Title("ColumnPlot");
+ gr->ColumnPlot(3, 0); gr->Box("r"); gr->Puts(mglPoint(0),"0","r");
+ gr->ColumnPlot(3, 1); gr->Box("g"); gr->Puts(mglPoint(0),"1","g");
+ gr->ColumnPlot(3, 2); gr->Box("b"); gr->Puts(mglPoint(0),"2","b");
+ gr->SubPlot(3,2,4,""); gr->Title("GridPlot");
+ gr->GridPlot(2, 2, 0); gr->Box("r"); gr->Puts(mglPoint(0),"0","r");
+ gr->GridPlot(2, 2, 1); gr->Box("g"); gr->Puts(mglPoint(0),"1","g");
+ gr->GridPlot(2, 2, 2); gr->Box("b"); gr->Puts(mglPoint(0),"2","b");
+ gr->GridPlot(2, 2, 3); gr->Box("m"); gr->Puts(mglPoint(0),"3","m");
+ gr->SubPlot(3,2,5,""); gr->Title("InPlot"); gr->Box();
+ gr->InPlot(0.4, 1, 0.6, 1, true); gr->Box("r");
+ gr->MultiPlot(3,2,1, 2, 1,""); gr->Title("MultiPlot"); gr->Box();
+ return 0;
+}
+@end verbatim
+
+@float
+@image{../png/inplot, 11cm}
+@caption{Example for most of positioning functions.}
+@end float
+
+
@c ------------------------------------------------------------------
-@node Axis and grids, Curvilinear coordinates, Subplots, Advanced usage
-@subsection Axis and grids
+@node Axis and ticks, Curvilinear coordinates, Subplots, Advanced usage
+@subsection Axis and ticks
-MathGL library can draw not only the bounding box but also the axes, grids, labels and so on. The limits of axes and their origin (the point of intersection) are determined by function @code{Axis()}. Also you can use @code{XRange(), YRange(), ZRange()} functions (@pxref{Ranges (bounding box)}). Ticks on axis are specified by function @code{SetTicks} (@pxref{Ticks}). First argument the direction for each change will be applied. Second argument gives the step between ticks (if positive) or gives the number of ticks on the axis (if negative) or set to use logarithmic ticks (if zero). Third argument gives numbers of sub-ticks between ticks (default is zero). Last argument define the initial ticks position.
+MathGL library can draw not only the bounding box but also the axes, grids, labels and so on. The ranges of axes and their origin (the point of intersection) are determined by functions @code{SetRange()}, @code{SetRanges()}, @code{SetOrigin()} (see @ref{Ranges (bounding box)}). Ticks on axis are specified by function @code{SetTicks}, @code{SetTicksVal}, @code{SetTicksTime} (see @ref{Ticks}). But usually
Function @code{Axis} draws axes. Its textual string shows in which directions the axis or axes will be drawn (by default @code{"xyz"}, function draws axes in all directions). Function @code{Grid} draws grid perpendicularly to specified directions. Example of axes and grid drawing is:
@verbatim
- int sample(mglGraph *gr, void *)
- {
- gr->SubPlot(2,2,0);
- gr->SetTicks('x', 0.4, 3); // sets tick step to 0.5
- gr->SetTicks('y', 0.4, 3); // and draws 3 subticks
- gr->Box(); // should be after the ticks change
- gr->Axis("xy");
- gr->Grid();
- gr->Puts(mglPoint(0,1.3,1),"Axis and grid");
-
- gr->SetTicks('x'); gr->SetTicks('y'); // restore back
- gr->Axis(mglPoint(-1,-1,-1),mglPoint(1,1,1),mglPoint(0,0,0));
-
- gr->SubPlot(2,2,1);
- gr->Rotate(60,40);
- gr->Axis();
- gr->Label('x',"x");
- gr->Label('y',"y");
- gr->Label('z',"z");
- gr->Puts(mglPoint(0,0,1.5),"Axis and labels");
-
- gr->SubPlot(2,2,2);
- gr->Rotate(60,40);
- gr->SetTicks('x', 0.2); gr->SetTicks('y', 0.2);
- gr->SetTicks('z', 0.2); // too low step of ticks
- gr->Axis(mglPoint(-1,-1,-1),mglPoint(1,1,1),mglPoint(-1,-1,-1));
- gr->Axis();
- gr->Grid();
- gr->Puts(mglPoint(0,0,1.5),"Shift origin and add grid");
- gr->Puts(mglPoint(0,0,1.2),"(note, too many ticks)");
-
- gr->SubPlot(2,2,3);
- gr->Rotate(60,40);
- gr->SetTicks('x', -6); // decrease the number of ticks
- gr->SetTicks('y', -6);
- gr->Axis("yz");
- gr->Label('y',"Y axis",0);
- gr->Label('z',"Z axis",0);
- gr->Puts(mglPoint(0,0,1.5),"Remove X axis, and");
- gr->Puts(mglPoint(0,0,1.2),"decrease number of ticks");
- return 0;
- }
+int sample(mglGraph *gr)
+{
+ gr->SubPlot(2,2,0); gr->Title("Axis origin, Grid"); gr->SetOrigin(0,0);
+ gr->Axis(); gr->Grid(); gr->FPlot("x^3");
+
+ gr->SubPlot(2,2,1); gr->Title("2 axis");
+ gr->SetRanges(-1,1,-1,1); gr->SetOrigin(-1,-1,-1); // first axis
+ gr->Axis(); gr->Label('y',"axis 1",0); gr->FPlot("sin(pi*x)");
+ gr->SetRanges(0,1,0,1); gr->SetOrigin(1,1,1); // second axis
+ gr->Axis(); gr->Label('y',"axis 2",0); gr->FPlot("cos(pi*x)");
+
+ gr->SubPlot(2,2,3); gr->Title("More axis");
+ gr->SetOrigin(NAN,NAN); gr->SetRange('x',-1,1);
+ gr->Axis(); gr->Label('x',"x",0); gr->Label('y',"y_1",0); gr->FPlot("x^2","k");
+ gr->SetRanges(-1,1,-1,1); gr->SetOrigin(-1.3,-1); // second axis
+ gr->Axis("y","r"); gr->Label('y',"#r{y_2}",0.2); gr->FPlot("x^3","r");
+
+ gr->SubPlot(2,2,2); gr->Title("4 segments, inverted axis"); gr->SetOrigin(0,0);
+ gr->InPlot(0.5,1,0.5,1); gr->SetRanges(0,10,0,2); gr->Axis();
+ gr->FPlot("sqrt(x/2)"); gr->Label('x',"W",1); gr->Label('y',"U",1);
+ gr->InPlot(0,0.5,0.5,1); gr->SetRanges(1,0,0,2); gr->Axis("x");
+ gr->FPlot("sqrt(x)+x^3"); gr->Label('x',"\\tau",-1);
+ gr->InPlot(0.5,1,0,0.5); gr->SetRanges(0,10,4,0); gr->Axis("y");
+ gr->FPlot("x/4"); gr->Label('y',"L",-1);
+ gr->InPlot(0,0.5,0,0.5); gr->SetRanges(1,0,4,0); gr->FPlot("4*x^2");
+ return 0;
+}
@end verbatim
-This example shows the importance of the correct choosing of the number of ticks on axis. If tick step is too small then its text may overlap and becomes unreadable. This code has the example of @code{Label} function. It draws label for axis in specified direction. The text position on axis is specified by third argument of @code{Label} function. If it is positive then then text is drawn near the axis maximum, if negative then the same takes place near the minimum of axis, if zero - then at the center of axis.
+Note, that MathGL can draw not only single axis (which is default). But also several axis on the plot (see right plots). The idea is that the change of settings does not influence on the already drawn graphics. So, for 2-axes I setup the first axis and draw everything concerning it. Then I setup the second axis and draw things for the second axis. Generally, the similar idea allows one to draw rather complicated plot of 4 axis with different ranges (see bottom left plot).
@float
-@image{../png/sample2, 7cm}
-@caption{Example of setting up axis range and axis ticks.}
+@image{../png/axis, 11cm}
+@caption{Example of axis.}
@end float
-@c ------------------------------------------------------------------
-@node Curvilinear coordinates, Text printing example, Axis and grids, Advanced usage
-@subsection Curvilinear coordinates
+Another MathGL feature is fine ticks tunning. By default (if it is not changed by @code{SetTicks} function), MathGL try to adjust ticks positioning, so that they looks most human readable. At this, MathGL try to extract common factor for too large or too small axis ranges, as well as for too narrow ranges. Last one is non-common notation and can be disabled by @code{SetTuneTicks} function.
+Also, one can specify its own ticks with arbitrary labels by help of @code{SetTicksVal} function. Or one can set ticks in time format. In last case MathGL will try to select optimal format for labels with automatic switching between years, months/days, hours/minutes/seconds or microseconds. However, you can specify its own time representation using formats described in @url{http://www.manpagez.com/man/3/strftime/}. Most common variants are @samp{%X} for national representation of time, @samp{%x} for national representation of date, @samp{%Y} for year with century.
-Now let use curvilinear coordinates. In difference from other systems of plot creation, MathGL uses textual formulas for connection of the old (data) and new (output) coordinates. This allows one to plot in arbitrary coordinates. The following code plots the line @var{y}=0, @var{z}=0 in Cartesian, polar, parabolic and spiral coordinates:
+The sample code, demonstrated ticks feature is
@verbatim
- int sample(mglGraph *gr, void *)
- {
- mglData x(50),y(50),z(50);
- y.Fill(0.5,0.5);
- x.Fill(-1,1); // creates data arrays
-
- gr->Axis(mglPoint(-1,-1,-1),mglPoint(1,1,1),mglPoint(-1,1,-1));
- gr->dz = 0.5; // sets tick step to 0.5
+int sample(mglGraph *gr)
+{
+ gr->SubPlot(3,2,0); gr->Title("Usual axis"); gr->Axis();
+ gr->SubPlot(3,2,1); gr->Title("Too big/small range");
+ gr->SetRanges(-1000,1000,0,0.001); gr->Axis();
+ gr->SubPlot(3,2,3); gr->Title("Too narrow range");
+ gr->SetRanges(100,100.1,10,10.01); gr->Axis();
+ gr->SubPlot(3,2,4); gr->Title("Disable ticks tuning");
+ gr->SetTuneTicks(0); gr->Axis();
+
+ gr->SubPlot(3,2,2); gr->Title("Manual ticks"); gr->SetRanges(-M_PI,M_PI, 0, 2);
+ float val[]={-M_PI, -M_PI/2, 0, 0.886, M_PI/2, M_PI};
+ gr->SetTicksVal('x', mglData(6,val), "-\\pi\n-\\pi/2\n0\nx^*\n\\pi/2\n\\pi");
+ gr->Axis(); gr->Grid(); gr->FPlot("2*cos(x^2)^2", "r2");
+
+ gr->SubPlot(3,2,5); gr->Title("Time ticks"); gr->SetRange('x',0,3e5);
+ gr->SetTicksTime('x',0); gr->Axis();
+ return 0;
+}
+@end verbatim
- gr->SubPlot(2,2,0);
- gr->Rotate(60,40);
- gr->Plot(x,y,z,"r2");
- gr->Axis(); gr->Grid();
- gr->Puts(mglPoint(0,1.3,1),"Cartesian");
+@float
+@image{../png/ticks, 11cm}
+@caption{Features of axis ticks.}
+@end float
- gr->SubPlot(2,2,1);
- gr->SetFunc("y*sin(pi*x)","y*cos(pi*x)",0);
- gr->Rotate(60,40);
- gr->Plot(x,y,z,"r2");
- gr->Axis(); gr->Grid();
- gr->Puts(mglPoint(0,1.3,1),"Cylindrical");
-
- gr->SubPlot(2,2,2);
- gr->Rotate(60,40);
- gr->SetFunc("2*y*x","y*y - x*x",0);
- gr->Plot(x,y,z,"r2");
- gr->Axis(); gr->Grid();
- gr->Puts(mglPoint(0,1.3,1),"Parabolic");
-
- gr->SubPlot(2,2,3);
- gr->Rotate(60,40);
- gr->SetFunc("y*sin(pi*x)","y*cos(pi*x)","x+z");
- gr->Plot(x,y,z,"r2");
- gr->Axis(); gr->Grid();
- gr->Puts(mglPoint(0,1.3,1),"Spiral");
- return 0;
- }
+The last sample I want to show in this subsection is Log-axis. From MathGL's point of vew, the log-axis is particular case of general curvilinear coordinates. So, we need first define new coordinates (see also @ref{Curvilinear coordinates}) by help of @code{SetFunc} or @code{SetCoor} functions. At this one should wary about proper axis range. So the code looks as following:
+@verbatim
+int sample(mglGraph *gr)
+{
+ gr->SubPlot(2,2,0,"<_"); gr->Title("Semi-log axis");
+ gr->SetRanges(0.01,100,-1,1); gr->SetFunc("lg(x)","");
+ gr->Axis(); gr->Grid("xy","g"); gr->FPlot("sin(1/x)");
+ gr->Label('x',"x",0); gr->Label('y', "y = sin 1/x",0);
+
+ gr->SubPlot(2,2,1,"<_"); gr->Title("Log-log axis");
+ gr->SetRanges(0.01,100,0.1,100); gr->SetFunc("lg(x)","lg(y)");
+ gr->Axis(); gr->FPlot("sqrt(1+x^2)"); gr->Label('x',"x",0);
+ gr->Label('y', "y = \\sqrt{1+x^2}",0);
+
+ gr->SubPlot(2,2,2,"<_"); gr->Title("Minus-log axis");
+ gr->SetRanges(-100,-0.01,-100,-0.1); gr->SetFunc("-lg(-x)","-lg(-y)");
+ gr->Axis(); gr->FPlot("-sqrt(1+x^2)");
+ gr->Label('x',"x",0); gr->Label('y', "y = -\\sqrt{1+x^2}",0);
+
+ gr->SubPlot(2,2,3,"<_"); gr->Title("Log-ticks");
+ gr->SetRanges(0.1,100,0,100); gr->SetFunc("sqrt(x)","");
+ gr->Axis(); gr->FPlot("x");
+ gr->Label('x',"x",1); gr->Label('y', "y = x",0);
+ return 0;
+}
@end verbatim
@float
-@image{../png/sample3, 7cm}
-@caption{Example of curvilinear coordinates}
+@image{../png/loglog, 11cm}
+@caption{Features of axis ticks.}
@end float
+You can see that MathGL automatically switch to log-ticks as we define log-axis formula (in difference from v.1.*). Moreover, it switch to log-ticks for any formula if axis range will be large enough (see right bottom plot). Another interesting feature is that you not necessary define usual log-axis (i.e. when coordinates are positive), but you can define ``minus-log'' axis when coordinate is negative (see left bottom plot).
@c ------------------------------------------------------------------
-@node Text printing example, Animation, Curvilinear coordinates, Advanced usage
-@subsection Text printing example
+@node Curvilinear coordinates, Colorbars, Axis and ticks, Advanced usage
+@subsection Curvilinear coordinates
-MathGL prints text by vector font. There are functions for manual specifying of text position (like @code{Puts}) and for its automatic selection (like @code{Label}, @code{Legend} and so on). MathGL prints text always in specified position even if it lies outside the bounding box. The default size of font is specified by variables @var{FontSize} (@pxref{Font settings}). However, the actual size of output string depends on position of axes (depends on functions @code{SubPlot}, @code{InPlot}). The switching of the font style (italic, bold, wire and so on) can be done for the whole string (by function parameter) or inside the string. By default MathGL parses TeX-like commands for symbols and indexes (see @pxref{Font styles}). Example of MathGL font drawing is:
+As I noted in previous subsection, MathGL support curvilinear coordinates. In difference from other plotting programs and libraries, MathGL uses textual formulas for connection of the old (data) and new (output) coordinates. This allows one to plot in arbitrary coordinates. The following code plots the line @var{y}=0, @var{z}=0 in Cartesian, polar, parabolic and spiral coordinates:
@verbatim
- int sample(mglGraph *gr, void *)
- {
- setlocale(LC_CTYPE, "ru_RU.cp1251");
- gr->Puts(mglPoint(0,1),"Text can be in ASCII and in Unicode");
- gr->Puts(mglPoint(0,0.6),"It can be \\wire{wire}, \\big{big} "
- "or #r{colored}");
- gr->Puts(mglPoint(0,0.2),"One can change style in string: "
- "\\b{bold}, \\i{italic, \\b{both}}");
- gr->Puts(mglPoint(0,-0.2),"Easy to \\a{overline} or "
- "\\u{underline}");
- gr->Puts(mglPoint(0,-0.6),"Easy to change indexes "
- "^{up} _{down} @{center}");
- gr->Puts(mglPoint(0,-1),"It parse TeX: \\int \\alpha \\cdot "
- "\\sqrt3{sin(\\pi x)^2 + \\gamma_{i_k}} dx");
- return 0;
- }
+int sample(mglGraph *gr)
+{
+ gr->SetOrigin(-1,1,-1);
+
+ gr->SubPlot(2,2,0); gr->Title("Cartesian"); gr->Rotate(50,60);
+ gr->FPlot("2*t-1","0.5","0","r2");
+ gr->Axis(); gr->Grid();
+
+ gr->SetFunc("y*sin(pi*x)","y*cos(pi*x)",0);
+ gr->SubPlot(2,2,1); gr->Title("Cylindrical"); gr->Rotate(50,60);
+ gr->FPlot("2*t-1","0.5","0","r2");
+ gr->Axis(); gr->Grid();
+
+ gr->SetFunc("2*y*x","y*y - x*x",0);
+ gr->SubPlot(2,2,2); gr->Title("Parabolic"); gr->Rotate(50,60);
+ gr->FPlot("2*t-1","0.5","0","r2");
+ gr->Axis(); gr->Grid();
+
+ gr->SetFunc("y*sin(pi*x)","y*cos(pi*x)","x+z");
+ gr->SubPlot(2,2,3); gr->Title("Spiral"); gr->Rotate(50,60);
+ gr->FPlot("2*t-1","0.5","0","r2");
+ gr->Axis(); gr->Grid();
+ gr->SetFunc(0,0,0); // set to default Cartesian
+ return 0;
+}
@end verbatim
@float
-@image{../png/sample4, 7cm}
-@caption{Example of text printing with different font effects}
+@image{../png/curvcoor, 11cm}
+@caption{Example of curvilinear coordinates}
@end float
-Another example demonstrate the features of TeX formula parsing.
+
+@c ------------------------------------------------------------------
+@node Colorbars, Ternary axis, Curvilinear coordinates, Advanced usage
+@subsection Colorbars
+
+MathGL handle colorbar as special kind of axis. So, most of functions for axis and ticks setup will work for colorbar too. Colorbars can be in log-scale, and generally as arbitrary function scale; common factor of colorbar labels can be separated; and so on.
+
+But of course, there are differences -- colorbars usually located out of bounding box. At this, colorbars can be at subplot boundaries (by default), or at bounding box (if symbol @samp{I} is specified). Colorbars can handle sharp colors. And they can be located at arbitrary position too. The sample code, which demonstrate colorbar features is:
@verbatim
- int sample(mglGraph *gr, void *)
- {
- gr->Puts(mglPoint(0), "\\sqrt{\\frac{\\alpha^{\\gamma^2}+"
- "\\overset 1{\\big\\infty}}{\\sqrt3{2+b}}}", 0, -4);
- return 0;
- }
+int sample(mglGraph *gr)
+{
+ gr->SubPlot(2,2,0); gr->Title("Colorbar out of box"); gr->Box();
+ gr->Colorbar("<"); gr->Colorbar(">");
+ gr->Colorbar("_"); gr->Colorbar("^");
+
+ gr->SubPlot(2,2,1); gr->Title("Colorbar near box"); gr->Box();
+ gr->Colorbar("<I"); gr->Colorbar(">I");
+ gr->Colorbar("_I"); gr->Colorbar("^I");
+
+ gr->SubPlot(2,2,2); gr->Title("manual colors");
+ mglData a,v; mgls_prepare2d(&a,0,&v);
+ gr->Box(); gr->ContD(v,a);
+ gr->Colorbar(v,"<"); gr->Colorbar(v,">");
+ gr->Colorbar(v,"_"); gr->Colorbar(v,"^");
+
+ gr->SubPlot(2,2,3); gr->Title("log-scale");
+ gr->SetRange('c',0.01,1e3);
+ gr->Colorbar(">",0.5,0); gr->Puts(mglPoint(0,1.2),"Normal scale");
+ gr->SetFunc("","","","lg(c)");
+ gr->Colorbar(">"); gr->Puts(mglPoint(1.3,1.2),"Log scale");
+ return 0;
+}
@end verbatim
@float
-@image{../png/samplee, 7cm}
-@caption{Example of TeX formula parsing}
+@image{../png/colorbar, 11cm}
+@caption{Example of colorbars}
@end float
-Finally you can change font during execution.
+
+@c ------------------------------------------------------------------
+@node Ternary axis, Text features, Colorbars, Advanced usage
+@subsection Ternary axis
+
+There are another unusual axis types which are supported by MathGL. These are ternary and quaternary axis. Ternary axis is special axis of 3 coordinates @var{a}, @var{b}, @var{c} which satisfy relation @var{a}+@var{b}+@var{c}=1. Correspondingly, quaternary axis is special axis of 4 coordinates @var{a}, @var{b}, @var{c}, @var{d} which satisfy relation @var{a}+@var{b}+@var{c}+@var{d}=1.
+
+Generally speaking, only 2 of coordinates (3 for quaternary) are independent. So, MathGL just introduce some special transformation formulas which treat @var{a} as @samp{x}, @var{b} as @samp{y} (and @var{c} as @samp{z} for quaternary). As result, all plotting functions (curves, surfaces, contours and so on) work as usual, but in new axis. You should use @code{Ternary} function for switching to ternary/quaternary coordinates. The sample code is:
@verbatim
- int sample(mglGraph *gr, void *)
- {
- float h=1.1, d=0.25;
- gr->LoadFont("STIX"); gr->Puts(mglPoint(0,h), "default font (STIX)");
- gr->LoadFont("adventor"); gr->Puts(mglPoint(0,h-d), "adventor font");
- gr->LoadFont("bonum"); gr->Puts(mglPoint(0,h-2*d), "bonum font");
- gr->LoadFont("chorus"); gr->Puts(mglPoint(0,h-3*d), "chorus font");
- gr->LoadFont("cursor"); gr->Puts(mglPoint(0,h-4*d), "cursor font");
- gr->LoadFont("heros"); gr->Puts(mglPoint(0,h-5*d), "heros font");
- gr->LoadFont("heroscn"); gr->Puts(mglPoint(0,h-6*d), "heroscn font");
- gr->LoadFont("pagella"); gr->Puts(mglPoint(0,h-7*d), "pagella font");
- gr->LoadFont("schola"); gr->Puts(mglPoint(0,h-8*d), "schola font");
- gr->LoadFont("termes"); gr->Puts(mglPoint(0,h-9*d), "termes font");
- }
+int sample(mglGraph *gr)
+{
+ gr->SetRanges(0,1,0,1,0,1);
+ mglData x(50),y(50),z(50),rx(10),ry(10), a(20,30);
+ a.Modify("30*x*y*(1-x-y)^2*(x+y<1)");
+ x.Modify("0.25*(1+cos(2*pi*x))");
+ y.Modify("0.25*(1+sin(2*pi*x))");
+ rx.Modify("rnd"); ry.Modify("(1-v)*rnd",rx);
+ z.Modify("x");
+
+ gr->SubPlot(2,2,0); gr->Title("Ordinary axis 3D");
+ gr->Rotate(50,60); gr->Light(true);
+ gr->Plot(x,y,z,"r2"); gr->Surf(a,"BbcyrR#");
+ gr->Axis(); gr->Grid(); gr->Box();
+ gr->Label('x',"B",1); gr->Label('y',"C",1); gr->Label('z',"Z",1);
+
+ gr->SubPlot(2,2,1); gr->Title("Ternary axis (x+y+t=1)");
+ gr->Ternary(1);
+ gr->Plot(x,y,"r2"); gr->Plot(rx,ry,"q^ "); gr->Cont(a,"BbcyrR");
+ gr->Line(mglPoint(0.5,0), mglPoint(0,0.75), "g2");
+ gr->Axis(); gr->Grid("xyz","B;");
+ gr->Label('x',"B"); gr->Label('y',"C"); gr->Label('t',"A");
+
+ gr->SubPlot(2,2,2); gr->Title("Quaternary axis 3D");
+ gr->Rotate(50,60); gr->Light(true);
+ gr->Ternary(2);
+ gr->Plot(x,y,z,"r2"); gr->Surf(a,"BbcyrR#");
+ gr->Axis(); gr->Grid(); gr->Box();
+ gr->Label('t',"A",1); gr->Label('x',"B",1);
+ gr->Label('y',"C",1); gr->Label('z',"D",1);
+
+ gr->SubPlot(2,2,3); gr->Title("Ternary axis 3D");
+ gr->Rotate(50,60); gr->Light(true);
+ gr->Ternary(1);
+ gr->Plot(x,y,z,"r2"); gr->Surf(a,"BbcyrR#");
+ gr->Axis(); gr->Grid(); gr->Box();
+ gr->Label('t',"A",1); gr->Label('x',"B",1);
+ gr->Label('y',"C",1); gr->Label('z',"Z",1);
+ return 0;
+}
@end verbatim
@float
-@image{../png/fonts, 7cm}
-@caption{Example of font face changing.}
+@image{../png/ternary, 11cm}
+@caption{Example of colorbars}
@end float
@c ------------------------------------------------------------------
-@node Animation, , Text printing example, Advanced usage
-@subsection Animation
+@node Text features, Cutting sample, Ternary axis, Advanced usage
+@subsection Text features
-You can make animation by several methods in MathGL: by export in animated GIF, or by save each frame in separate file (usually JPEG) and convert these files into movie. Let me show both methods.
+MathGL prints text by vector font. There are functions for manual specifying of text position (like @code{Puts}) and for its automatic selection (like @code{Label}, @code{Legend} and so on). MathGL prints text always in specified position even if it lies outside the bounding box. The default size of font is specified by functions @var{SetFontSize*} (see @ref{Font settings}). However, the actual size of output string depends on subplot size (depends on functions @code{SubPlot}, @code{InPlot}). The switching of the font style (italic, bold, wire and so on) can be done for the whole string (by function parameter) or inside the string. By default MathGL parses TeX-like commands for symbols and indexes (see @ref{Font styles}).
-The simplest methods is making animated GIF. There are 3 steps: (1) open GIF file by @code{StartGIF()} function; (2) create the frames by calling @code{NewFrame()} before and @code{EndFrame()} after plotting; (3) close GIF by @code{CloseGIF()} function. So the simplest code for ``running'' sinusoid will look like this:
+Text can be printed as usual one (from left to right), along some direction (rotated text), or along a curve. Text can be printed on several lines, divided by new line symbol @samp{\n}.
+
+Example of MathGL font drawing is:
@verbatim
- int sample(mglGraph *gr, void *)
- {
- mglData dat(100);
- char str[32];
- gr->StartGIF("sample.gif");
- for(int i=0;i<100;i++)
- {
- gr->NewFrame(); // start frame
- gr->Box(); // some plotting
- sprintf(str,"sin(pi*x+%g*pi)",0.02*i);
- dat.Modify(str);
- gr->Plot(dat,"b");
- gr->EndFrame(); // end frame
- }
- gr->CloseGIF();
- return 0;
- }
+int sample(mglGraph *gr)
+{
+ gr->SubPlot(2,2,0,"");
+ gr->Putsw(mglPoint(0,1),L"Text can be in ASCII and in Unicode");
+ gr->Puts(mglPoint(0,0.6),"It can be \\wire{wire}, \\big{big} or #r{colored}");
+ gr->Puts(mglPoint(0,0.2),"One can change style in string: "
+ "\\b{bold}, \\i{italic, \\b{both}}");
+ gr->Puts(mglPoint(0,-0.2),"Easy to \\a{overline} or "
+ "\\u{underline}");
+ gr->Puts(mglPoint(0,-0.6),"Easy to change indexes ^{up} _{down} @{center}");
+ gr->Puts(mglPoint(0,-1),"It parse TeX: \\int \\alpha \\cdot "
+ "\\sqrt3{sin(\\pi x)^2 + \\gamma_{i_k}} dx");
+
+ gr->SubPlot(2,2,1,"");
+ gr->Puts(mglPoint(0,0.5), "\\sqrt{\\frac{\\alpha^{\\gamma^2}+\\overset 1{\\big\\infty}}{\\sqrt3{2+b}}}", "@", -4);
+ gr->Puts(mglPoint(0,-0.5),"Text can be printed\non several lines");
+
+ gr->SubPlot(2,2,2,"");
+ mglData y; mgls_prepare1d(&y);
+ gr->Box(); gr->Plot(y.SubData(-1,0));
+ gr->Text(y,"This is very very long string drawn along a curve",":k");
+ gr->Text(y,"Another string drawn above a curve","T:r");
+
+ gr->SubPlot(2,2,3,"");
+ gr->Line(mglPoint(-1,-1),mglPoint(1,-1),"rA");
+ gr->Puts(mglPoint(0,-1),mglPoint(1,-1),"Horizontal");
+ gr->Line(mglPoint(-1,-1),mglPoint(1,1),"rA");
+ gr->Puts(mglPoint(0,0),mglPoint(1,1),"At angle","@");
+ gr->Line(mglPoint(-1,-1),mglPoint(-1,1),"rA");
+ gr->Puts(mglPoint(-1,0),mglPoint(-1,1),"Vertical");
+ return 0;
+}
@end verbatim
-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 @code{WriteFrame()}. This function save each frame with automatic name @samp{frame0001.jpg, frame0002.jpg} and so on. Here prefix @samp{frame} is defined by @var{PlotId} variable of @code{mglGraph} class. So the similar code will look like this:
+@float
+@image{../png/text, 11cm}
+@caption{Example of text printing}
+@end float
+
+@c ------------------------------------------------------------------
+@node Cutting sample, , Text features, Advanced usage
+@subsection Cutting sample
+
+The last common thing which I want to show in this section is how one can cut off points from plot. There are 4 mechanism for that.
+@itemize @bullet
+@item
+You can set one of coordinate to NAN value. All points with NAN values will be omitted.
+
+@item
+You can enable cutting at edges by @code{SetCut} function. As result all points out of bounding box will be omitted.
+
+@item
+You can set cutting box by @code{SetCutBox} function. All points inside this box will be omitted.
+
+@item
+You can define cutting formula by @code{SetCutOff} function. All points for which the value of formula is nonzero will be omitted. Note, that this is the slowest variant.
+@end itemize
+
+Below I place the code which demonstrate last 3 possibilities:
@verbatim
- int sample(mglGraph *gr, void *)
- {
- mglData dat(100);
- char str[32];
- for(int i=0;i<100;i++)
- {
- gr->NewFrame(); // start frame
- gr->Box(); // some plotting
- sprintf(str,"sin(pi*x+%g*pi)",0.02*i);
- dat.Modify(str);
- gr->Plot(dat,"b");
- gr->EndFrame(); // end frame
- gr->WriteFrame(); // save frame
- }
- return 0;
- }
+int sample(mglGraph *gr)
+{
+ mglData a,c,v(1); mgls_prepare2d(&a); mgls_prepare3d(&c); v.a[0]=0.5;
+ gr->SubPlot(2,2,0); gr->Title("Cut on (default)");
+ gr->Rotate(50,60); gr->Light(true);
+ gr->Box(); gr->Surf(a,"","zrange -1 0.5");
+
+ gr->SubPlot(2,2,1); gr->Title("Cut off"); gr->Rotate(50,60);
+ gr->Box(); gr->Surf(a,"","zrange -1 0.5; cut off");
+
+ gr->SubPlot(2,2,2); gr->Title("Cut in box"); gr->Rotate(50,60);
+ gr->SetCutBox(mglPoint(0,-1,-1), mglPoint(1,0,1.1));
+ gr->Alpha(true); gr->Box(); gr->Surf3(c);
+ gr->SetCutBox(mglPoint(0), mglPoint(0)); // switch it off
+
+ gr->SubPlot(2,2,3); gr->Title("Cut by formula"); gr->Rotate(50,60);
+ gr->CutOff("(z>(x+0.5*y-1)^2-1) & (z>(x-0.5*y-1)^2-1)");
+ gr->Box(); gr->Surf3(c); gr->CutOff(""); // switch it off
+ return 0;
+}
@end verbatim
-Created files can be converted to movie by help of a lot of programs. For example, you can use ImageMagic (command @samp{convert frame*.jpg movie.mpg}), MPEG library, GIMP and so on.
+@float
+@image{../png/cut, 11cm}
+@caption{Example of point cutting}
+@end float
+
-Finally, you can use @code{mgl2gif} tool for doing the same with MGL scripts (@pxref{Utilities}).
@c ------------------------------------------------------------------
@node Data handling, Data plotting, Advanced usage, Examples
@menu
* Array creation::
+* Linking array::
* Change data::
+* User defined types::
@end menu
@c ------------------------------------------------------------------
@node Array creation, Change data, , Data handling
@subsection Array creation
+There are many ways in MathGL how data arrays can be created and filled.
+
One can put the data in @code{mglData} instance by several ways. Let us do it for sinus function:
@itemize @bullet
@item
one can create external array, fill it and put to @code{mglData} variable
@verbatim
- double *a = new double[50];
- for(int i=0;i<50;i++) a[i] = sin(M_PI*i/49.);
+ double *a = new double[50];
+ for(int i=0;i<50;i++) a[i] = sin(M_PI*i/49.);
- mglData y;
- y.Set(a,50);
+ mglData y;
+ y.Set(a,50);
@end verbatim
@item
another way is to create @code{mglData} instance of the desired size and then to work directly with data in this variable
@verbatim
- mglData y(50);
- for(int i=0;i<50;i++) y.a[i] = sin(M_PI*i/49.);
+ mglData y(50);
+ for(int i=0;i<50;i++) y.a[i] = sin(M_PI*i/49.);
@end verbatim
@item
next way is to fill the data in @code{mglData} instance by textual formula with the help of @code{Modify()} function
@verbatim
- mglData y(50);
- y.Modify("sin(pi*x)");
+ mglData y(50);
+ y.Modify("sin(pi*x)");
@end verbatim
@item
or one may fill the array in some interval and modify it later
@verbatim
- mglData y(50);
- y.Fill(0,M_PI);
- y.Modify("sin(u)");
+ mglData y(50);
+ y.Fill(0,M_PI);
+ y.Modify("sin(u)");
@end verbatim
@item
finally it can be loaded from file
@verbatim
- FILE *fp=fopen("sin.dat","wt"); // create file first
- for(int i=0;i<50;i++) fprintf(fp,"%g\n",sin(M_PI*i/49.));
- fclose(fp);
+ FILE *fp=fopen("sin.dat","wt"); // create file first
+ for(int i=0;i<50;i++) fprintf(fp,"%g\n",sin(M_PI*i/49.));
+ fclose(fp);
- mglData y("sin.dat"); // load it
+ mglData y("sin.dat"); // load it
@end verbatim
+At this you can use textual or HDF files, as well as import values from bitmap image (PNG is supported right now).
@item
at this one can read only part of data
@verbatim
- FILE *fp-fopen("sin.dat","wt"); // create large file first
- for(int i=0;i<70;i++) fprintf(fp,"%g\n",sin(M_PI*i/49.));
- fclose(fp);
+ FILE *fp-fopen("sin.dat","wt"); // create large file first
+ for(int i=0;i<70;i++) fprintf(fp,"%g\n",sin(M_PI*i/49.));
+ fclose(fp);
- mglData y;
- y.Read("sin.dat",50); // load it
+ mglData y;
+ y.Read("sin.dat",50); // load it
@end verbatim
@end itemize
Creation of 2d- and 3d-arrays is mostly the same. But one should keep in mind that class @code{mglData} uses flat data representation. For example, matrix 30*40 is presented as flat (1d-) array with length 30*40=1200 (nx=30, ny=40). The element with indexes @{i,j@} is a[i+nx*j]. So for 2d array we have:
@verbatim
- mglData z(30,40);
- for(int i=0;i<30;i++) for(int j=0;j<40;j++)
- z.a[i+30*j] = sin(M_PI*i/29.)*sin(M_PI*j/39.);
+ mglData z(30,40);
+ for(int i=0;i<30;i++) for(int j=0;j<40;j++)
+ z.a[i+30*j] = sin(M_PI*i/29.)*sin(M_PI*j/39.);
@end verbatim
or by using @code{Modify()} function
@verbatim
- mglData z(30,40);
- z.Modify("sin(pi*x)*cos(pi*y)");
+ mglData z(30,40);
+ z.Modify("sin(pi*x)*cos(pi*y)");
@end verbatim
-The only non-obvious thing here is using multidimensional arrays in C/C++, i.e. arrays defined like @code{float dat[40][30];}. Since, formaly this arrays element @code{dat[i]} can address the memory in arbitrary place you should use the proper function to convert such arrays to @code{mglData} object. For C++ this is functions like @code{mglData::Set(float **dat, int N1, int N2);}. For C this is functions like @code{mgl_data_set_float2(HMDT d, const float **dat, int N1, int N2);}. At this, you should keep in mind that @code{nx=N2} and @code{ny=N1} after conversion.
+The only non-obvious thing here is using multidimensional arrays in C/C++, i.e. arrays defined like @code{float dat[40][30];}. Since, formally these elements @code{dat[i]} can address the memory in arbitrary place you should use the proper function to convert such arrays to @code{mglData} object. For C++ this is functions like @code{mglData::Set(float **dat, int N1, int N2);}. For C this is functions like @code{mgl_data_set_float2(HMDT d, const float **dat, int N1, int N2);}. At this, you should keep in mind that @code{nx=N2} and @code{ny=N1} after conversion.
+
+@c ------------------------------------------------------------------
+@node Linking array, Change data, Array creation, Data handling
+@subsection Linking array
+
+Sometimes the data arrays are so large, that one don't need to copy its values to another array (i.e. into mglData).
+
+
+
@c ------------------------------------------------------------------
-@node Change data, , Array creation, Data handling
+@node Change data, User defined types, Linking array, Data handling
@subsection Change data
MathGL has functions for data processing: differentiating, integrating, smoothing and so on (for more detail, @pxref{Data processing}). Let us consider some examples. The simplest ones are integration and differentiation. The direction in which operation will be performed is specified by textual string, which may contain symbols @samp{x}, @samp{y} or @samp{z}. For example, the call of @code{Diff("x")} will differentiate data along @samp{x} direction; the call of @code{Integral("xy")} perform the double integration of data along @samp{x} and @samp{y} directions; the call of @code{Diff2("xyz")} will apply 3d Laplace operator to data and so on. Example of this operations on 2d array a=x*y is presented in code:
@verbatim
- int sample(mglGraph *gr, void *)
+ int sample(mglGraph *gr)
{
mglData a(30,40); a.Modify("x*y");
gr->Axis(mglPoint(0,0,0),mglPoint(1,1,1));
Data smoothing (function @code{Smooth()}) is more interesting and important. This function has 2 main arguments: type of smoothing and its direction. Now 4 methods are supported: @code{SMOOTH_NONE} does nothing for delta=0 or approaches data to zero with the step delta, @code{SMOOTH_LINE_3} linear averaging by 3 points, @code{SMOOTH_LINE_5} linear averaging by 5 points, @code{SMOOTH_QUAD_5} quadratic averaging by 5 points. Let me demonstrate it for 1d case:
@verbatim
- int sample(mglGraph *gr, void *)
+ int sample(mglGraph *gr)
{
mglData y0(30),y1,y2,y3;
y0.Modify("0.4*sin(2*pi*x)+0.3*cos(3*pi*x)-0.4*sin(4*pi*x)+0.2*rnd");
Below I shall show the features of 1D plotting on base of @code{Plot()} function (see @ref{plot}). Let us start from sinus plot:
@verbatim
- int sample(mglGraph *gr, void *)
+ int sample(mglGraph *gr)
{
mglData y0(50); y0.Modify("sin(pi*(2*x-1))");
gr->SubPlot(2,2,0);
Now I shall show the example of a surface drawing. At first let us switch lightning on
@verbatim
- int sample(mglGraph *gr, void *)
+ int sample(mglGraph *gr)
{
gr->Light(true); gr->Light(0,mglPoint(0,0,1));
@end verbatim
Drawing of other 2D plots is analogous. The only peculiarity is the usage of flag @samp{#}. By default this flag switches on the drawing of a grid on plot (@code{Grid()} or @code{Mesh()} for plots in plain or in volume). However, for isosurfaces (including surfaces of rotation @code{Axial()}) this flag switches the face drawing off. Figure becomes wired. The following code gives example of flag @samp{#} using (compare with normal function drawing as in its description):
@verbatim
- int sample(mglGraph *gr, void *)
+ int sample(mglGraph *gr)
{
gr->Alpha(true); gr->Light(true); gr->Light(0,mglPoint(0,0,1));
mglData a(30,20);
Drawing procedures for 3D plot looks similarly to 1D and 2D plots described above. There are 3 general types of 3D plots (@pxref{3D plotting}): (i) plots on slices or on projections, (ii) isosurfaces, (iii) cloud-like plots. Plots on slice are clear enough -- one specifies a slice (as its index or as coordinate value) and MathGL draws contour lines or density plot on slice plane. Isosurface gives more information. Isosurface is 3D analogue of the contour line @code{Cont()}. It shows the region where data array values exceed specified isosurface level. Plot becomes more informative if one adds transparency, lightning or sets color scheme depending on coordinates. Generalization of isosurface is the cloud-like plot. For this plot the darker color and less transparent regions correspond to higher values of data. Contrary, the regions with low values are transparent. For plotting of the phase of fields (or beams or pulses) one can use isosurface which transparency depends on the other data array (see function @code{Surf3A()}). As example of 3D data plots let us draw the Gaussian beam diffraction in space. Beam propagates along @var{x} axis:
@verbatim
- int sample(mglGraph *gr, void *)
+ int sample(mglGraph *gr)
{
gr->Alpha(true); gr->Light(true);
gr->Light(0,mglPoint(0,0,1));
@section Dual samples
@c ------------------------------------------------------------------
-@node More samples, C/Fortran interface, Dual samples, Examples
+@node More samples, Hints, Dual samples, Examples
@section More samples
@c ------------------------------------------------------------------
-@node C/Fortran interface, MathGL and PyQt, More samples, Examples
-@section C/Fortran interface
-
-The usage of pure C or Fortran or any similar interfaces (@pxref{C interface}) is practically identical to classes usage. But there are some differences. C functions must have argument HMGL (for graphics) and/or HMDT (for data arrays) which specifies the object for drawing or manipulating (changing). Fortran users may regard these variables as integer. So, firstly the user has to create this object by function mgl_create_*() and has to delete it after the using by function mgl_delete_*().
-
-Also, all arguments of C function have to be defined. So there are several functions with practically identical names doing practically the same. But some of them have simplified interface for the quick plotting and some of them have access to all plotting parameters for manual tunning.
-
-As an example of C function usage let me draw the plot from @ref{Plots for 2D data}. The C code which does it is shown below:
-@verbatim
- #include <mgl/mgl_c.h>
- int main()
- {
- HMGL gr = mgl_create_graph_zb(600, 400);
- mgl_set_alpha(gr, true);
- mgl_set_light(gr, true);
- HMDT a = mgl_create_data_size(30,20,1);
- mgl_data_modify(a,"0.6*sin(2*pi*x)*sin(3*pi*y) + 0.4*cos(3*pi*(x*y))",0);
-
- mgl_subplot(gr, 2,2,0);
- mgl_rotate(gr, 40,60,0);
- mgl_surf(gr,a,"BbcyrR#");
- mgl_box(gr, true);
- mgl_subplot(gr, 2,2,1);
- mgl_rotate(gr, 40,60,0);
- mgl_dens(gr,a,"BbcyrR#",NAN);
- mgl_box(gr, true);
- mgl_subplot(gr, 2,2,2);
- mgl_rotate(gr, 40,60,0);
- mgl_cont(gr,a,"BbcyrR#",7,NAN);
- mgl_box(gr, true);
- mgl_subplot(gr, 2,2,3);
- mgl_rotate(gr, 40,60,0);
- mgl_axial(gr,a,"BbcyrR#",3);
- mgl_box(gr, true);
-
- /* don't forgot to save graphics */
- mgl_write_png(gr,"sample.png",0);
- return 0;
- }
-@end verbatim
-
-Practically the same simple to create a window. For example let rewrite the code from for window creation (@pxref{Using FLTK/GLUT window}):
-@verbatim
- int sample(HMGL gr, void *)
- {
- mgl_rotate(gr,60,40,0);
- mgl_box(gr,1);
- return 0;
- }
- //-----------------------------------------------------
- int main(int argc,char **argv)
- {
- mgl_create_graph_fltk(sample, "MathGL examples", NULL);
- mgl_fltk_run();
- return 0;
- }
-@end verbatim
-
-The Fortran code have some peculiarities. Exactly it not allow one to send arbitrary parameter (which was @code{NULL} in previous example) to function. This is limitation of Fortran language. So, the corresponding code will be @strong{NOT TESTED NOW!!!}:
-@verbatim
- program TEST
- integer x,f,func
- call mgl_create_graph_fltk(sample, 'MathGL examples');
- call mgl_fltk_run();
- end program TEST
-
- integer function sample(gr)
- integer*8 gr
- call mgl_rotate(gr,60,40,0);
- call mgl_box(gr,1);
- sample=0
- return
- end
-@end verbatim
-
-@c ------------------------------------------------------------------
-@node MathGL and PyQt, Hints, C/Fortran interface, Examples
-@section MathGL and PyQt
-
-Generally SWIG based classes (including the Python one) are the same as C++ classes. However, there are few tips for using MathGL with PyQt. Below I place a very simple python code which demonstrate how MathGL can be used with PyQt. This code is mostly written by Prof. Dr. Heino Falcke. You can just copy it to a file @code{mgl-pyqt-test.py} and execute it from python shell by command @code{execfile("mgl-pyqt-test.py")}
-
-@verbatim
-from PyQt4 import QtGui,QtCore
-from mathgl import *
-import sys
-app = QtGui.QApplication(sys.argv)
-qpointf=QtCore.QPointF()
-
-class hfQtPlot(QtGui.QWidget):
- def __init__(self, parent=None):
- QtGui.QWidget.__init__(self, parent)
- self.img=(QtGui.QImage())
- def setgraph(self,gr):
- self.buffer='\t'
- self.buffer=self.buffer.expandtabs(4*gr.GetWidth()*gr.GetHeight())
- gr.GetBGRN(self.buffer,len(self.buffer))
- self.img=QtGui.QImage(self.buffer, gr.GetWidth(),gr.GetHeight(),QtGui.QImage.Format_ARGB32)
- self.update()
- def paintEvent(self, event):
- paint = QtGui.QPainter()
- paint.begin(self)
- paint.drawImage(qpointf,self.img)
- paint.end()
-
-BackgroundColor=[1.0,1.0,1.0]
-size=100
-gr=mglGraph()
-y=mglData(size)
-#y.Modify("((0.7*cos(2*pi*(x+.2)*500)+0.3)*(rnd*0.5+0.5)+362.135+10000.)")
-y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
-x=mglData(size)
-x.Modify("x^2");
-
-def plotpanel(gr,x,y,n):
- gr.SubPlot(2,2,n)
- gr.SetXRange(x)
- gr.SetYRange(y)
- gr.AdjustTicks()
- gr.Axis()
- gr.Box()
- gr.Label("x","x-Axis",1)
- gr.Label("y","y-Axis",1)
- gr.ClearLegend()
- gr.AddLegend("Legend: "+str(n),"k")
- gr.Legend()
- gr.Plot(x,y)
-
-
-gr.Clf(BackgroundColor[0],BackgroundColor[1],BackgroundColor[2])
-gr.SetPlotFactor(1.5)
-plotpanel(gr,x,y,0)
-y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
-plotpanel(gr,x,y,1)
-y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
-plotpanel(gr,x,y,2)
-y.Modify("(cos(2*pi*x*10)+1.1)*1000.*rnd-501")
-plotpanel(gr,x,y,3)
-
-gr.WritePNG("test.png","Test Plot")
-
-qw = hfQtPlot()
-qw.show()
-qw.setgraph(gr)
-qw.raise_()
-@end verbatim
-
-
-@c ------------------------------------------------------------------
-@node Hints, , MathGL and PyQt, Examples
+@node Hints, , More samples, Examples
@section Hints
In this section I have included some small hints and advices for the improving of the quality of plots and for the demonstration of some non-trivial features of MathGL library. In contrast to previous examples I showed mostly the idea but not the whole drawing function.