With
qwtplot3d.pro you can create a
- VC8 DLL project for WinXX environments (should even work down to VC6 projects)
- shared library for POSIX systems.
Adjust the target path and perhaps the library directories. The same
is true for the examples .pro
files.
QwtPlot3D supports Qt3 and Qt4. Older Qt versions than 3.0 are not
supported (and
will never work - especially the 2.3.0 non-commercial version for
Windows).
If I'm
wrong please don't hesitate to contact me. I'll try to provide a
code fix for Qt versions >= 3.0.?.
The library requires OpenGL >= 1.1 or equivalent and a true
color
mode with 24 or 32 bits color depth.
The API Documentation has been created using doxygen. If you
prefer to generate your own version, you will find the configuration in
./doc/Doxyfile.doxygen in
the offline
documentation.
Remark:
You can test almost all abilities of QwtPlot3D from within the
mesh2 example,
including:
- Colors, fonts, normal vectors, mouse handling etc.
- Grid and FEM data reading from files (in
data/*
)
- Output to all pixmap formats supported by Qt
- Output to vector formats supported by gl2ps
- Plotting styles and resolution change on the fly
- Shading
The
example
demonstrates vector graphics output utilizing
gl2ps. That
means EPS, PS and PDF. See
here
for an
extensive discussion. gl2ps
uses optionally
zlib for
compression. This leads to
significant smaller EPS
& PDF output and is therefore recommended. The zlib switch in
qwtplot3d.pro turns compression on or off. The default setting is OFF
for Windows and ON for all other systems.
So, it would be a good idea to get this example project up and
running
...
Calculations are performed as accurate
as
DBL_EPSILON (see your
float.h for the precise value). This is mainly due to the autoscaler.
See e.g.
here
for a topic related discussion.
Simple
Plot
//----------------------------------------------------------------- // simpleplot.cpp // // A simple example which shows how to use SurfacePlot //-----------------------------------------------------------------
#include <math.h>
#include <qapplication.h> #include <qwt3d_surfaceplot.h> #include < qwt3d_ function.h>
using namespace Qwt3D;
class Rosenbrock : public Function { public:
Rosenbrock(SurfacePlot* pw) :Function(pw) { }
double operator()(double x, double y) { return log((1-x)*(1-x) + 100 * (y - x*x)*(y - x*x)) / 8; } };
class Plot : public SurfacePlot { public: Plot(); };
Plot::Plot() { setTitle("A Simple SurfacePlot Demonstration"); Rosenbrock rosenbrock(this);
rosenbrock.setMesh(41,31); rosenbrock.setDomain(-1.73,1.5,-1.5,1.5); rosenbrock.setMinZ(-10);
rosenbrock.create();
setRotation(30,0,15); setScale(1,1,1); setShift(0.15,0,0); setZoom(0.9);
for (unsigned i=0; i!=coordinates()->axes.size(); ++i) { coordinates()->axes[i].setMajors(7); coordinates()->axes[i].setMinors(4); }
coordinates()->axes[X1].setLabelString("x-axis"); coordinates()->axes[Y1].setLabelString("y-axis"); coordinates()->axes[Z1].setLabelString(QChar (0x38f)); // Omega - see http://www.unicode.org/charts/
setCoordinateStyle(BOX);
updateData(); updateGL(); }
int main(int argc, char **argv) { QApplication a(argc, argv); Plot plot; a.setMainWidget(&plot); plot.resize(800,600); plot.show(); return a.exec(); }
|
The code above shows the almost most simple application of a
SurfacePlot. Data are provided by a mathematical function object
(Rosenbrock). You can derive from this kind of classes by
including
qwt3d_function.h.
A base for the other player
-
the widget itself - resides inside
qwt3d_surfaceplot.h.
The derived class makes only small adaptations to the standard
behaviour,
mainly providing scales and label for the axes and a boxed coordinate
system . The axes themselves are autoscaled.
Mouse
and Keyboard Handling
Try Ctrl, Shift, Alt in combination with your wheel and left
mouse button to get a clue (or use instead your cursor keys).
The base class Plot3D implements the standard mouse and keyboard
behaviour. You can
perform shifts, turns, scales and zooms with your left mouse button and
combinations of
Ctrl, Shift
and
Alt. Some
actions
have equivalents delegated to your wheel. You can also turn on or off
mouse handling entirely by using Plot3D::enableMouse () and
Plot3D::disableMouse (). The default behaviour can be changed with
Plot3D::assignMouse(). Keyboard handling has been implemented in a
similar way.
Additionally, you can determine the speed of the performed
actions when using the keyboard.
Coordinate
Systems and Axes
Axes are subdivided by major and minor tics. You have full control over
tic length and orientation and also the line width of tics and the axis
body. Furthermore, the axes provide captions and numberings. Colors,
fonts etc. of all of this parts are customizable. Additionally, all
axes
with linear scaling are autoscalable, giving them major tics at
positions which are
multiples of 1,2,5 * 10^n relative to the underlying interval. 12 axes
together form the coordinate system. It can be visualized as frame or
box
and has
the ability to autoswitch axis decoration and visibility of axes
themselves depending on the position in the 3D-space. Most axis
properties can be changed for the whole coordinate system at once or
separately for single axes. An axis is
also part of the color legend object.
Axes are highly customizable regarding label content and tic
distribution. Linear and logarithmic scales are supported by default.
Other variants, like different numbering schemes (date/time, letters
etc.) and user-defined scales are possible.
See the
'axes' project for example implementations.
Plotting
Styles
// todo
Normal
Vectors
// todo
Colors
The
Color
class operates comparable to
Function in defining
a callback operator(x,y,z) - able to assign to every single data point
a RGBA value. In many cases it is sufficient to do this in an
exclusively
z-coordinate dependent manner.To satisfy this demand, the
StandardColor
class has been provided. The class has a vector<RGBA> member and
the operator() distributes the entries equidistant between the extreme
z values of the data. The Plot3D constructor enforces as standard
behaviour a StandardColor object with 100 RGBA entries.
The mesh2 data color dialog gives a good example of changing a standard
color. The widget is a specialized Qt file
dialog for reading palette files (*) . The files include at most 256
different colors (because originally designed for 256 color graphics),
but the color vector itself (and also the file reading routine) is by
no means limited to this number. To give a plot a new color use
Plot3D::setDataColor
. Also, simple RGBA Color attributes are available for background,
axes,
meshes, labels, title etc..
*shameless stolen from the
fractint
homepage
Lighting
Some Plot3D class member encapsulate (partially) OpenGL's
lighting features. This means material and light source properties and
light source positions. You can set up to 8 different lights (OpenGL
guaranteed minimum). Beware, that some calculations become very slow in
this case. Lighting is considered
experimental at this
moment, and works not yet in a completely precise way. This will be
fixed in the future.
Fonts
etc.
All Fonts available for Qt are also provided for screen representation
(including Unicode) and pixmap output. A special question concerns
output in
vector formats. At the moment I
have no plans in supporting FreeType or similar solutions. But you can
still use the gl2ps provided mixed TeX-EPS/PDF variant, producing
pretty satisfying results.
Enrichments
Generally spoken, an Enrichment provides additional visual objects
depending on data properties. Furthermore, the base class has been well
embedded in the plots framework to draw these objects in a reasonable
efficient manner. Enrichments come in six flavors: vertex-, edge-,
face-, voxel-, graph- and widget-driven (the term 'graph' refers to the
data
object as a whole). Widget Enrichments are somewhat special, because
they describe entities outside the data object. In future
versions they will also gather things like title and legends. The
variants 2)-6) are
future work, but
the yet implemented vertex based Enrichments are still remarkable
powerful:
The primary impulse came from the wish
to add some small objects (esp. marker etc.) at dedicated positions to
the plot. The result is surprisingly more far-reaching. The screenshot
shows an
entire new plotting
style utilizing Vertex Enrichments. The small red-white
marker objects are part of the generating Enrichment
object as well as the bars themselves. Beginning with version 0.2.3
QwtPlot3D supports user defined plotting styles. But not enough,
Plot3D provides a container allowing the injection of arbitrary
Enrichments also in other contexts. See the class documentation for
closer explanation. The
example/enrichment directory
contains the application from which the screenshot has been obtained.
Text, Legends
// todo
Mesh Types
// todo
Input/Output
File I/O in QwtPlot3D works in one of the following ways:
a)
Define a global
function:
bool MyHandler(Plot3D* plot,
QString const& fname)
{
SurfacePlot* tmpplot = (SurfacePlot*)plot;
// ... do your in- or output here
return true;
}
b)
... or an enhanced
version - a Functor:
class
MyHandler :
public IO::Functor
{
public:
bool some_modifier;
void adaptMyBehaviour();
// The next both must be implemented:
Functor* clone() const
{
// The framework assumes the
destruction,
// so provide a heap based object
here
return new MyHandler(you_name_it);
}
bool operator()(Plot3D* plot, QString const&
fname)
{
// Do highly complex I/O-things here
}
};
In any case the new function/functor has to be registered by one of the
following static functions:
bool IO::defineInputHandler(
QString
const& format, Functor const& func)
bool IO::defineInputHandler( QString const& format, Function func)
The same procedure applies to the
output variants. If you
wish to modify the
behaviour later, you can either replace the actual handler with a
second
call to define...Handler() conveying a fresh function/functor or - in
the case of a functor -
manipulate the yet installed object:
MyHandler* own_format_handler =
(MyHandler*)IO::outputHandler("OWN");
if (
own_format_handler
)
own_format_handler->
adaptMyBehaviour()
;
// ...
Pre-defined
output
handler for all of the QImageIO pixmap formats are available, in
addition
a functor for PDF, PS and EPS
output (see also
here).
Data Input
QwtPlot3D supports one general and some special forms of native data
input:
Generic:
A general approach has been provided in form of the 3 SurfacePlot
member:
bool |
loadFromData(double
**data, unsigned int columns, unsigned int rows, double minx,
double maxx, double miny, double maxy) |
bool |
loadFromData(Qwt3D::Triple
**data, unsigned int columns, unsigned int rows, bool uperiodic=false,
bool vperiodic=false) |
bool |
loadFromData(Qwt3D::TripleField
const &data, Qwt3D::CellField
const &poly) |
The 3 functions in this order have ascending generality:
- The first one deals with data on top of
plane grids: z=f(x,y) ;
- The 2nd form maps also deformed rectangular grids x=f(u,v),
y=g(u,v), z=h(u,v) u and v can be periodic - both or
one of them.
- The last variant eventually provides
support for more free formed meshs, divided in a node- (the TripleField
argument) and a polygon- (the CellField) part. This kind of
data is common for FEM and CAD applications but not limited to them. It
is the 'swiss knife' because it is of course able to represent all the
other variants. The question here is performance (still not too bad).
Mathematical
Functions & Parametric Surfaces:
Setup a function object. To do so, inherit from the Function class and
write your own version of
Function::operator()(double
x, double y). Set
the domain and perhaps limitations for the range and call
Function::create(). Thats
all.See also Function and the implementation
of concrete functions in 'examples'. Parametric surfaces are
generalizations of functions. In a similar way,
ParameterSurface::operator()(double u,
double v) must be replaced. (u,v) domains might have rotational
symmetry. The drawing routines of SurfacePlot are aware of this,
if you provide the necessary information with
ParametricSurface::setPeriodic().
Grid data
files:
jk:11051895-17021986
MESH
327 466
557726 567506
5.10821e+006 5.12216e+006
682 682 682 682 912 924 928 928 932 ...
... element[327*466-1]
Coding example:
Reading of the aforementioned file type, utilizing the first of the
above mentioned functions.
See NativeReader for additional information. Write your own reader
classes in this spirit. It should always be enough to provide
appropriate data for SurfacePlot::loadFromData.
bool NativeReader::operator()(Plot3D* plot, QString const& fname, QString const& format) { FILE* file; unsigned int xmesh, ymesh; double minx, maxx, miny, maxy; if ( !collectInfo(file, fname, xmesh, ymesh, minx, maxx, miny, maxy) ) return false; /* allocate some space for the mesh */ double** data = allocateData(xmesh, ymesh);
for (unsigned int j = 0; j < ymesh; j++) { for (unsigned int i = 0; i < xmesh; i++) { if (fscanf(file, "%lf", &data[i][j]) != 1) { fprintf(stderr, "NativeReader::read: error in data file \"%s\"\n", (const char*)fname.local8Bit()); return false; }
if (data[i][j] > maxz_) data[i][j] = maxz_; else if (data[i][j] < minz_) data[i][j] = minz_; } }
/* close the file */ fclose(file);
((SurfacePlot*)plot)->loadFromData(data, xmesh, ymesh, minx, maxx, miny, maxy); deleteData(data,xmesh);
return true; }
|
Data Output
// todo
Examples
All the examples can be found in the
examples
subdirectory,
executables are gathered in the
examples/bin
directory.
simpleplot
|
The almost most simple plot
possible
|
autoswitch
|
Demonstrates the autoswitching
of axes, and the parallel use of 2 plot widgets in a splitter windows.
|
axes
|
Manipulation of axes
parts, like tics, labeling (including the application of user-defined
numbering); Positioning for labels; Nonlinear scales
|
enrichments
|
The running version from the Enrichment discussion.
|
mesh2
|
Main example. It includes (most
of) the other features not found in specialized examples. There are
still things, hidden in the API. There is a thesis.tex file under the
sources of mesh2. It can be used to produce complete output (esp.
vectorized numbering etc.) in connection with the libraries PDF and PS
output facilities.
|