[qwtplot3d] 35/39: New upstream version 0.2.7+svn191+gcc7

Andreas Tille tille at debian.org
Mon Dec 25 10:30:05 UTC 2017


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository qwtplot3d.

commit 348615c015785bc71eaf9f338af258d2d75ee873
Author: Andreas Tille <tille at debian.org>
Date:   Mon Dec 25 11:20:59 2017 +0100

    New upstream version 0.2.7+svn191+gcc7
---
 3rdparty/gl2ps/COPYING.GL2PS                       |   25 +
 3rdparty/gl2ps/COPYING.LGPL                        |  482 ++
 3rdparty/gl2ps/gl2ps.c                             | 5986 ++++++++++++++++++++
 3rdparty/gl2ps/gl2ps.h                             |  199 +
 COPYING                                            |   23 +
 debian/README.Debian                               |   27 -
 debian/changelog                                   |  147 -
 debian/compat                                      |    1 -
 debian/control                                     |   52 -
 debian/copyright                                   |   72 -
 debian/libqwtplot3d-doc.doc-base                   |    9 -
 debian/libqwtplot3d-doc.examples                   |    1 -
 debian/libqwtplot3d-doc.install                    |    1 -
 debian/libqwtplot3d-qt5-0.install                  |    1 -
 debian/libqwtplot3d-qt5-0.symbols                  |  604 --
 debian/libqwtplot3d-qt5-dev.install                |    2 -
 debian/patches/01_makefile.patch                   |  125 -
 debian/patches/02_examples_include.patch           |  132 -
 debian/patches/03_fix_ftbs.patch                   |   18 -
 debian/patches/04_hardening.patch                  |   15 -
 debian/patches/series                              |    4 -
 debian/rules                                       |   40 -
 debian/source/format                               |    1 -
 debian/watch                                       |    4 -
 doc/Doxyfile.doxygen                               |  227 +
 doc/footer.html                                    |    7 +
 doc/web/navigation/doxygen.css                     |  176 +
 doc/web/navigation/doxygen.png                     |  Bin 0 -> 2352 bytes
 doc/web/navigation/menu.css                        |   12 +
 doc/web/navigation/sflogo.png                      |  Bin 0 -> 2112 bytes
 dsp.bat                                            |    2 +
 examples/autoswitch/autoswitch.cpp                 |  102 +
 examples/autoswitch/autoswitch.h                   |   58 +
 examples/autoswitch/autoswitch.pro                 |    4 +
 examples/axes/axes.pro                             |   15 +
 examples/axes/src/axes.h                           |   75 +
 examples/axes/src/axesmainwindow.cpp               |  245 +
 examples/axes/src/axesmainwindow.h                 |   64 +
 examples/axes/src/axesmainwindowbase.ui            |  243 +
 examples/axes/src/axesmainwindowbase4.ui           |  295 +
 examples/axes/src/main.cpp                         |   31 +
 examples/box.png                                   |  Bin 0 -> 533 bytes
 examples/common.pro                                |   37 +
 examples/dsp.bat                                   |   12 +
 examples/enrichments/enrichments.pro               |   16 +
 examples/enrichments/src/enrichmentmainwindow.cpp  |  147 +
 examples/enrichments/src/enrichmentmainwindow.h    |   57 +
 .../enrichments/src/enrichmentmainwindowbase.ui    |  215 +
 .../enrichments/src/enrichmentmainwindowbase4.ui   |  167 +
 examples/enrichments/src/enrichments.cpp           |  150 +
 examples/enrichments/src/enrichments.h             |   31 +
 examples/enrichments/src/main.cpp                  |   30 +
 examples/examples.pro                              |   10 +
 examples/examples.sln                              |   43 +
 examples/filecell.png                              |  Bin 0 -> 975 bytes
 examples/fileopen.png                              |  Bin 0 -> 178 bytes
 examples/filledmesh.png                            |  Bin 0 -> 918 bytes
 examples/floordata.png                             |  Bin 0 -> 292 bytes
 examples/floorempty.png                            |  Bin 0 -> 213 bytes
 examples/flooriso.png                              |  Bin 0 -> 297 bytes
 examples/floormesh.png                             |  Bin 0 -> 248 bytes
 examples/frame.png                                 |  Bin 0 -> 290 bytes
 examples/grid.png                                  |  Bin 0 -> 527 bytes
 examples/gridb.png                                 |  Bin 0 -> 1001 bytes
 examples/gridc.png                                 |  Bin 0 -> 820 bytes
 examples/gridf.png                                 |  Bin 0 -> 890 bytes
 examples/gridfr.png                                |  Bin 0 -> 969 bytes
 examples/gridl.png                                 |  Bin 0 -> 877 bytes
 examples/gridr.png                                 |  Bin 0 -> 799 bytes
 examples/hiddenline.png                            |  Bin 0 -> 1014 bytes
 examples/icon.gif                                  |  Bin 0 -> 1168 bytes
 examples/icon.ico                                  |  Bin 0 -> 2238 bytes
 examples/icon.png                                  |  Bin 0 -> 1369 bytes
 examples/icon.rc                                   |    1 +
 examples/images.qrc                                |   31 +
 examples/mesh2/mesh2.pro                           |   25 +
 examples/mesh2/src/colormapreader.cpp              |   81 +
 examples/mesh2/src/colormapreader.h                |   28 +
 examples/mesh2/src/designerworkaround.cpp          |  146 +
 examples/mesh2/src/designerworkaround.h            |   76 +
 examples/mesh2/src/femreader.h                     |   83 +
 examples/mesh2/src/functions.h                     |  214 +
 examples/mesh2/src/lightingdlg.cpp                 |  220 +
 examples/mesh2/src/lightingdlg.h                   |  100 +
 examples/mesh2/src/lightingdlgbase.ui              |  361 ++
 examples/mesh2/src/lightingdlgbase4.ui             |  293 +
 examples/mesh2/src/lightingdlgbaseimpl.cpp         |   22 +
 examples/mesh2/src/lightingdlgbaseimpl.h           |   15 +
 examples/mesh2/src/main.cpp                        |   32 +
 examples/mesh2/src/mesh.cpp                        |   57 +
 examples/mesh2/src/mesh2mainwindow.cpp             |  956 ++++
 examples/mesh2/src/mesh2mainwindow.h               |  134 +
 examples/mesh2/src/mesh2mainwindowbase.ui          | 1728 ++++++
 examples/mesh2/src/mesh2mainwindowbase4.ui         |  479 ++
 examples/mesh2/src/thesis.tex                      |    9 +
 examples/movie.png                                 |  Bin 0 -> 1260 bytes
 examples/nodata.png                                |  Bin 0 -> 824 bytes
 examples/none.png                                  |  Bin 0 -> 487 bytes
 examples/normals.png                               |  Bin 0 -> 1344 bytes
 examples/polygon.png                               |  Bin 0 -> 733 bytes
 examples/qwtplot.png                               |  Bin 0 -> 543 bytes
 examples/savecontent.png                           |  Bin 0 -> 550 bytes
 examples/scattered.png                             |  Bin 0 -> 479 bytes
 examples/simpleplot/simpleplot.cpp                 |   83 +
 examples/simpleplot/simpleplot.pro                 |    3 +
 examples/wireframe.png                             |  Bin 0 -> 1119 bytes
 include/qwt3d_autoptr.h                            |   75 +
 include/qwt3d_autoscaler.h                         |   51 +
 include/qwt3d_axis.h                               |  131 +
 include/qwt3d_color.h                              |   63 +
 include/qwt3d_colorlegend.h                        |   77 +
 include/qwt3d_coordsys.h                           |  100 +
 include/qwt3d_drawable.h                           |   66 +
 include/qwt3d_enrichment.h                         |   62 +
 include/qwt3d_enrichment_std.h                     |  116 +
 include/qwt3d_function.h                           |   41 +
 include/qwt3d_global.h                             |   58 +
 include/qwt3d_graphplot.h                          |   24 +
 include/qwt3d_gridmapping.h                        |   34 +
 include/qwt3d_helper.h                             |   36 +
 include/qwt3d_io.h                                 |  141 +
 include/qwt3d_io_gl2ps.h                           |   91 +
 include/qwt3d_io_reader.h                          |   35 +
 include/qwt3d_label.h                              |   80 +
 include/qwt3d_mapping.h                            |   27 +
 include/qwt3d_multiplot.h                          |   24 +
 include/qwt3d_openglhelper.h                       |  130 +
 include/qwt3d_parametricsurface.h                  |   44 +
 include/qwt3d_plot.h                               |  315 +
 include/qwt3d_portability.h                        |   91 +
 include/qwt3d_scale.h                              |   87 +
 include/qwt3d_surfaceplot.h                        |  132 +
 include/qwt3d_types.h                              |  455 ++
 include/qwt3d_volumeplot.h                         |   24 +
 lingua_de.ts                                       |   10 +
 qwtplot3d.pro                                      |   95 +
 scripts/fixvc7.py                                  |   16 +
 scripts/makedistro.py                              |   67 +
 scripts/makedocu.py                                |   36 +
 scripts/qwtplot3d.supp                             |   17 +
 scripts/valgr.sh                                   |    1 +
 src/qwt3d_autoscaler.cpp                           |  253 +
 src/qwt3d_axis.cpp                                 |  386 ++
 src/qwt3d_color.cpp                                |   63 +
 src/qwt3d_colorlegend.cpp                          |  223 +
 src/qwt3d_coordsys.cpp                             |  633 +++
 src/qwt3d_dataviews.cpp                            |   10 +
 src/qwt3d_drawable.cpp                             |  140 +
 src/qwt3d_enrichment_std.cpp                       |  347 ++
 src/qwt3d_function.cpp                             |  101 +
 src/qwt3d_gridmapping.cpp                          |   32 +
 src/qwt3d_gridplot.cpp                             |  596 ++
 src/qwt3d_io.cpp                                   |  365 ++
 src/qwt3d_io_gl2ps.cpp                             |  409 ++
 src/qwt3d_io_reader.cpp                            |  225 +
 src/qwt3d_label.cpp                                |  287 +
 src/qwt3d_lighting.cpp                             |  192 +
 src/qwt3d_meshplot.cpp                             |  320 ++
 src/qwt3d_mousekeyboard.cpp                        |  387 ++
 src/qwt3d_movements.cpp                            |  106 +
 src/qwt3d_parametricsurface.cpp                    |  104 +
 src/qwt3d_plot.cpp                                 |  498 ++
 src/qwt3d_scale.cpp                                |  304 +
 src/qwt3d_surfaceplot.cpp                          |  183 +
 src/qwt3d_types.cpp                                |  222 +
 165 files changed, 23601 insertions(+), 1256 deletions(-)

diff --git a/3rdparty/gl2ps/COPYING.GL2PS b/3rdparty/gl2ps/COPYING.GL2PS
new file mode 100644
index 0000000..ff08f6d
--- /dev/null
+++ b/3rdparty/gl2ps/COPYING.GL2PS
@@ -0,0 +1,25 @@
+
+                           GL2PS LICENSE
+                      Version 2, November 2003
+
+              Copyright (C) 2003, Christophe Geuzaine
+
+Permission to use, copy, and distribute this software and its
+documentation for any purpose with or without fee is hereby granted,
+provided that the copyright notice appear in all copies and that both
+that copyright notice and this permission notice appear in supporting
+documentation.
+
+Permission to modify and distribute modified versions of this software
+is granted, provided that:
+
+1) the modifications are licensed under the same terms as this
+software;
+
+2) you make available the source code of any modifications that you
+distribute, either on the same media as you distribute any executable
+or other form of this software, or via a mechanism generally accepted
+in the software development community for the electronic transfer of
+data.
+
+This software is provided "as is" without express or implied warranty.
diff --git a/3rdparty/gl2ps/COPYING.LGPL b/3rdparty/gl2ps/COPYING.LGPL
new file mode 100644
index 0000000..8bc654b
--- /dev/null
+++ b/3rdparty/gl2ps/COPYING.LGPL
@@ -0,0 +1,482 @@
+
+                  GNU LIBRARY GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+                    675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+

+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+

+                  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+

+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+

+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+

+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+

+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+

+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+

+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+

+     Appendix: How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/3rdparty/gl2ps/gl2ps.c b/3rdparty/gl2ps/gl2ps.c
new file mode 100644
index 0000000..6073dfa
--- /dev/null
+++ b/3rdparty/gl2ps/gl2ps.c
@@ -0,0 +1,5986 @@
+/* $Id: gl2ps.c 188 2007-08-19 15:51:12Z krischnamurti $ */
+/*
+ * GL2PS, an OpenGL to PostScript Printing Library
+ * Copyright (C) 1999-2006 Christophe Geuzaine <geuz at geuz.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of either:
+ *
+ * a) the GNU Library General Public License as published by the Free
+ * Software Foundation, either version 2 of the License, or (at your
+ * option) any later version; or
+ *
+ * b) the GL2PS License as published by Christophe Geuzaine, either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See either
+ * the GNU Library General Public License or the GL2PS License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library in the file named "COPYING.LGPL";
+ * if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+ * Cambridge, MA 02139, USA.
+ *
+ * You should have received a copy of the GL2PS License with this
+ * library in the file named "COPYING.GL2PS"; if not, I will be glad
+ * to provide one.
+ *
+ * Contributors:
+ *   Michael Sweet <mike at easysw.com>
+ *   Marc Ume <marc.ume at digitalgraphics.be>
+ *   Jean-Francois Remacle <remacle at gce.ucl.ac.be>
+ *   Bart Kaptein <B.L.Kaptein at lumc.nl>
+ *   Quy Nguyen-Dai <quy at nguyendai.org>
+ *   Sam Buss <sbuss at ucsd.edu>
+ *   Shane Hill <Shane.Hill at dsto.defence.gov.au>
+ *   Romain Boman <r_boman at yahoo.fr>
+ *   Rouben Rostamian <rostamian at umbc.edu>
+ *   Diego Santa Cruz <Diego.SantaCruz at epfl.ch>
+ *   Shahzad Muzaffar <Shahzad.Muzaffar at cern.ch>
+ *   Lassi Tuura <lassi.tuura at cern.ch>
+ *   Guy Barrand <barrand at lal.in2p3.fr>
+ *   Prabhu Ramachandran <prabhu at aero.iitm.ernet.in>
+ *   Micha Bieber <bieber at traits.de>
+ *   Olivier Couet <couet at mail.cern.ch>
+ *   Shai Ayal <shaiay at gmail.com>
+ *   Fabian Wenzel <wenzel at tu-harburg.de>
+ *   Ian D. Gay <gay at sfu.ca>
+ *   Cosmin Truta <cosmin at cs.toronto.edu>
+ *   Baiju Devani <b.devani at gmail.com>
+ *   Alexander Danilov <danilov at lanl.gov>
+ *
+ * For the latest info about gl2ps, see http://www.geuz.org/gl2ps/.
+ * Please report all bugs and problems to <gl2ps at geuz.org>.
+ */
+
+#include "gl2ps.h"
+
+#include <math.h>
+#include <string.h>
+#include <sys/types.h>
+#include <stdarg.h>
+#include <time.h>
+#include <float.h>
+
+#if defined(GL2PS_HAVE_ZLIB)
+#include <zlib.h>
+#endif
+
+#if defined(GL2PS_HAVE_LIBPNG)
+#include <png.h>
+#endif
+
+/********************************************************************* 
+ *
+ * Private definitions, data structures and prototypes
+ *
+ *********************************************************************/
+
+/* Magic numbers (assuming that the order of magnitude of window
+   coordinates is 10^3) */
+
+#define GL2PS_EPSILON       5.0e-3F
+#define GL2PS_ZSCALE        1000.0F
+#define GL2PS_ZOFFSET       5.0e-2F
+#define GL2PS_ZOFFSET_LARGE 20.0F
+#define GL2PS_ZERO(arg)     (fabs(arg) < 1.e-20)
+
+/* Primitive types */
+
+#define GL2PS_NO_TYPE          -1
+#define GL2PS_TEXT             1
+#define GL2PS_POINT            2
+#define GL2PS_LINE             3
+#define GL2PS_QUADRANGLE       4
+#define GL2PS_TRIANGLE         5
+#define GL2PS_PIXMAP           6
+#define GL2PS_IMAGEMAP         7
+#define GL2PS_IMAGEMAP_WRITTEN 8
+#define GL2PS_IMAGEMAP_VISIBLE 9
+#define GL2PS_SPECIAL          10
+
+/* BSP tree primitive comparison */
+
+#define GL2PS_COINCIDENT  1
+#define GL2PS_IN_FRONT_OF 2
+#define GL2PS_IN_BACK_OF  3
+#define GL2PS_SPANNING    4
+
+/* 2D BSP tree primitive comparison */
+
+#define GL2PS_POINT_COINCIDENT 0
+#define GL2PS_POINT_INFRONT    1
+#define GL2PS_POINT_BACK       2
+
+/* Internal feedback buffer pass-through tokens */
+
+#define GL2PS_BEGIN_OFFSET_TOKEN   1
+#define GL2PS_END_OFFSET_TOKEN     2
+#define GL2PS_BEGIN_BOUNDARY_TOKEN 3
+#define GL2PS_END_BOUNDARY_TOKEN   4
+#define GL2PS_BEGIN_STIPPLE_TOKEN  5
+#define GL2PS_END_STIPPLE_TOKEN    6
+#define GL2PS_POINT_SIZE_TOKEN     7
+#define GL2PS_LINE_WIDTH_TOKEN     8
+#define GL2PS_BEGIN_BLEND_TOKEN    9
+#define GL2PS_END_BLEND_TOKEN      10
+#define GL2PS_SRC_BLEND_TOKEN      11
+#define GL2PS_DST_BLEND_TOKEN      12
+#define GL2PS_IMAGEMAP_TOKEN       13
+#define GL2PS_DRAW_PIXELS_TOKEN    14
+#define GL2PS_TEXT_TOKEN           15
+
+typedef enum {
+  T_UNDEFINED    = -1,
+  T_CONST_COLOR  = 1,
+  T_VAR_COLOR    = 1<<1,
+  T_ALPHA_1      = 1<<2,
+  T_ALPHA_LESS_1 = 1<<3,
+  T_VAR_ALPHA    = 1<<4
+} GL2PS_TRIANGLE_PROPERTY;
+
+typedef GLfloat GL2PSxyz[3];
+typedef GLfloat GL2PSplane[4];
+
+typedef struct _GL2PSbsptree2d GL2PSbsptree2d;
+
+struct _GL2PSbsptree2d {
+  GL2PSplane plane;
+  GL2PSbsptree2d *front, *back;
+};
+
+typedef struct {
+  GLint nmax, size, incr, n;
+  char *array;
+} GL2PSlist;
+
+typedef struct _GL2PSbsptree GL2PSbsptree;
+
+struct _GL2PSbsptree {
+  GL2PSplane plane;
+  GL2PSlist *primitives;
+  GL2PSbsptree *front, *back;
+};
+
+typedef struct {
+  GL2PSxyz xyz;
+  GL2PSrgba rgba;
+} GL2PSvertex;
+
+typedef struct {
+  GL2PSvertex vertex[3];
+  int prop;
+} GL2PStriangle;
+
+typedef struct {
+  GLshort fontsize;
+  char *str, *fontname;
+  /* Note: for a 'special' string, 'alignment' holds the format
+     (PostScript, PDF, etc.) of the special string */
+  GLint alignment;
+  GLfloat angle;
+} GL2PSstring;
+
+typedef struct {
+  GLsizei width, height;
+  /* Note: for an imagemap, 'type' indicates if it has already been
+     written to the file or not, and 'format' indicates if it is
+     visible or not */
+  GLenum format, type;
+  GLfloat *pixels;
+} GL2PSimage;
+
+typedef struct _GL2PSimagemap GL2PSimagemap;
+
+struct _GL2PSimagemap {
+  GL2PSimage *image;
+  GL2PSimagemap *next;
+};
+
+typedef struct {
+  GLshort type, numverts;
+  GLushort pattern;
+  char boundary, offset, culled;
+  GLint factor;
+  GLfloat width;
+  GL2PSvertex *verts;
+  union {
+    GL2PSstring *text;
+    GL2PSimage *image;
+  } data;
+} GL2PSprimitive;
+
+typedef struct {
+#if defined(GL2PS_HAVE_ZLIB)
+  Bytef *dest, *src, *start;
+  uLongf destLen, srcLen;
+#else
+  int dummy;
+#endif
+} GL2PScompress;
+
+typedef struct{
+  GL2PSlist* ptrlist;
+  int gsno, fontno, imno, shno, maskshno, trgroupno;
+  int gsobjno, fontobjno, imobjno, shobjno, maskshobjno, trgroupobjno;
+} GL2PSpdfgroup;
+
+typedef struct {
+  /* General */
+  GLint format, sort, options, colorsize, colormode, buffersize;
+  char *title, *producer, *filename;
+  GLboolean boundary, blending;
+  GLfloat *feedback, offset[2], lastlinewidth;
+  GLint viewport[4], blendfunc[2], lastfactor;
+  GL2PSrgba *colormap, lastrgba, threshold, bgcolor;
+  GLushort lastpattern;
+  GL2PSvertex lastvertex;
+  GL2PSlist *primitives, *auxprimitives;
+  FILE *stream;
+  GL2PScompress *compress;
+  GLboolean header;
+
+  /* BSP-specific */
+  GLint maxbestroot;
+
+  /* Occlusion culling-specific */
+  GLboolean zerosurfacearea;
+  GL2PSbsptree2d *imagetree;
+  GL2PSprimitive *primitivetoadd;
+  
+  /* PDF-specific */
+  int streamlength;
+  GL2PSlist *pdfprimlist, *pdfgrouplist;
+  int *xreflist;
+  int objects_stack; /* available objects */
+  int extgs_stack; /* graphics state object number */
+  int font_stack; /* font object number */
+  int im_stack; /* image object number */
+  int trgroupobjects_stack; /* xobject numbers */
+  int shader_stack; /* shader object numbers */
+  int mshader_stack; /* mask shader object numbers */
+
+  /* for image map list */
+  GL2PSimagemap *imagemap_head;
+  GL2PSimagemap *imagemap_tail;
+} GL2PScontext;
+
+typedef struct {
+  void  (*printHeader)(void);
+  void  (*printFooter)(void);
+  void  (*beginViewport)(GLint viewport[4]);
+  GLint (*endViewport)(void);
+  void  (*printPrimitive)(void *data);
+  void  (*printFinalPrimitive)(void);
+  const char *file_extension;
+  const char *description;
+} GL2PSbackend;
+
+/* The gl2ps context. gl2ps is not thread safe (we should create a
+   local GL2PScontext during gl2psBeginPage) */
+
+static GL2PScontext *gl2ps = NULL;
+
+/* Need to forward-declare this one */
+
+static GLint gl2psPrintPrimitives(void);
+
+/********************************************************************* 
+ *
+ * Utility routines
+ *
+ *********************************************************************/
+
+static void gl2psMsg(GLint level, const char *fmt, ...)
+{
+  va_list args;
+
+  if(!(gl2ps->options & GL2PS_SILENT)){
+    switch(level){
+    case GL2PS_INFO : fprintf(stderr, "GL2PS info: "); break;
+    case GL2PS_WARNING : fprintf(stderr, "GL2PS warning: "); break;
+    case GL2PS_ERROR : fprintf(stderr, "GL2PS error: "); break;
+    }
+    va_start(args, fmt);
+    vfprintf(stderr, fmt, args); 
+    va_end(args);
+    fprintf(stderr, "\n");
+  }
+  /* if(level == GL2PS_ERROR) exit(1); */
+}
+
+static void *gl2psMalloc(size_t size)
+{
+  void *ptr;
+
+  if(!size) return(NULL);
+  ptr = malloc(size);
+  if(!ptr){
+    gl2psMsg(GL2PS_ERROR, "Couldn't allocate requested memory");
+    exit(1);
+  }
+  return(ptr);
+}
+
+static void *gl2psRealloc(void *ptr, size_t size)
+{
+  if(!size) return(NULL);
+  ptr = realloc(ptr, size);
+  if(!ptr){
+    gl2psMsg(GL2PS_ERROR, "Couldn't reallocate requested memory");
+    exit(1);
+  }
+  return(ptr);
+}
+
+static void gl2psFree(void *ptr)
+{
+  if(!ptr) return;
+  free(ptr);
+}
+
+static size_t gl2psWriteBigEndian(unsigned long data, size_t bytes)
+{
+  size_t i;
+  size_t size = sizeof(unsigned long);
+  for(i = 1; i <= bytes; ++i){
+    fputc(0xff & (data >> (size-i) * 8), gl2ps->stream);
+  }
+  return bytes;
+}
+
+/* zlib compression helper routines */
+
+#if defined(GL2PS_HAVE_ZLIB)
+
+static void gl2psSetupCompress(void)
+{
+  gl2ps->compress = (GL2PScompress*)gl2psMalloc(sizeof(GL2PScompress));
+  gl2ps->compress->src = NULL;
+  gl2ps->compress->start = NULL;
+  gl2ps->compress->dest = NULL;
+  gl2ps->compress->srcLen = 0;
+  gl2ps->compress->destLen = 0;
+}
+
+static void gl2psFreeCompress(void)
+{
+  if(!gl2ps->compress)
+    return;
+  gl2psFree(gl2ps->compress->start);
+  gl2psFree(gl2ps->compress->dest);
+  gl2ps->compress->src = NULL;
+  gl2ps->compress->start = NULL;
+  gl2ps->compress->dest = NULL;
+  gl2ps->compress->srcLen = 0;
+  gl2ps->compress->destLen = 0;
+}
+
+static int gl2psAllocCompress(unsigned int srcsize)
+{
+  gl2psFreeCompress();
+  
+  if(!gl2ps->compress || !srcsize)
+    return GL2PS_ERROR;
+  
+  gl2ps->compress->srcLen = srcsize;
+  gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
+  gl2ps->compress->src = (Bytef*)gl2psMalloc(gl2ps->compress->srcLen);
+  gl2ps->compress->start = gl2ps->compress->src;
+  gl2ps->compress->dest = (Bytef*)gl2psMalloc(gl2ps->compress->destLen);
+  
+  return GL2PS_SUCCESS;
+}
+
+static void *gl2psReallocCompress(unsigned int srcsize)
+{
+  if(!gl2ps->compress || !srcsize)
+    return NULL;
+  
+  if(srcsize < gl2ps->compress->srcLen)
+    return gl2ps->compress->start;
+  
+  gl2ps->compress->srcLen = srcsize;
+  gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
+  gl2ps->compress->src = (Bytef*)gl2psRealloc(gl2ps->compress->src, 
+                                              gl2ps->compress->srcLen);
+  gl2ps->compress->start = gl2ps->compress->src;
+  gl2ps->compress->dest = (Bytef*)gl2psRealloc(gl2ps->compress->dest, 
+                                               gl2ps->compress->destLen);
+  
+  return gl2ps->compress->start;
+}
+
+static size_t gl2psWriteBigEndianCompress(unsigned long data, size_t bytes)
+{
+  size_t i;
+  size_t size = sizeof(unsigned long);
+  for(i = 1; i <= bytes; ++i){
+    *gl2ps->compress->src = (Bytef)(0xff & (data >> (size-i) * 8));
+    ++gl2ps->compress->src;
+  }
+  return bytes;
+}
+
+static int gl2psDeflate(void)
+{
+  /* For compatibility with older zlib versions, we use compress(...)
+     instead of compress2(..., Z_BEST_COMPRESSION) */
+  return compress(gl2ps->compress->dest, &gl2ps->compress->destLen, 
+                  gl2ps->compress->start, gl2ps->compress->srcLen);  
+}
+
+#endif
+
+static int gl2psPrintf(const char* fmt, ...)
+{
+  int ret;
+  va_list args;
+
+#if defined(GL2PS_HAVE_ZLIB)
+  unsigned int oldsize = 0;
+  static char buf[1000];
+  if(gl2ps->options & GL2PS_COMPRESS){
+    va_start(args, fmt);
+    ret = vsprintf(buf, fmt, args);
+    va_end(args);
+    oldsize = gl2ps->compress->srcLen;
+    gl2ps->compress->start = (Bytef*)gl2psReallocCompress(oldsize + ret);
+    memcpy(gl2ps->compress->start+oldsize, buf, ret);
+    ret = 0;
+  }
+  else{
+#endif
+    va_start(args, fmt);
+    ret = vfprintf(gl2ps->stream, fmt, args);
+    va_end(args);
+#if defined(GL2PS_HAVE_ZLIB)
+  }
+#endif
+  return ret;
+}
+
+static void gl2psPrintGzipHeader()
+{
+#if defined(GL2PS_HAVE_ZLIB)
+  char tmp[10] = {'\x1f', '\x8b', /* magic numbers: 0x1f, 0x8b */
+                  8, /* compression method: Z_DEFLATED */
+                  0, /* flags */
+                  0, 0, 0, 0, /* time */
+                  2, /* extra flags: max compression */
+                  '\x03'}; /* OS code: 0x03 (Unix) */
+
+  if(gl2ps->options & GL2PS_COMPRESS){
+    gl2psSetupCompress();
+    /* add the gzip file header */
+    fwrite(tmp, 10, 1, gl2ps->stream);
+  }
+#endif  
+}
+
+static void gl2psPrintGzipFooter()
+{
+#if defined(GL2PS_HAVE_ZLIB)
+  int n;
+  uLong crc, len;
+  char tmp[8];
+
+  if(gl2ps->options & GL2PS_COMPRESS){
+    if(Z_OK != gl2psDeflate()){
+      gl2psMsg(GL2PS_ERROR, "Zlib deflate error");
+    }
+    else{
+      /* determine the length of the header in the zlib stream */
+      n = 2; /* CMF+FLG */
+      if(gl2ps->compress->dest[1] & (1<<5)){
+        n += 4; /* DICTID */
+      }
+      /* write the data, without the zlib header and footer */
+      fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4), 
+             1, gl2ps->stream);
+      /* add the gzip file footer */
+      crc = crc32(0L, gl2ps->compress->start, gl2ps->compress->srcLen);
+      for(n = 0; n < 4; ++n){
+        tmp[n] = (char)(crc & 0xff);
+        crc >>= 8;
+      }
+      len = gl2ps->compress->srcLen;
+      for(n = 4; n < 8; ++n){
+        tmp[n] = (char)(len & 0xff);
+        len >>= 8;
+      }
+      fwrite(tmp, 8, 1, gl2ps->stream);
+    }
+    gl2psFreeCompress();
+    gl2psFree(gl2ps->compress);
+    gl2ps->compress = NULL;
+  }
+#endif 
+}
+
+/* The list handling routines */
+
+static void gl2psListRealloc(GL2PSlist *list, GLint n)
+{
+  if(!list){
+    gl2psMsg(GL2PS_ERROR, "Cannot reallocate NULL list");
+    return;
+  }
+  if(n <= 0) return;
+  if(!list->array){
+    list->nmax = n;
+    list->array = (char*)gl2psMalloc(list->nmax * list->size);
+  }
+  else{
+    if(n > list->nmax){
+      list->nmax = ((n - 1) / list->incr + 1) * list->incr;
+      list->array = (char*)gl2psRealloc(list->array,
+                                        list->nmax * list->size);
+    }
+  }
+}
+
+static GL2PSlist *gl2psListCreate(GLint n, GLint incr, GLint size)
+{
+  GL2PSlist *list;
+
+  if(n < 0) n = 0;
+  if(incr <= 0) incr = 1;
+  list = (GL2PSlist*)gl2psMalloc(sizeof(GL2PSlist));
+  list->nmax = 0;
+  list->incr = incr;
+  list->size = size;
+  list->n = 0;
+  list->array = NULL;
+  gl2psListRealloc(list, n);
+  return(list);
+}
+
+static void gl2psListReset(GL2PSlist *list)
+{
+  if(!list) return;
+  list->n = 0;
+}
+
+static void gl2psListDelete(GL2PSlist *list)
+{
+  if(!list) return;  
+  gl2psFree(list->array);
+  gl2psFree(list);
+}
+
+static void gl2psListAdd(GL2PSlist *list, void *data)
+{
+  if(!list){
+    gl2psMsg(GL2PS_ERROR, "Cannot add into unallocated list");
+    return;
+  }
+  list->n++;
+  gl2psListRealloc(list, list->n);
+  memcpy(&list->array[(list->n - 1) * list->size], data, list->size);
+}
+
+static int gl2psListNbr(GL2PSlist *list)
+{
+  if(!list)
+    return 0;
+  return(list->n);
+}
+
+static void *gl2psListPointer(GL2PSlist *list, GLint index)
+{
+  if(!list){
+    gl2psMsg(GL2PS_ERROR, "Cannot point into unallocated list");
+    return NULL;
+  }
+  if((index < 0) || (index >= list->n)){
+    gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListPointer");
+    return NULL;
+  }
+  return(&list->array[index * list->size]);
+}
+
+static void gl2psListSort(GL2PSlist *list,
+                          int (*fcmp)(const void *a, const void *b))
+{
+  if(!list)
+    return;
+  qsort(list->array, list->n, list->size, fcmp);
+}
+
+static void gl2psListAction(GL2PSlist *list, void (*action)(void *data))
+{
+  GLint i;
+
+  for(i = 0; i < gl2psListNbr(list); i++){
+    (*action)(gl2psListPointer(list, i));
+  }
+}
+
+static void gl2psListActionInverse(GL2PSlist *list, void (*action)(void *data))
+{
+  GLint i;
+
+  for(i = gl2psListNbr(list); i > 0; i--){
+    (*action)(gl2psListPointer(list, i-1));
+  }
+}
+
+#if defined(GL2PS_HAVE_LIBPNG)
+
+static void gl2psListRead(GL2PSlist *list, int index, void *data)
+{
+  if((index < 0) || (index >= list->n))
+    gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListRead");
+  memcpy(data, &list->array[index * list->size], list->size);
+}
+
+static void gl2psEncodeBase64Block(unsigned char in[3], unsigned char out[4], int len)
+{
+  static const char cb64[] = 
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+  out[0] = cb64[ in[0] >> 2 ];
+  out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
+  out[2] = (len > 1) ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=';
+  out[3] = (len > 2) ? cb64[ in[2] & 0x3f ] : '=';
+}
+
+static void gl2psListEncodeBase64(GL2PSlist *list)
+{
+  unsigned char *buffer, in[3], out[4];
+  int i, n, index, len;
+
+  n = list->n * list->size;
+  buffer = (unsigned char*)gl2psMalloc(n * sizeof(unsigned char));
+  memcpy(buffer, list->array, n * sizeof(unsigned char));
+  gl2psListReset(list);
+
+  index = 0;
+  while(index < n) {
+    len = 0;
+    for(i = 0; i < 3; i++) {
+      if(index < n){
+        in[i] = buffer[index];
+        len++;
+      }
+      else{
+        in[i] = 0;
+      }
+      index++;
+    }
+    if(len) {
+      gl2psEncodeBase64Block(in, out, len);
+      for(i = 0; i < 4; i++)
+        gl2psListAdd(list, &out[i]);
+    }
+  }
+  gl2psFree(buffer);
+}
+
+#endif
+
+/* Helpers for rgba colors */
+
+static GLboolean gl2psSameColor(GL2PSrgba rgba1, GL2PSrgba rgba2)
+{
+  if(!GL2PS_ZERO(rgba1[0] - rgba2[0]) ||
+     !GL2PS_ZERO(rgba1[1] - rgba2[1]) ||
+     !GL2PS_ZERO(rgba1[2] - rgba2[2]))
+    return GL_FALSE;
+  return GL_TRUE;
+}
+  
+static GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim)
+{
+  int i;
+
+  for(i = 1; i < prim->numverts; i++){
+    if(!gl2psSameColor(prim->verts[0].rgba, prim->verts[i].rgba)){
+      return GL_FALSE;
+    }
+  }
+  return GL_TRUE;
+}
+
+static GLboolean gl2psSameColorThreshold(int n, GL2PSrgba rgba[],
+                                         GL2PSrgba threshold)
+{
+  int i;
+
+  if(n < 2) return GL_TRUE;
+  
+  for(i = 1; i < n; i++){
+    if(fabs(rgba[0][0] - rgba[i][0]) > threshold[0] ||
+       fabs(rgba[0][1] - rgba[i][1]) > threshold[1] ||
+       fabs(rgba[0][2] - rgba[i][2]) > threshold[2])
+      return GL_FALSE;
+  }
+  
+  return GL_TRUE;
+}
+
+static void gl2psSetLastColor(GL2PSrgba rgba)
+{
+  int i;        
+  for(i = 0; i < 3; ++i){
+    gl2ps->lastrgba[i] = rgba[i];
+  }
+}
+
+static GLfloat gl2psGetRGB(GL2PSimage *im, GLuint x, GLuint y,
+                           GLfloat *red, GLfloat *green, GLfloat *blue)
+{
+  
+  GLsizei width = im->width;
+  GLsizei height = im->height;
+  GLfloat *pixels = im->pixels;
+  GLfloat *pimag;
+
+  /* OpenGL image is from down to up, PS image is up to down */  
+  switch(im->format){
+  case GL_RGBA:
+    pimag = pixels + 4 * (width * (height - 1 - y) + x);
+    break;
+  case GL_RGB:
+  default:
+    pimag = pixels + 3 * (width * (height - 1 - y) + x);
+    break;
+  }
+  *red = *pimag; pimag++;
+  *green = *pimag; pimag++;
+  *blue = *pimag; pimag++;
+
+  return (im->format == GL_RGBA) ? *pimag : 1.0F;
+}
+
+/* Helper routines for pixmaps */
+
+static GL2PSimage *gl2psCopyPixmap(GL2PSimage *im)
+{
+  int size;
+  GL2PSimage *image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
+  
+  image->width = im->width;
+  image->height = im->height;
+  image->format = im->format;
+  image->type = im->type;
+
+  switch(image->format){
+  case GL_RGBA:
+    size = image->height * image->width * 4 * sizeof(GLfloat);
+    break;
+  case GL_RGB:
+  default:
+    size = image->height * image->width * 3 * sizeof(GLfloat);
+    break;
+  }
+
+  image->pixels = (GLfloat*)gl2psMalloc(size);
+  memcpy(image->pixels, im->pixels, size);
+  
+  return image;
+}
+
+static void gl2psFreePixmap(GL2PSimage *im)
+{
+  if(!im)
+    return;
+  gl2psFree(im->pixels);
+  gl2psFree(im);
+}
+
+#if defined(GL2PS_HAVE_LIBPNG)
+
+#if !defined(png_jmpbuf)
+#  define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#endif
+
+static void gl2psUserWritePNG(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+  unsigned int i;
+  GL2PSlist *png = (GL2PSlist*)png_get_io_ptr(png_ptr);
+  for(i = 0; i < length; i++) 
+    gl2psListAdd(png, &data[i]);
+}
+
+static void gl2psUserFlushPNG(png_structp png_ptr)
+{
+}
+
+static void gl2psConvertPixmapToPNG(GL2PSimage *pixmap, GL2PSlist *png)
+{
+  png_structp png_ptr;
+  png_infop info_ptr;
+  unsigned char *row_data;
+  GLfloat dr, dg, db;
+  int row, col;
+
+  if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
+    return;
+  
+  if(!(info_ptr = png_create_info_struct(png_ptr))){
+    png_destroy_write_struct(&png_ptr, NULL);
+    return;
+  }
+  
+  if(setjmp(png_jmpbuf(png_ptr))) {
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return;
+  }
+  
+  png_set_write_fn(png_ptr, (void *)png, gl2psUserWritePNG, gl2psUserFlushPNG);
+  png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
+  png_set_IHDR(png_ptr, info_ptr, pixmap->width, pixmap->height, 8, 
+               PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, 
+               PNG_FILTER_TYPE_BASE);
+  png_write_info(png_ptr, info_ptr);
+
+  row_data = (unsigned char*)gl2psMalloc(3 * pixmap->width * sizeof(unsigned char));
+  for(row = 0; row < pixmap->height; row++){
+    for(col = 0; col < pixmap->width; col++){
+      gl2psGetRGB(pixmap, col, row, &dr, &dg, &db);
+      row_data[3*col] = (unsigned char)(255. * dr);
+      row_data[3*col+1] = (unsigned char)(255. * dg);
+      row_data[3*col+2] = (unsigned char)(255. * db);
+    }
+    png_write_row(png_ptr, (png_bytep)row_data);
+  }
+  gl2psFree(row_data);
+
+  png_write_end(png_ptr, info_ptr);
+  png_destroy_write_struct(&png_ptr, &info_ptr);
+}
+
+#endif
+
+/* Helper routines for text strings */
+
+static GLint gl2psAddText(GLint type, const char *str, const char *fontname, 
+                          GLshort fontsize, GLint alignment, GLfloat angle)
+{
+  GLfloat pos[4];
+  GL2PSprimitive *prim;
+  GLboolean valid;
+
+  if(!gl2ps || !str || !fontname) return GL2PS_UNINITIALIZED;
+
+  if(gl2ps->options & GL2PS_NO_TEXT) return GL2PS_SUCCESS;
+
+  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
+  if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
+
+  glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
+
+  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+  prim->type = type;
+  prim->boundary = 0;
+  prim->numverts = 1;
+  prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
+  prim->verts[0].xyz[0] = pos[0];
+  prim->verts[0].xyz[1] = pos[1];
+  prim->verts[0].xyz[2] = pos[2];
+  prim->culled = 0;
+  prim->offset = 0;
+  prim->pattern = 0;
+  prim->factor = 0;
+  prim->width = 1;
+  glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
+  prim->data.text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
+  prim->data.text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char));
+  strcpy(prim->data.text->str, str); 
+  prim->data.text->fontname = (char*)gl2psMalloc((strlen(fontname)+1)*sizeof(char));
+  strcpy(prim->data.text->fontname, fontname);
+  prim->data.text->fontsize = fontsize;
+  prim->data.text->alignment = alignment;
+  prim->data.text->angle = angle;
+
+  gl2psListAdd(gl2ps->auxprimitives, &prim);
+  glPassThrough(GL2PS_TEXT_TOKEN);
+    
+  return GL2PS_SUCCESS;
+}
+
+static GL2PSstring *gl2psCopyText(GL2PSstring *t)
+{
+  GL2PSstring *text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
+  text->str = (char*)gl2psMalloc((strlen(t->str)+1)*sizeof(char));
+  strcpy(text->str, t->str); 
+  text->fontname = (char*)gl2psMalloc((strlen(t->fontname)+1)*sizeof(char));
+  strcpy(text->fontname, t->fontname);
+  text->fontsize = t->fontsize;
+  text->alignment = t->alignment;
+  text->angle = t->angle;
+  
+  return text;
+}
+
+static void gl2psFreeText(GL2PSstring *text)
+{
+  if(!text)
+    return;
+  gl2psFree(text->str);
+  gl2psFree(text->fontname);
+  gl2psFree(text);
+}
+
+/* Helpers for blending modes */
+
+static GLboolean gl2psSupportedBlendMode(GLenum sfactor, GLenum dfactor)
+{
+  /* returns TRUE if gl2ps supports the argument combination: only two
+     blending modes have been implemented so far */
+
+  if( (sfactor == GL_SRC_ALPHA && dfactor == GL_ONE_MINUS_SRC_ALPHA) || 
+      (sfactor == GL_ONE && dfactor == GL_ZERO) )
+    return GL_TRUE;
+  return GL_FALSE;
+}
+
+static void gl2psAdaptVertexForBlending(GL2PSvertex *v)
+{
+  /* Transforms vertex depending on the actual blending function -
+     currently the vertex v is considered as source vertex and his
+     alpha value is changed to 1.0 if source blending GL_ONE is
+     active. This might be extended in the future */
+
+  if(!v || !gl2ps)
+    return;
+
+  if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){
+    v->rgba[3] = 1.0F;
+    return;
+  }
+  
+  switch(gl2ps->blendfunc[0]){
+  case GL_ONE:
+    v->rgba[3] = 1.0F;
+    break;
+  default:
+    break;
+  }
+}
+
+static void gl2psAssignTriangleProperties(GL2PStriangle *t)
+{
+  /* int i; */
+
+  t->prop = T_VAR_COLOR;
+
+  /* Uncommenting the following lines activates an even more fine
+     grained distinction between triangle types - please don't delete,
+     a remarkable amount of PDF handling code inside this file depends
+     on it if activated */
+  /*
+  t->prop = T_CONST_COLOR;    
+  for(i = 0; i < 3; ++i){
+    if(!GL2PS_ZERO(t->vertex[0].rgba[i] - t->vertex[1].rgba[i]) || 
+       !GL2PS_ZERO(t->vertex[1].rgba[i] - t->vertex[2].rgba[i])){
+      t->prop = T_VAR_COLOR;
+      break;
+    }
+  }
+  */
+
+  if(!GL2PS_ZERO(t->vertex[0].rgba[3] - t->vertex[1].rgba[3]) || 
+     !GL2PS_ZERO(t->vertex[1].rgba[3] - t->vertex[2].rgba[3])){
+    t->prop |= T_VAR_ALPHA;
+  }
+  else{
+    if(t->vertex[0].rgba[3] < 1)
+      t->prop |= T_ALPHA_LESS_1;
+    else
+      t->prop |= T_ALPHA_1;
+  }
+}
+
+static void gl2psFillTriangleFromPrimitive(GL2PStriangle *t, GL2PSprimitive *p,
+                                           GLboolean assignprops)
+{
+  t->vertex[0] = p->verts[0];
+  t->vertex[1] = p->verts[1];
+  t->vertex[2] = p->verts[2];
+  if(GL_TRUE == assignprops)
+    gl2psAssignTriangleProperties(t);
+}
+
+static void gl2psInitTriangle(GL2PStriangle *t)
+{
+  int i;
+  GL2PSvertex vertex = { {-1.0F, -1.0F, -1.0F}, {-1.0F, -1.0F, -1.0F, -1.0F} };
+  for(i = 0; i < 3; i++)
+    t->vertex[i] = vertex;
+  t->prop = T_UNDEFINED;
+}
+
+/* Miscellaneous helper routines */
+
+static GL2PSprimitive *gl2psCopyPrimitive(GL2PSprimitive *p)
+{
+  GL2PSprimitive *prim;
+
+  if(!p){
+    gl2psMsg(GL2PS_ERROR, "Trying to copy an empty primitive");
+    return NULL;
+  }
+
+  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+  
+  prim->type = p->type;
+  prim->numverts = p->numverts;
+  prim->boundary = p->boundary;
+  prim->offset = p->offset;
+  prim->pattern = p->pattern;
+  prim->factor = p->factor;
+  prim->culled = p->culled;
+  prim->width = p->width;
+  prim->verts = (GL2PSvertex*)gl2psMalloc(p->numverts*sizeof(GL2PSvertex));
+  memcpy(prim->verts, p->verts, p->numverts * sizeof(GL2PSvertex));
+
+  switch(prim->type){
+  case GL2PS_PIXMAP :
+    prim->data.image = gl2psCopyPixmap(p->data.image);
+    break;
+  case GL2PS_TEXT :
+  case GL2PS_SPECIAL :
+    prim->data.text = gl2psCopyText(p->data.text);
+    break;
+  default:
+    break;
+  }
+
+  return prim;
+}
+
+static GLboolean gl2psSamePosition(GL2PSxyz p1, GL2PSxyz p2)
+{
+  if(!GL2PS_ZERO(p1[0] - p2[0]) ||
+     !GL2PS_ZERO(p1[1] - p2[1]) ||
+     !GL2PS_ZERO(p1[2] - p2[2]))
+    return GL_FALSE;
+  return GL_TRUE;
+}
+
+/********************************************************************* 
+ *
+ * 3D sorting routines 
+ *
+ *********************************************************************/
+
+static GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane)
+{
+  return(plane[0] * point[0] + 
+         plane[1] * point[1] + 
+         plane[2] * point[2] + 
+         plane[3]);
+}
+
+static GLfloat gl2psPsca(GLfloat *a, GLfloat *b)
+{
+  return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
+}
+
+static void gl2psPvec(GLfloat *a, GLfloat *b, GLfloat *c)
+{
+  c[0] = a[1]*b[2] - a[2]*b[1];
+  c[1] = a[2]*b[0] - a[0]*b[2];
+  c[2] = a[0]*b[1] - a[1]*b[0];
+}
+
+static GLfloat gl2psNorm(GLfloat *a)
+{
+  return (GLfloat)sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
+}
+
+static void gl2psGetNormal(GLfloat *a, GLfloat *b, GLfloat *c)
+{
+  GLfloat norm;
+
+  gl2psPvec(a, b, c);
+  if(!GL2PS_ZERO(norm = gl2psNorm(c))){
+    c[0] = c[0] / norm;
+    c[1] = c[1] / norm;
+    c[2] = c[2] / norm;
+  }
+  else{
+    /* The plane is still wrong despite our tests in gl2psGetPlane.
+       Let's return a dummy value for now (this is a hack: we should
+       do more intelligent tests in GetPlane) */
+    c[0] = c[1] = 0.0F;
+    c[2] = 1.0F;
+  }
+}
+
+static void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane)
+{
+  GL2PSxyz v = {0.0F, 0.0F, 0.0F}, w = {0.0F, 0.0F, 0.0F};
+
+  switch(prim->type){
+  case GL2PS_TRIANGLE :
+  case GL2PS_QUADRANGLE :
+    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0]; 
+    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1]; 
+    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2]; 
+    w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0]; 
+    w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1]; 
+    w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2]; 
+    if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) || 
+       (GL2PS_ZERO(w[0]) && GL2PS_ZERO(w[1]) && GL2PS_ZERO(w[2]))){
+      plane[0] = plane[1] = 0.0F;
+      plane[2] = 1.0F;
+      plane[3] = -prim->verts[0].xyz[2];
+    }
+    else{
+      gl2psGetNormal(v, w, plane);
+      plane[3] = 
+        - plane[0] * prim->verts[0].xyz[0] 
+        - plane[1] * prim->verts[0].xyz[1] 
+        - plane[2] * prim->verts[0].xyz[2];
+    }
+    break;
+  case GL2PS_LINE :
+    v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0]; 
+    v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1]; 
+    v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2]; 
+    if(GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])){
+      plane[0] = plane[1] = 0.0F;
+      plane[2] = 1.0F;
+      plane[3] = -prim->verts[0].xyz[2];
+    }
+    else{
+      if(GL2PS_ZERO(v[0]))      w[0] = 1.0F;
+      else if(GL2PS_ZERO(v[1])) w[1] = 1.0F;
+      else                      w[2] = 1.0F;
+      gl2psGetNormal(v, w, plane);
+      plane[3] = 
+        - plane[0] * prim->verts[0].xyz[0] 
+        - plane[1] * prim->verts[0].xyz[1] 
+        - plane[2] * prim->verts[0].xyz[2];
+    }
+    break;
+  case GL2PS_POINT :
+  case GL2PS_PIXMAP :
+  case GL2PS_TEXT :
+  case GL2PS_SPECIAL :
+  case GL2PS_IMAGEMAP:
+    plane[0] = plane[1] = 0.0F;
+    plane[2] = 1.0F;
+    plane[3] = -prim->verts[0].xyz[2];
+    break;
+  default :
+    gl2psMsg(GL2PS_ERROR, "Unknown primitive type in BSP tree");
+    plane[0] = plane[1] = plane[3] = 0.0F;
+    plane[2] = 1.0F;
+    break;
+  }
+}
+
+static void gl2psCutEdge(GL2PSvertex *a, GL2PSvertex *b, GL2PSplane plane,
+                         GL2PSvertex *c)
+{
+  GL2PSxyz v;
+  GLfloat sect;
+
+  v[0] = b->xyz[0] - a->xyz[0];
+  v[1] = b->xyz[1] - a->xyz[1];
+  v[2] = b->xyz[2] - a->xyz[2];
+
+  sect = - gl2psComparePointPlane(a->xyz, plane) / gl2psPsca(plane, v);
+
+  c->xyz[0] = a->xyz[0] + v[0] * sect;
+  c->xyz[1] = a->xyz[1] + v[1] * sect;
+  c->xyz[2] = a->xyz[2] + v[2] * sect;
+  
+  c->rgba[0] = (1 - sect) * a->rgba[0] + sect * b->rgba[0];
+  c->rgba[1] = (1 - sect) * a->rgba[1] + sect * b->rgba[1];
+  c->rgba[2] = (1 - sect) * a->rgba[2] + sect * b->rgba[2];
+  c->rgba[3] = (1 - sect) * a->rgba[3] + sect * b->rgba[3];
+}
+
+static void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane,
+                                      GL2PSprimitive *child, GLshort numverts,
+                                      GLshort *index0, GLshort *index1)
+{
+  GLshort i;
+
+  if(parent->type == GL2PS_IMAGEMAP){
+    child->type = GL2PS_IMAGEMAP;
+    child->data.image = parent->data.image;
+  }
+  else{
+    if(numverts > 4){
+      gl2psMsg(GL2PS_WARNING, "%d vertices in polygon", numverts);
+      numverts = 4;
+    }
+    switch(numverts){
+    case 1 : child->type = GL2PS_POINT; break; 
+    case 2 : child->type = GL2PS_LINE; break; 
+    case 3 : child->type = GL2PS_TRIANGLE; break; 
+    case 4 : child->type = GL2PS_QUADRANGLE; break;    
+    default: child->type = GL2PS_NO_TYPE; break;
+    }
+  }
+
+  child->boundary = 0; /* FIXME: not done! */
+  child->culled = parent->culled;
+  child->offset = parent->offset;
+  child->pattern = parent->pattern;
+  child->factor = parent->factor;
+  child->width = parent->width;
+  child->numverts = numverts;
+  child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
+
+  for(i = 0; i < numverts; i++){
+    if(index1[i] < 0){
+      child->verts[i] = parent->verts[index0[i]];
+    }
+    else{
+      gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]], 
+                   plane, &child->verts[i]);
+    }
+  }
+}
+
+static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb, 
+                          GLshort i, GLshort j)
+{
+  GLint k;
+
+  for(k = 0; k < *nb; k++){
+    if((index0[k] == i && index1[k] == j) ||
+       (index1[k] == i && index0[k] == j)) return;
+  }
+  index0[*nb] = i;
+  index1[*nb] = j;
+  (*nb)++;
+}
+
+static GLshort gl2psGetIndex(GLshort i, GLshort num)
+{
+  return (i < num - 1) ? i + 1 : 0;
+}
+
+static GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane)
+{
+  GLint type = GL2PS_COINCIDENT;
+  GLshort i, j;
+  GLfloat d[5]; 
+
+  for(i = 0; i < prim->numverts; i++){  
+    d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
+  }
+
+  if(prim->numverts < 2){
+    return 0;
+  }
+  else{
+    for(i = 0; i < prim->numverts; i++){
+      j = gl2psGetIndex(i, prim->numverts);
+      if(d[j] > GL2PS_EPSILON){
+        if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
+        else if(type != GL2PS_IN_BACK_OF) return 1; 
+        if(d[i] < -GL2PS_EPSILON)         return 1;
+      }
+      else if(d[j] < -GL2PS_EPSILON){
+        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;   
+        else if(type != GL2PS_IN_FRONT_OF) return 1;
+        if(d[i] > GL2PS_EPSILON)           return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+static GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane, 
+                                 GL2PSprimitive **front, GL2PSprimitive **back)
+{
+  GLshort i, j, in = 0, out = 0, in0[5], in1[5], out0[5], out1[5];
+  GLint type;
+  GLfloat d[5]; 
+
+  type = GL2PS_COINCIDENT;
+
+  for(i = 0; i < prim->numverts; i++){  
+    d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
+  }
+
+  switch(prim->type){
+  case GL2PS_POINT :
+    if(d[0] > GL2PS_EPSILON)       type = GL2PS_IN_BACK_OF;
+    else if(d[0] < -GL2PS_EPSILON) type = GL2PS_IN_FRONT_OF;
+    else                           type = GL2PS_COINCIDENT;
+    break;
+  default :
+    for(i = 0; i < prim->numverts; i++){
+      j = gl2psGetIndex(i, prim->numverts);
+      if(d[j] > GL2PS_EPSILON){
+        if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
+        else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING; 
+        if(d[i] < -GL2PS_EPSILON){
+          gl2psAddIndex(in0, in1, &in, i, j);
+          gl2psAddIndex(out0, out1, &out, i, j);
+          type = GL2PS_SPANNING;
+        }
+        gl2psAddIndex(out0, out1, &out, j, -1);
+      }
+      else if(d[j] < -GL2PS_EPSILON){
+        if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;   
+        else if(type != GL2PS_IN_FRONT_OF) type = GL2PS_SPANNING;
+        if(d[i] > GL2PS_EPSILON){
+          gl2psAddIndex(in0, in1, &in, i, j);
+          gl2psAddIndex(out0, out1, &out, i, j);
+          type = GL2PS_SPANNING;
+        }
+        gl2psAddIndex(in0, in1, &in, j, -1);
+      }
+      else{
+        gl2psAddIndex(in0, in1, &in, j, -1);
+        gl2psAddIndex(out0, out1, &out, j, -1);
+      }
+    }
+    break;
+  }
+
+  if(type == GL2PS_SPANNING){
+    *back = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+    *front = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+    gl2psCreateSplitPrimitive(prim, plane, *back, out, out0, out1);
+    gl2psCreateSplitPrimitive(prim, plane, *front, in, in0, in1);
+  }
+
+  return type;
+}
+
+static void gl2psDivideQuad(GL2PSprimitive *quad, 
+                            GL2PSprimitive **t1, GL2PSprimitive **t2)
+{
+  *t1 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+  *t2 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+  (*t1)->type = (*t2)->type = GL2PS_TRIANGLE;
+  (*t1)->numverts = (*t2)->numverts = 3;
+  (*t1)->culled = (*t2)->culled = quad->culled;
+  (*t1)->offset = (*t2)->offset = quad->offset;
+  (*t1)->pattern = (*t2)->pattern = quad->pattern;
+  (*t1)->factor = (*t2)->factor = quad->factor;
+  (*t1)->width = (*t2)->width = quad->width;
+  (*t1)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex));
+  (*t2)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex));
+  (*t1)->verts[0] = quad->verts[0];
+  (*t1)->verts[1] = quad->verts[1];
+  (*t1)->verts[2] = quad->verts[2];
+  (*t1)->boundary = ((quad->boundary & 1) ? 1 : 0) | ((quad->boundary & 2) ? 2 : 0);
+  (*t2)->verts[0] = quad->verts[0];
+  (*t2)->verts[1] = quad->verts[2];
+  (*t2)->verts[2] = quad->verts[3];
+  (*t1)->boundary = ((quad->boundary & 4) ? 2 : 0) | ((quad->boundary & 4) ? 2 : 0);
+}
+
+static int gl2psCompareDepth(const void *a, const void *b)
+{
+  GL2PSprimitive *q, *w;
+  GLfloat dq = 0.0F, dw = 0.0F, diff;
+  int i;
+  
+  q = *(GL2PSprimitive**)a;
+  w = *(GL2PSprimitive**)b;
+
+  for(i = 0; i < q->numverts; i++){
+    dq += q->verts[i].xyz[2]; 
+  }
+  dq /= (GLfloat)q->numverts;
+
+  for(i = 0; i < w->numverts; i++){
+    dw += w->verts[i].xyz[2]; 
+  }
+  dw /= (GLfloat)w->numverts;
+
+  diff = dq - dw;
+  if(diff > 0.){
+    return -1;
+  }
+  else if(diff < 0.){
+    return 1;
+  }
+  else{
+    return 0;
+  }
+}
+
+static int gl2psTrianglesFirst(const void *a, const void *b)
+{
+  GL2PSprimitive *q, *w;
+
+  q = *(GL2PSprimitive**)a;
+  w = *(GL2PSprimitive**)b;
+  return(q->type < w->type ? 1 : -1);
+}
+
+static GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root)
+{
+  GLint i, j, count, best = 1000000, index = 0;
+  GL2PSprimitive *prim1, *prim2;
+  GL2PSplane plane;
+  GLint maxp;
+
+  if(!gl2psListNbr(primitives)){
+    gl2psMsg(GL2PS_ERROR, "Cannot fint root in empty primitive list");
+    return 0;
+  }
+
+  *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0);
+
+  if(gl2ps->options & GL2PS_BEST_ROOT){
+    maxp = gl2psListNbr(primitives);
+    if(maxp > gl2ps->maxbestroot){
+      maxp = gl2ps->maxbestroot;
+    }
+    for(i = 0; i < maxp; i++){
+      prim1 = *(GL2PSprimitive**)gl2psListPointer(primitives, i);
+      gl2psGetPlane(prim1, plane);
+      count = 0;
+      for(j = 0; j < gl2psListNbr(primitives); j++){
+        if(j != i){
+          prim2 = *(GL2PSprimitive**)gl2psListPointer(primitives, j);
+          count += gl2psTestSplitPrimitive(prim2, plane); 
+        }
+        if(count > best) break;
+      }
+      if(count < best){
+        best = count;
+        index = i;
+        *root = prim1;
+        if(!count) return index;
+      }
+    }
+    /* if(index) gl2psMsg(GL2PS_INFO, "GL2PS_BEST_ROOT was worth it: %d", index); */
+    return index;
+  }
+  else{
+    return 0;
+  }
+}
+
+static void gl2psFreeImagemap(GL2PSimagemap *list){
+  GL2PSimagemap *next;
+  while(list != NULL){
+    next = list->next;
+    gl2psFree(list->image->pixels);
+    gl2psFree(list->image);
+    gl2psFree(list);
+    list = next;
+  }
+}
+
+static void gl2psFreePrimitive(void *data)
+{
+  GL2PSprimitive *q;
+  
+  q = *(GL2PSprimitive**)data;
+  gl2psFree(q->verts);
+  if(q->type == GL2PS_TEXT || q->type == GL2PS_SPECIAL){
+    gl2psFreeText(q->data.text);
+  }
+  else if(q->type == GL2PS_PIXMAP){
+    gl2psFreePixmap(q->data.image);
+  }
+  gl2psFree(q);
+}
+
+static void gl2psAddPrimitiveInList(GL2PSprimitive *prim, GL2PSlist *list)
+{
+  GL2PSprimitive *t1, *t2;
+
+  if(prim->type != GL2PS_QUADRANGLE){
+    gl2psListAdd(list, &prim);
+  }
+  else{
+    gl2psDivideQuad(prim, &t1, &t2);
+    gl2psListAdd(list, &t1);
+    gl2psListAdd(list, &t2);
+    gl2psFreePrimitive(&prim);
+  }
+  
+}
+
+static void gl2psFreeBspTree(GL2PSbsptree **tree)
+{
+  if(*tree){
+    if((*tree)->back) gl2psFreeBspTree(&(*tree)->back);
+    if((*tree)->primitives){
+      gl2psListAction((*tree)->primitives, gl2psFreePrimitive);
+      gl2psListDelete((*tree)->primitives);
+    }
+    if((*tree)->front) gl2psFreeBspTree(&(*tree)->front);
+    gl2psFree(*tree);
+    *tree = NULL;
+  }
+}
+
+static GLboolean gl2psGreater(GLfloat f1, GLfloat f2)
+{
+  if(f1 > f2) return GL_TRUE;
+  else return GL_FALSE;
+}
+
+static GLboolean gl2psLess(GLfloat f1, GLfloat f2)
+{
+  if(f1 < f2) return GL_TRUE;
+  else return GL_FALSE;
+}
+
+static void gl2psBuildBspTree(GL2PSbsptree *tree, GL2PSlist *primitives)
+{
+  GL2PSprimitive *prim, *frontprim = NULL, *backprim = NULL;
+  GL2PSlist *frontlist, *backlist;
+  GLint i, index;
+
+  tree->front = NULL;
+  tree->back = NULL;
+  tree->primitives = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+  index = gl2psFindRoot(primitives, &prim);
+  gl2psGetPlane(prim, tree->plane);
+  gl2psAddPrimitiveInList(prim, tree->primitives);
+
+  frontlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+  backlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+
+  for(i = 0; i < gl2psListNbr(primitives); i++){
+    if(i != index){
+      prim = *(GL2PSprimitive**)gl2psListPointer(primitives,i);
+      switch(gl2psSplitPrimitive(prim, tree->plane, &frontprim, &backprim)){
+      case GL2PS_COINCIDENT:
+        gl2psAddPrimitiveInList(prim, tree->primitives);
+        break;
+      case GL2PS_IN_BACK_OF:
+        gl2psAddPrimitiveInList(prim, backlist);
+        break;
+      case GL2PS_IN_FRONT_OF:
+        gl2psAddPrimitiveInList(prim, frontlist);
+        break;
+      case GL2PS_SPANNING:
+        gl2psAddPrimitiveInList(backprim, backlist);
+        gl2psAddPrimitiveInList(frontprim, frontlist);
+        gl2psFreePrimitive(&prim);
+        break;
+      }
+    }
+  }
+
+  if(gl2psListNbr(tree->primitives)){
+    gl2psListSort(tree->primitives, gl2psTrianglesFirst);
+  }
+
+  if(gl2psListNbr(frontlist)){
+    gl2psListSort(frontlist, gl2psTrianglesFirst);
+    tree->front = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
+    gl2psBuildBspTree(tree->front, frontlist);
+  }
+  else{
+    gl2psListDelete(frontlist);
+  }
+
+  if(gl2psListNbr(backlist)){
+    gl2psListSort(backlist, gl2psTrianglesFirst);
+    tree->back = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
+    gl2psBuildBspTree(tree->back, backlist);
+  }
+  else{
+    gl2psListDelete(backlist);
+  }
+
+  gl2psListDelete(primitives);
+}
+
+static void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsilon,
+                                 GLboolean (*compare)(GLfloat f1, GLfloat f2),
+                                 void (*action)(void *data), int inverse)
+{
+  GLfloat result;
+
+  if(!tree) return;
+
+  result = gl2psComparePointPlane(eye, tree->plane);
+
+  if(GL_TRUE == compare(result, epsilon)){
+    gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
+    if(inverse){
+      gl2psListActionInverse(tree->primitives, action);
+    }
+    else{
+      gl2psListAction(tree->primitives, action);
+    }
+    gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
+  }
+  else if(GL_TRUE == compare(-epsilon, result)){ 
+    gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
+    if(inverse){
+      gl2psListActionInverse(tree->primitives, action);
+    }
+    else{
+      gl2psListAction(tree->primitives, action);
+    }
+    gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
+  }
+  else{
+    gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
+    gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
+  }
+}
+
+static void gl2psRescaleAndOffset()
+{
+  GL2PSprimitive *prim;
+  GLfloat minZ, maxZ, rangeZ, scaleZ;
+  GLfloat factor, units, area, dZ, dZdX, dZdY, maxdZ;
+  int i, j;
+
+  if(!gl2psListNbr(gl2ps->primitives))
+    return;
+
+  /* get z-buffer range */
+  prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, 0);
+  minZ = maxZ = prim->verts[0].xyz[2];
+  for(i = 1; i < prim->numverts; i++){
+    if(prim->verts[i].xyz[2] < minZ) minZ = prim->verts[i].xyz[2];
+    if(prim->verts[i].xyz[2] > maxZ) maxZ = prim->verts[i].xyz[2];
+  }
+  for(i = 1; i < gl2psListNbr(gl2ps->primitives); i++){
+    prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
+    for(j = 0; j < prim->numverts; j++){
+      if(prim->verts[j].xyz[2] < minZ) minZ = prim->verts[j].xyz[2];
+      if(prim->verts[j].xyz[2] > maxZ) maxZ = prim->verts[j].xyz[2];
+    }
+  }
+  rangeZ = (maxZ - minZ);
+
+  /* rescale z-buffer coordinate in [0,GL2PS_ZSCALE], to make it of
+     the same order of magnitude as the x and y coordinates */
+  scaleZ = GL2PS_ZERO(rangeZ) ? GL2PS_ZSCALE : (GL2PS_ZSCALE / rangeZ);
+  /* avoid precision loss (we use floats!) */
+  if(scaleZ > 100000.F) scaleZ = 100000.F;
+
+  /* apply offsets */
+  for(i = 0; i < gl2psListNbr(gl2ps->primitives); i++){
+    prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
+    for(j = 0; j < prim->numverts; j++){
+      prim->verts[j].xyz[2] = (prim->verts[j].xyz[2] - minZ) * scaleZ;
+    }
+    if((gl2ps->options & GL2PS_SIMPLE_LINE_OFFSET) &&
+       (prim->type == GL2PS_LINE)){
+      if(gl2ps->sort == GL2PS_SIMPLE_SORT){
+        prim->verts[0].xyz[2] -= GL2PS_ZOFFSET_LARGE;
+        prim->verts[1].xyz[2] -= GL2PS_ZOFFSET_LARGE;
+      }
+      else{
+        prim->verts[0].xyz[2] -= GL2PS_ZOFFSET;
+        prim->verts[1].xyz[2] -= GL2PS_ZOFFSET;
+      }
+    }
+    else if(prim->offset && (prim->type == GL2PS_TRIANGLE)){
+      factor = gl2ps->offset[0];
+      units = gl2ps->offset[1];
+      area = 
+        (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * 
+        (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) - 
+        (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * 
+        (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]);
+      dZdX = 
+        ((prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) *
+         (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) -
+         (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) *
+         (prim->verts[2].xyz[2] - prim->verts[1].xyz[2])) / area;
+      dZdY = 
+        ((prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
+         (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) -
+         (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
+         (prim->verts[1].xyz[2] - prim->verts[0].xyz[2])) / area;
+      maxdZ = (GLfloat)sqrt(dZdX * dZdX + dZdY * dZdY);
+      dZ = factor * maxdZ + units;
+      prim->verts[0].xyz[2] += dZ;
+      prim->verts[1].xyz[2] += dZ;
+      prim->verts[2].xyz[2] += dZ;
+    }
+  }
+}
+
+/********************************************************************* 
+ *
+ * 2D sorting routines (for occlusion culling) 
+ *
+ *********************************************************************/
+
+static GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane)
+{
+  GLfloat n; 
+
+  plane[0] = b[1] - a[1];
+  plane[1] = a[0] - b[0];
+  n = (GLfloat)sqrt(plane[0]*plane[0] + plane[1]*plane[1]);
+  plane[2] = 0.0F;
+  if(!GL2PS_ZERO(n)){
+    plane[0] /= n;
+    plane[1] /= n;
+    plane[3] = -plane[0]*a[0]-plane[1]*a[1]; 
+    return 1;
+  }
+  else{
+    plane[0] = -1.0F;
+    plane[1] = 0.0F;
+    plane[3] = a[0];
+    return 0;
+  }
+}
+
+static void gl2psFreeBspImageTree(GL2PSbsptree2d **tree)
+{
+  if(*tree){
+    if((*tree)->back)  gl2psFreeBspImageTree(&(*tree)->back);
+    if((*tree)->front) gl2psFreeBspImageTree(&(*tree)->front);
+    gl2psFree(*tree);
+    *tree = NULL;
+  }
+}
+
+static GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane)
+{
+  GLfloat pt_dis;
+
+  pt_dis = gl2psComparePointPlane(point, plane);
+  if(pt_dis > GL2PS_EPSILON)        return GL2PS_POINT_INFRONT;
+  else if(pt_dis < -GL2PS_EPSILON)  return GL2PS_POINT_BACK;
+  else                              return GL2PS_POINT_COINCIDENT;
+}
+
+static void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim,
+                                         GL2PSbsptree2d **tree)
+{
+  GLint ret = 0;
+  GLint i;
+  GLint offset = 0;
+  GL2PSbsptree2d *head = NULL, *cur = NULL;
+
+  if((*tree == NULL) && (prim->numverts > 2)){
+    head = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
+    for(i = 0; i < prim->numverts-1; i++){
+      if(!gl2psGetPlaneFromPoints(prim->verts[i].xyz,
+                                  prim->verts[i+1].xyz,
+                                  head->plane)){
+        if(prim->numverts-i > 3){
+          offset++;
+        }
+        else{
+          gl2psFree(head);
+          return;
+        }
+      }
+      else{
+        break;
+      }
+    }
+    head->back = NULL;
+    head->front = NULL;
+    for(i = 2+offset; i < prim->numverts; i++){
+      ret = gl2psCheckPoint(prim->verts[i].xyz, head->plane);
+      if(ret != GL2PS_POINT_COINCIDENT) break;
+    }
+    switch(ret){
+    case GL2PS_POINT_INFRONT :
+      cur = head;
+      for(i = 1+offset; i < prim->numverts-1; i++){
+        if(cur->front == NULL){
+          cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
+        }
+        if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
+                                   prim->verts[i+1].xyz,
+                                   cur->front->plane)){
+          cur = cur->front;
+          cur->front = NULL;
+          cur->back = NULL;
+        }
+      }
+      if(cur->front == NULL){
+        cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
+      }
+      if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
+                                 prim->verts[offset].xyz,
+                                 cur->front->plane)){
+        cur->front->front = NULL;
+        cur->front->back = NULL;
+      }
+      else{
+        gl2psFree(cur->front);
+        cur->front = NULL;
+      }
+      break;
+    case GL2PS_POINT_BACK :
+      for(i = 0; i < 4; i++){
+        head->plane[i] = -head->plane[i];
+      }
+      cur = head;
+      for(i = 1+offset; i < prim->numverts-1; i++){
+        if(cur->front == NULL){
+          cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
+        }
+        if(gl2psGetPlaneFromPoints(prim->verts[i+1].xyz,
+                                   prim->verts[i].xyz,
+                                   cur->front->plane)){
+          cur = cur->front;
+          cur->front = NULL;
+          cur->back = NULL;
+        }
+      }
+      if(cur->front == NULL){
+        cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
+      }
+      if(gl2psGetPlaneFromPoints(prim->verts[offset].xyz,
+                                 prim->verts[i].xyz,
+                                 cur->front->plane)){
+        cur->front->front = NULL;
+        cur->front->back = NULL;
+      }
+      else{
+        gl2psFree(cur->front);
+        cur->front = NULL;
+      }
+      break;
+    default:
+      gl2psFree(head);
+      return;
+    }
+    (*tree) = head;
+  }
+}
+
+static GLint gl2psCheckPrimitive(GL2PSprimitive *prim, GL2PSplane plane)
+{
+  GLint i;
+  GLint pos;
+
+  pos = gl2psCheckPoint(prim->verts[0].xyz, plane);
+  for(i = 1; i < prim->numverts; i++){
+    pos |= gl2psCheckPoint(prim->verts[i].xyz, plane);
+    if(pos == (GL2PS_POINT_INFRONT | GL2PS_POINT_BACK)) return GL2PS_SPANNING;
+  }
+  if(pos & GL2PS_POINT_INFRONT)   return GL2PS_IN_FRONT_OF;
+  else if(pos & GL2PS_POINT_BACK) return GL2PS_IN_BACK_OF;
+  else                            return GL2PS_COINCIDENT;
+}
+
+static GL2PSprimitive *gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent,
+                                                   GLshort numverts,
+                                                   GL2PSvertex *vertx)
+{
+  GLint i;
+  GL2PSprimitive *child = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+
+  if(parent->type == GL2PS_IMAGEMAP){
+    child->type = GL2PS_IMAGEMAP;
+    child->data.image = parent->data.image;
+  }
+  else {
+    switch(numverts){
+    case 1 : child->type = GL2PS_POINT; break;
+    case 2 : child->type = GL2PS_LINE; break;
+    case 3 : child->type = GL2PS_TRIANGLE; break;
+    case 4 : child->type = GL2PS_QUADRANGLE; break;
+    default: child->type = GL2PS_NO_TYPE; break; /* FIXME */
+    }
+  }
+  child->boundary = 0; /* FIXME: not done! */
+  child->culled = parent->culled;
+  child->offset = parent->offset;
+  child->pattern = parent->pattern;
+  child->factor = parent->factor;
+  child->width = parent->width;
+  child->numverts = numverts;
+  child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
+  for(i = 0; i < numverts; i++){
+    child->verts[i] = vertx[i];
+  }
+  return child;
+}
+
+static void gl2psSplitPrimitive2D(GL2PSprimitive *prim,
+                                  GL2PSplane plane, 
+                                  GL2PSprimitive **front, 
+                                  GL2PSprimitive **back)
+{
+  /* cur will hold the position of the current vertex
+     prev will hold the position of the previous vertex
+     prev0 will hold the position of the vertex number 0
+     v1 and v2 represent the current and previous vertices, respectively
+     flag is set if the current vertex should be checked against the plane */
+  GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1;
+  
+  /* list of vertices that will go in front and back primitive */
+  GL2PSvertex *front_list = NULL, *back_list = NULL;
+  
+  /* number of vertices in front and back list */
+  GLshort front_count = 0, back_count = 0;
+
+  for(i = 0; i <= prim->numverts; i++){
+    v1 = i;
+    if(v1 == prim->numverts){
+      if(prim->numverts < 3) break;
+      v1 = 0;
+      v2 = prim->numverts-1;
+      cur = prev0;
+    }
+    else if(flag){
+      cur = gl2psCheckPoint(prim->verts[v1].xyz, plane);
+      if(i == 0){
+        prev0 = cur;
+      }
+    } 
+    if(((prev == -1) || (prev == cur) || (prev == 0) || (cur == 0)) &&
+       (i < prim->numverts)){
+      if(cur == GL2PS_POINT_INFRONT){
+        front_count++;
+        front_list = (GL2PSvertex*)gl2psRealloc(front_list,
+                                                sizeof(GL2PSvertex)*front_count);
+        front_list[front_count-1] = prim->verts[v1];
+      }
+      else if(cur == GL2PS_POINT_BACK){
+        back_count++;
+        back_list = (GL2PSvertex*)gl2psRealloc(back_list,
+                                               sizeof(GL2PSvertex)*back_count);
+        back_list[back_count-1] = prim->verts[v1];
+      }
+      else{
+        front_count++;
+        front_list = (GL2PSvertex*)gl2psRealloc(front_list,
+                                                sizeof(GL2PSvertex)*front_count);
+        front_list[front_count-1] = prim->verts[v1];
+        back_count++;
+        back_list = (GL2PSvertex*)gl2psRealloc(back_list,
+                                               sizeof(GL2PSvertex)*back_count);
+        back_list[back_count-1] = prim->verts[v1];
+      }
+      flag = 1;
+    }
+    else if((prev != cur) && (cur != 0) && (prev != 0)){
+      if(v1 != 0){
+        v2 = v1-1;
+        i--;
+      }
+      front_count++;
+      front_list = (GL2PSvertex*)gl2psRealloc(front_list,
+                                              sizeof(GL2PSvertex)*front_count);
+      gl2psCutEdge(&prim->verts[v2],
+                   &prim->verts[v1],
+                   plane,
+                   &front_list[front_count-1]);
+      back_count++;
+      back_list = (GL2PSvertex*)gl2psRealloc(back_list,
+                                             sizeof(GL2PSvertex)*back_count);
+      back_list[back_count-1] = front_list[front_count-1];
+      flag = 0;
+    }
+    prev = cur;
+  }
+  *front = gl2psCreateSplitPrimitive2D(prim, front_count, front_list);
+  *back = gl2psCreateSplitPrimitive2D(prim, back_count, back_list);
+  gl2psFree(front_list);
+  gl2psFree(back_list);
+}
+
+static GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree)
+{
+  GLint ret = 0;
+  GL2PSprimitive *frontprim = NULL, *backprim = NULL;
+  
+  /* FIXME: until we consider the actual extent of text strings and
+     pixmaps, never cull them. Otherwise the whole string/pixmap gets
+     culled as soon as the reference point is hidden */
+  if(prim->type == GL2PS_PIXMAP || 
+     prim->type == GL2PS_TEXT || 
+     prim->type == GL2PS_SPECIAL){
+    return 1;
+  }
+
+  if(*tree == NULL){
+    if((prim->type != GL2PS_IMAGEMAP) && (GL_FALSE == gl2ps->zerosurfacearea)){
+      gl2psAddPlanesInBspTreeImage(gl2ps->primitivetoadd, tree);
+    }
+    return 1;
+  }
+  else{
+    switch(gl2psCheckPrimitive(prim, (*tree)->plane)){
+    case GL2PS_IN_BACK_OF: return gl2psAddInBspImageTree(prim, &(*tree)->back);
+    case GL2PS_IN_FRONT_OF: 
+      if((*tree)->front != NULL) return gl2psAddInBspImageTree(prim, &(*tree)->front);
+      else                       return 0;
+    case GL2PS_SPANNING:
+      gl2psSplitPrimitive2D(prim, (*tree)->plane, &frontprim, &backprim);
+      ret = gl2psAddInBspImageTree(backprim, &(*tree)->back);
+      if((*tree)->front != NULL){
+        if(gl2psAddInBspImageTree(frontprim, &(*tree)->front)){
+          ret = 1;
+        }
+      }
+      gl2psFree(frontprim->verts);
+      gl2psFree(frontprim);
+      gl2psFree(backprim->verts);
+      gl2psFree(backprim);
+      return ret;
+    case GL2PS_COINCIDENT:
+      if((*tree)->back != NULL){
+        gl2ps->zerosurfacearea = GL_TRUE;
+        ret = gl2psAddInBspImageTree(prim, &(*tree)->back);
+        gl2ps->zerosurfacearea = GL_FALSE;
+        if(ret) return ret;
+      }
+      if((*tree)->front != NULL){
+        gl2ps->zerosurfacearea = GL_TRUE;
+        ret = gl2psAddInBspImageTree(prim, &(*tree)->front);
+        gl2ps->zerosurfacearea = GL_FALSE;
+        if(ret) return ret;
+      }
+      if(prim->type == GL2PS_LINE) return 1;
+      else                         return 0;
+    }
+  }
+  return 0;
+}
+
+static void gl2psAddInImageTree(void *data)
+{
+  GL2PSprimitive *prim = *(GL2PSprimitive **)data;
+  gl2ps->primitivetoadd = prim;
+  if(prim->type == GL2PS_IMAGEMAP && prim->data.image->format == GL2PS_IMAGEMAP_VISIBLE){
+    prim->culled = 1;
+  }
+  else if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){
+    prim->culled = 1;
+  }
+  else if(prim->type == GL2PS_IMAGEMAP){
+    prim->data.image->format = GL2PS_IMAGEMAP_VISIBLE;
+  }
+}
+
+/* Boundary construction */
+
+static void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list)
+{
+  GL2PSprimitive *b;
+  GLshort i;
+  GL2PSxyz c;
+
+  c[0] = c[1] = c[2] = 0.0F;
+  for(i = 0; i < prim->numverts; i++){
+    c[0] += prim->verts[i].xyz[0];
+    c[1] += prim->verts[i].xyz[1];
+  }
+  c[0] /= prim->numverts;
+  c[1] /= prim->numverts;
+
+  for(i = 0; i < prim->numverts; i++){
+    if(prim->boundary & (GLint)pow(2., i)){
+      b = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+      b->type = GL2PS_LINE;
+      b->offset = prim->offset;
+      b->pattern = prim->pattern;
+      b->factor = prim->factor;
+      b->culled = prim->culled;
+      b->width = prim->width;
+      b->boundary = 0;
+      b->numverts = 2;
+      b->verts = (GL2PSvertex*)gl2psMalloc(2 * sizeof(GL2PSvertex));
+
+#if 0 /* FIXME: need to work on boundary offset... */
+      v[0] = c[0] - prim->verts[i].xyz[0];
+      v[1] = c[1] - prim->verts[i].xyz[1];
+      v[2] = 0.0F;
+      norm = gl2psNorm(v);
+      v[0] /= norm;
+      v[1] /= norm;
+      b->verts[0].xyz[0] = prim->verts[i].xyz[0] +0.1*v[0];
+      b->verts[0].xyz[1] = prim->verts[i].xyz[1] +0.1*v[1];
+      b->verts[0].xyz[2] = prim->verts[i].xyz[2];
+      v[0] = c[0] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
+      v[1] = c[1] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
+      norm = gl2psNorm(v);
+      v[0] /= norm;
+      v[1] /= norm;
+      b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0] +0.1*v[0];
+      b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1] +0.1*v[1];
+      b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
+#else
+      b->verts[0].xyz[0] = prim->verts[i].xyz[0];
+      b->verts[0].xyz[1] = prim->verts[i].xyz[1];
+      b->verts[0].xyz[2] = prim->verts[i].xyz[2];
+      b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
+      b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
+      b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
+#endif
+
+      b->verts[0].rgba[0] = 0.0F;
+      b->verts[0].rgba[1] = 0.0F;
+      b->verts[0].rgba[2] = 0.0F;
+      b->verts[0].rgba[3] = 0.0F;
+      b->verts[1].rgba[0] = 0.0F;
+      b->verts[1].rgba[1] = 0.0F;
+      b->verts[1].rgba[2] = 0.0F;
+      b->verts[1].rgba[3] = 0.0F;
+      gl2psListAdd(list, &b);
+    }
+  }
+
+}
+
+static void gl2psBuildPolygonBoundary(GL2PSbsptree *tree)
+{
+  GLint i;
+  GL2PSprimitive *prim;
+
+  if(!tree) return;
+  gl2psBuildPolygonBoundary(tree->back);
+  for(i = 0; i < gl2psListNbr(tree->primitives); i++){
+    prim = *(GL2PSprimitive**)gl2psListPointer(tree->primitives, i);
+    if(prim->boundary) gl2psAddBoundaryInList(prim, tree->primitives);
+  }
+  gl2psBuildPolygonBoundary(tree->front);
+}
+
+/********************************************************************* 
+ *
+ * Feedback buffer parser
+ *
+ *********************************************************************/
+
+static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts, 
+                                  GL2PSvertex *verts, GLint offset, 
+                                  GLushort pattern, GLint factor,
+                                  GLfloat width, char boundary)
+{
+  GL2PSprimitive *prim;
+
+  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+  prim->type = type;
+  prim->numverts = numverts;
+  prim->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
+  memcpy(prim->verts, verts, numverts * sizeof(GL2PSvertex));
+  prim->boundary = boundary;
+  prim->offset = offset;
+  prim->pattern = pattern;
+  prim->factor = factor;
+  prim->width = width;
+  prim->culled = 0;
+
+  /* FIXME: here we should have an option to split stretched
+     tris/quads to enhance SIMPLE_SORT */
+
+  gl2psListAdd(gl2ps->primitives, &prim);
+}
+
+static GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p)
+{
+  GLint i;
+
+  v->xyz[0] = p[0];
+  v->xyz[1] = p[1];
+  v->xyz[2] = p[2];
+
+  if(gl2ps->colormode == GL_COLOR_INDEX && gl2ps->colorsize > 0){
+    i = (GLint)(p[3] + 0.5);
+    v->rgba[0] = gl2ps->colormap[i][0];
+    v->rgba[1] = gl2ps->colormap[i][1];
+    v->rgba[2] = gl2ps->colormap[i][2];
+    v->rgba[3] = gl2ps->colormap[i][3];
+    return 4;
+  }
+  else{
+    v->rgba[0] = p[3];
+    v->rgba[1] = p[4];
+    v->rgba[2] = p[5];
+    v->rgba[3] = p[6];
+    return 7;
+  }
+}
+
+static void gl2psParseFeedbackBuffer(GLint used)
+{
+  char flag;
+  GLushort pattern = 0;
+  GLboolean boundary;
+  GLint i, sizeoffloat, count, v, vtot, offset = 0, factor = 0, auxindex = 0;
+  GLfloat lwidth = 1.0F, psize = 1.0F;
+  GLfloat *current;
+  GL2PSvertex vertices[3];
+  GL2PSprimitive *prim;
+  GL2PSimagemap *node;
+
+  current = gl2ps->feedback;
+  boundary = gl2ps->boundary = GL_FALSE;
+
+  while(used > 0){
+
+    if(GL_TRUE == boundary) gl2ps->boundary = GL_TRUE;
+    
+    switch((GLint)*current){
+    case GL_POINT_TOKEN :
+      current ++;
+      used --;
+      i = gl2psGetVertex(&vertices[0], current);
+      current += i;
+      used    -= i;
+      gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0, 
+                            pattern, factor, psize, 0);
+      break;
+    case GL_LINE_TOKEN :
+    case GL_LINE_RESET_TOKEN :
+      current ++;
+      used --;
+      i = gl2psGetVertex(&vertices[0], current);
+      current += i;
+      used    -= i;
+      i = gl2psGetVertex(&vertices[1], current);
+      current += i;
+      used    -= i;
+      gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0, 
+                            pattern, factor, lwidth, 0);
+      break;
+    case GL_POLYGON_TOKEN :
+      count = (GLint)current[1];
+      current += 2;
+      used -= 2;
+      v = vtot = 0;
+      while(count > 0 && used > 0){
+        i = gl2psGetVertex(&vertices[v], current);
+        gl2psAdaptVertexForBlending(&vertices[v]);
+        current += i;
+        used    -= i;
+        count --;
+        vtot++;
+        if(v == 2){
+          if(GL_TRUE == boundary){
+            if(!count && vtot == 2) flag = 1|2|4;
+            else if(!count) flag = 2|4;
+            else if(vtot == 2) flag = 1|2;
+            else flag = 2;
+          }
+          else
+            flag = 0;
+          gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, vertices, offset,
+                                pattern, factor, 1, flag);
+          vertices[1] = vertices[2];
+        }
+        else
+          v ++;
+      }
+      break;      
+    case GL_BITMAP_TOKEN :
+    case GL_DRAW_PIXEL_TOKEN :
+    case GL_COPY_PIXEL_TOKEN :
+      current ++;
+      used --;
+      i = gl2psGetVertex(&vertices[0], current);
+      current += i;
+      used    -= i;
+      break;      
+    case GL_PASS_THROUGH_TOKEN :
+      switch((GLint)current[1]){
+      case GL2PS_BEGIN_OFFSET_TOKEN : offset = 1; break;
+      case GL2PS_END_OFFSET_TOKEN : offset = 0; break;
+      case GL2PS_BEGIN_BOUNDARY_TOKEN : boundary = GL_TRUE; break;
+      case GL2PS_END_BOUNDARY_TOKEN : boundary = GL_FALSE; break;
+      case GL2PS_END_STIPPLE_TOKEN : pattern = factor = 0; break;
+      case GL2PS_BEGIN_BLEND_TOKEN : gl2ps->blending = GL_TRUE; break;
+      case GL2PS_END_BLEND_TOKEN : gl2ps->blending = GL_FALSE; break;
+      case GL2PS_BEGIN_STIPPLE_TOKEN : 
+        current += 2;
+        used -= 2; 
+        pattern = (GLushort)current[1]; 
+        current += 2;
+        used -= 2; 
+        factor = (GLint)current[1]; 
+        break;
+      case GL2PS_SRC_BLEND_TOKEN : 
+        current += 2; 
+        used -= 2; 
+        gl2ps->blendfunc[0] = (GLint)current[1];
+        break;
+      case GL2PS_DST_BLEND_TOKEN : 
+        current += 2; 
+        used -= 2; 
+        gl2ps->blendfunc[1] = (GLint)current[1];
+        break;
+      case GL2PS_POINT_SIZE_TOKEN : 
+        current += 2; 
+        used -= 2; 
+        psize = current[1];
+        break;
+      case GL2PS_LINE_WIDTH_TOKEN : 
+        current += 2; 
+        used -= 2; 
+        lwidth = current[1];
+        break;
+      case GL2PS_IMAGEMAP_TOKEN :
+        prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive));
+        prim->type = GL2PS_IMAGEMAP;
+        prim->boundary = 0;
+        prim->numverts = 4;
+        prim->verts = (GL2PSvertex *)gl2psMalloc(4 * sizeof(GL2PSvertex));
+        prim->culled = 0;
+        prim->offset = 0;
+        prim->pattern = 0;
+        prim->factor = 0;
+        prim->width = 1;
+        
+        node = (GL2PSimagemap*)gl2psMalloc(sizeof(GL2PSimagemap));
+        node->image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
+        node->image->type = 0;
+        node->image->format = 0;
+        node->next = NULL;
+        
+        if(gl2ps->imagemap_head == NULL)
+          gl2ps->imagemap_head = node;
+        else
+          gl2ps->imagemap_tail->next = node;
+        gl2ps->imagemap_tail = node;
+        prim->data.image = node->image;
+        
+        current += 2; used -= 2;
+        i = gl2psGetVertex(&prim->verts[0], &current[1]);
+        current += i; used -= i;
+        
+        node->image->width = (GLint)current[2];
+        current += 2; used -= 2;
+        node->image->height = (GLint)current[2];
+        prim->verts[0].xyz[0] = prim->verts[0].xyz[0] - (int)(node->image->width / 2) + 0.5f;
+        prim->verts[0].xyz[1] = prim->verts[0].xyz[1] - (int)(node->image->height / 2) + 0.5f;
+        for(i = 1; i < 4; i++){
+          for(v = 0; v < 3; v++){
+            prim->verts[i].xyz[v] = prim->verts[0].xyz[v];
+            prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
+          }
+          prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
+        }
+        prim->verts[1].xyz[0] = prim->verts[1].xyz[0] + node->image->width;
+        prim->verts[2].xyz[0] = prim->verts[1].xyz[0];
+        prim->verts[2].xyz[1] = prim->verts[2].xyz[1] + node->image->height;
+        prim->verts[3].xyz[1] = prim->verts[2].xyz[1];
+
+        sizeoffloat = sizeof(GLfloat);
+        v = 2 * sizeoffloat;
+        vtot = node->image->height + node->image->height * 
+          ((node->image->width-1)/8);
+        node->image->pixels = (GLfloat*)gl2psMalloc(v + vtot);
+        node->image->pixels[0] = prim->verts[0].xyz[0];
+        node->image->pixels[1] = prim->verts[0].xyz[1];
+        
+        for(i = 0; i < vtot; i += sizeoffloat){
+          current += 2; used -= 2;
+          if((vtot - i) >= 4)
+            memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), sizeoffloat);
+          else
+            memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), vtot - i);
+        }
+        current++; used--;
+        gl2psListAdd(gl2ps->primitives, &prim);
+        break;
+      case GL2PS_DRAW_PIXELS_TOKEN :
+      case GL2PS_TEXT_TOKEN :
+        if(auxindex < gl2psListNbr(gl2ps->auxprimitives))
+          gl2psListAdd(gl2ps->primitives, 
+                       gl2psListPointer(gl2ps->auxprimitives, auxindex++));
+        else
+          gl2psMsg(GL2PS_ERROR, "Wrong number of auxiliary tokens in buffer");
+        break;
+      }
+      current += 2; 
+      used -= 2; 
+      break;      
+    default :
+      gl2psMsg(GL2PS_WARNING, "Unknown token in buffer");
+      current ++;
+      used --;
+      break;
+    }
+  }
+
+  gl2psListReset(gl2ps->auxprimitives);
+}
+
+/********************************************************************* 
+ *
+ * PostScript routines
+ *
+ *********************************************************************/
+
+static void gl2psWriteByte(unsigned char byte)
+{
+  unsigned char h = byte / 16;
+  unsigned char l = byte % 16;
+  gl2psPrintf("%x%x", h, l);
+}
+
+static void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GL2PSimage *im)
+{
+  GLuint nbhex, nbyte, nrgb, nbits;
+  GLuint row, col, ibyte, icase;
+  GLfloat dr, dg, db, fgrey;
+  unsigned char red = 0, green = 0, blue = 0, b, grey;
+  GLuint width = (GLuint)im->width;
+  GLuint height = (GLuint)im->height;
+
+  /* FIXME: should we define an option for these? Or just keep the
+     8-bit per component case? */
+  int greyscale = 0; /* set to 1 to output greyscale image */
+  int nbit = 8; /* number of bits per color compoment (2, 4 or 8) */
+
+  if((width <= 0) || (height <= 0)) return;
+
+  gl2psPrintf("gsave\n");
+  gl2psPrintf("%.2f %.2f translate\n", x, y); 
+  gl2psPrintf("%d %d scale\n", width, height); 
+
+  if(greyscale){ /* greyscale */
+    gl2psPrintf("/picstr %d string def\n", width); 
+    gl2psPrintf("%d %d %d\n", width, height, 8); 
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); 
+    gl2psPrintf("{ currentfile picstr readhexstring pop }\n");
+    gl2psPrintf("image\n");
+    for(row = 0; row < height; row++){
+      for(col = 0; col < width; col++){ 
+        gl2psGetRGB(im, col, row, &dr, &dg, &db);
+        fgrey = (0.30f * dr + 0.59f * dg + 0.11f * db);
+        grey = (unsigned char)(255. * fgrey);
+        gl2psWriteByte(grey);
+      }
+      gl2psPrintf("\n");
+    }
+    nbhex = width * height * 2; 
+    gl2psPrintf("%%%% nbhex digit          :%d\n", nbhex); 
+  }
+  else if(nbit == 2){ /* color, 2 bits for r and g and b; rgbs following each other */
+    nrgb = width  * 3;
+    nbits = nrgb * nbit;
+    nbyte = nbits/8;
+    if((nbyte * 8) != nbits) nbyte++;
+    gl2psPrintf("/rgbstr %d string def\n", nbyte);
+    gl2psPrintf("%d %d %d\n", width, height, nbit);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
+    gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
+    gl2psPrintf("false 3\n");
+    gl2psPrintf("colorimage\n");
+    for(row = 0; row < height; row++){
+      icase = 1;
+      col = 0;
+      b = 0;
+      for(ibyte = 0; ibyte < nbyte; ibyte++){
+        if(icase == 1) {
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          } 
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = red;
+          b = (b<<2) + green;
+          b = (b<<2) + blue;
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          } 
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = (b<<2) + red;
+          gl2psWriteByte(b);
+          b = 0;
+          icase++;
+        } 
+        else if(icase == 2) {
+          b = green;
+          b = (b<<2) + blue;
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          }
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = (b<<2) + red;
+          b = (b<<2) + green;
+          gl2psWriteByte(b);
+          b = 0;
+          icase++;
+        } 
+        else if(icase == 3) {
+          b = blue;
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          }
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = (b<<2) + red;
+          b = (b<<2) + green;
+          b = (b<<2) + blue;
+          gl2psWriteByte(b);
+          b = 0;
+          icase = 1;
+        }
+      }
+      gl2psPrintf("\n");
+    }
+  }
+  else if(nbit == 4){ /* color, 4 bits for r and g and b; rgbs following each other */
+    nrgb = width  * 3;
+    nbits = nrgb * nbit;
+    nbyte = nbits/8;
+    if((nbyte * 8) != nbits) nbyte++; 
+    gl2psPrintf("/rgbstr %d string def\n", nbyte);
+    gl2psPrintf("%d %d %d\n", width, height, nbit);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
+    gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
+    gl2psPrintf("false 3\n");
+    gl2psPrintf("colorimage\n");
+    for(row = 0; row < height; row++){
+      col = 0;
+      icase = 1;
+      for(ibyte = 0; ibyte < nbyte; ibyte++){
+        if(icase == 1) {
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          } 
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(15. * dr);
+          green = (unsigned char)(15. * dg);
+          gl2psPrintf("%x%x", red, green);
+          icase++;
+        } 
+        else if(icase == 2) {
+          blue = (unsigned char)(15. * db);
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          } 
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(15. * dr);
+          gl2psPrintf("%x%x", blue, red);
+          icase++;
+        }
+        else if(icase == 3) {
+          green = (unsigned char)(15. * dg);
+          blue = (unsigned char)(15. * db);
+          gl2psPrintf("%x%x", green, blue);
+          icase = 1;
+        }
+      }
+      gl2psPrintf("\n");
+    }
+  }
+  else{ /* 8 bit for r and g and b */
+    nbyte = width * 3;
+    gl2psPrintf("/rgbstr %d string def\n", nbyte);
+    gl2psPrintf("%d %d %d\n", width, height, 8);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); 
+    gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
+    gl2psPrintf("false 3\n");
+    gl2psPrintf("colorimage\n");
+    for(row = 0; row < height; row++){
+      for(col = 0; col < width; col++){
+        gl2psGetRGB(im, col, row, &dr, &dg, &db);
+        red = (unsigned char)(255. * dr);
+        gl2psWriteByte(red);
+        green = (unsigned char)(255. * dg);
+        gl2psWriteByte(green);
+        blue = (unsigned char)(255. * db);
+        gl2psWriteByte(blue);
+      }
+      gl2psPrintf("\n");
+    }
+  }
+  
+  gl2psPrintf("grestore\n");
+}
+
+static void gl2psPrintPostScriptImagemap(GLfloat x, GLfloat y,
+                                         GLsizei width, GLsizei height,
+                                         const unsigned char *imagemap){
+  int i, size;
+  
+  if((width <= 0) || (height <= 0)) return;
+  
+  size = height + height * (width-1)/8;
+  
+  gl2psPrintf("gsave\n");
+  gl2psPrintf("%.2f %.2f translate\n", x, y);
+  gl2psPrintf("%d %d scale\n%d %d\ntrue\n", width, height,width, height); 
+  gl2psPrintf("[ %d 0 0 -%d 0 %d ] {<", width, height);
+  for(i = 0; i < size; i++){
+    gl2psWriteByte(*imagemap);
+    imagemap++;
+  }
+  gl2psPrintf(">} imagemask\ngrestore\n");
+}
+
+static void gl2psPrintPostScriptHeader(void)
+{
+  time_t now;
+
+  /* Since compression is not part of the PostScript standard,
+     compressed PostScript files are just gzipped PostScript files
+     ("ps.gz" or "eps.gz") */
+  gl2psPrintGzipHeader();
+
+  time(&now);
+
+  if(gl2ps->format == GL2PS_PS){
+    gl2psPrintf("%%!PS-Adobe-3.0\n");
+  }
+  else{
+    gl2psPrintf("%%!PS-Adobe-3.0 EPSF-3.0\n");
+  }
+
+  gl2psPrintf("%%%%Title: %s\n"
+              "%%%%Creator: GL2PS %d.%d.%d%s, %s\n"
+              "%%%%For: %s\n"
+              "%%%%CreationDate: %s"
+              "%%%%LanguageLevel: 3\n"
+              "%%%%DocumentData: Clean7Bit\n"
+              "%%%%Pages: 1\n",
+              gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, 
+              GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
+              gl2ps->producer, ctime(&now));
+
+  if(gl2ps->format == GL2PS_PS){
+    gl2psPrintf("%%%%Orientation: %s\n"
+                "%%%%DocumentMedia: Default %d %d 0 () ()\n",
+                (gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait",
+                (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
+                (int)gl2ps->viewport[2], 
+                (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] : 
+                (int)gl2ps->viewport[3]);
+  }
+
+  gl2psPrintf("%%%%BoundingBox: %d %d %d %d\n"
+              "%%%%EndComments\n",
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] : 
+              (int)gl2ps->viewport[0],
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[0] :
+              (int)gl2ps->viewport[1],
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] : 
+              (int)gl2ps->viewport[2],
+              (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
+              (int)gl2ps->viewport[3]);
+
+  /* RGB color: r g b C (replace C by G in output to change from rgb to gray)
+     Grayscale: r g b G
+     Font choose: size fontname FC
+     Text string: (string) x y size fontname S??
+     Rotated text string: (string) angle x y size fontname S??R
+     Point primitive: x y size P
+     Line width: width W
+     Line start: x y LS
+     Line joining last point: x y L
+     Line end: x y LE
+     Flat-shaded triangle: x3 y3 x2 y2 x1 y1 T
+     Smooth-shaded triangle: x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 ST */
+
+  gl2psPrintf("%%%%BeginProlog\n"
+              "/gl2psdict 64 dict def gl2psdict begin\n"
+              "0 setlinecap 0 setlinejoin\n"
+              "/tryPS3shading %s def %% set to false to force subdivision\n"
+              "/rThreshold %g def %% red component subdivision threshold\n"
+              "/gThreshold %g def %% green component subdivision threshold\n"
+              "/bThreshold %g def %% blue component subdivision threshold\n",
+              (gl2ps->options & GL2PS_NO_PS3_SHADING) ? "false" : "true",
+              gl2ps->threshold[0], gl2ps->threshold[1], gl2ps->threshold[2]);
+
+  gl2psPrintf("/BD { bind def } bind def\n"
+              "/C  { setrgbcolor } BD\n"
+              "/G  { 0.082 mul exch 0.6094 mul add exch 0.3086 mul add neg 1.0 add setgray } BD\n"
+              "/W  { setlinewidth } BD\n");
+
+  gl2psPrintf("/FC { findfont exch /SH exch def SH scalefont setfont } BD\n"
+              "/SW { dup stringwidth pop } BD\n"
+              "/S  { FC moveto show } BD\n"
+              "/SBC{ FC moveto SW -2 div 0 rmoveto show } BD\n"
+              "/SBR{ FC moveto SW neg 0 rmoveto show } BD\n"
+              "/SCL{ FC moveto 0 SH -2 div rmoveto show } BD\n"
+              "/SCC{ FC moveto SW -2 div SH -2 div rmoveto show } BD\n"
+              "/SCR{ FC moveto SW neg SH -2 div rmoveto show } BD\n"
+              "/STL{ FC moveto 0 SH neg rmoveto show } BD\n"
+              "/STC{ FC moveto SW -2 div SH neg rmoveto show } BD\n"
+              "/STR{ FC moveto SW neg SH neg rmoveto show } BD\n");
+
+  /* rotated text routines: same nameanem with R appended */
+
+  gl2psPrintf("/FCT { FC translate 0 0 } BD\n"
+              "/SR  { gsave FCT moveto rotate show grestore } BD\n"  
+              "/SBCR{ gsave FCT moveto rotate SW -2 div 0 rmoveto show grestore } BD\n"
+              "/SBRR{ gsave FCT moveto rotate SW neg 0 rmoveto show grestore } BD\n"
+              "/SCLR{ gsave FCT moveto rotate 0 SH -2 div rmoveto show grestore} BD\n");
+  gl2psPrintf("/SCCR{ gsave FCT moveto rotate SW -2 div SH -2 div rmoveto show grestore} BD\n"
+              "/SCRR{ gsave FCT moveto rotate SW neg SH -2 div rmoveto show grestore} BD\n"
+              "/STLR{ gsave FCT moveto rotate 0 SH neg rmoveto show grestore } BD\n"
+              "/STCR{ gsave FCT moveto rotate SW -2 div SH neg rmoveto show grestore } BD\n"
+              "/STRR{ gsave FCT moveto rotate SW neg SH neg rmoveto show grestore } BD\n");
+
+  gl2psPrintf("/P  { newpath 0.0 360.0 arc closepath fill } BD\n"
+              "/LS { newpath moveto } BD\n"
+              "/L  { lineto } BD\n"
+              "/LE { lineto stroke } BD\n"
+              "/T  { newpath moveto lineto lineto closepath fill } BD\n");
+  
+  /* Smooth-shaded triangle with PostScript level 3 shfill operator:
+        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STshfill */
+
+  gl2psPrintf("/STshfill {\n"
+              "      /b1 exch def /g1 exch def /r1 exch def /y1 exch def /x1 exch def\n"
+              "      /b2 exch def /g2 exch def /r2 exch def /y2 exch def /x2 exch def\n"
+              "      /b3 exch def /g3 exch def /r3 exch def /y3 exch def /x3 exch def\n"
+              "      gsave << /ShadingType 4 /ColorSpace [/DeviceRGB]\n"
+              "      /DataSource [ 0 x1 y1 r1 g1 b1 0 x2 y2 r2 g2 b2 0 x3 y3 r3 g3 b3 ] >>\n"
+              "      shfill grestore } BD\n");
+
+  /* Flat-shaded triangle with middle color:
+        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 Tm */
+
+  gl2psPrintf(/* stack : x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 */
+              "/Tm { 3 -1 roll 8 -1 roll 13 -1 roll add add 3 div\n" /* r = (r1+r2+r3)/3 */
+              /* stack : x3 y3 g3 b3 x2 y2 g2 b2 x1 y1 g1 b1 r */
+              "      3 -1 roll 7 -1 roll 11 -1 roll add add 3 div\n" /* g = (g1+g2+g3)/3 */
+              /* stack : x3 y3 b3 x2 y2 b2 x1 y1 b1 r g b */
+              "      3 -1 roll 6 -1 roll 9 -1 roll add add 3 div" /* b = (b1+b2+b3)/3 */
+              /* stack : x3 y3 x2 y2 x1 y1 r g b */
+              " C T } BD\n");
+
+  /* Split triangle in four sub-triangles (at sides middle points) and call the
+     STnoshfill procedure on each, interpolating the colors in RGB space:
+        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STsplit
+     (in procedure comments key: (Vi) = xi yi ri gi bi) */
+
+  gl2psPrintf("/STsplit {\n"
+              "      4 index 15 index add 0.5 mul\n" /* x13 = (x1+x3)/2 */
+              "      4 index 15 index add 0.5 mul\n" /* y13 = (y1+y3)/2 */
+              "      4 index 15 index add 0.5 mul\n" /* r13 = (r1+r3)/2 */
+              "      4 index 15 index add 0.5 mul\n" /* g13 = (g1+g3)/2 */
+              "      4 index 15 index add 0.5 mul\n" /* b13 = (b1+b3)/2 */
+              "      5 copy 5 copy 25 15 roll\n");
+
+  /* at his point, stack = (V3) (V13) (V13) (V13) (V2) (V1) */
+
+  gl2psPrintf("      9 index 30 index add 0.5 mul\n" /* x23 = (x2+x3)/2 */
+              "      9 index 30 index add 0.5 mul\n" /* y23 = (y2+y3)/2 */
+              "      9 index 30 index add 0.5 mul\n" /* r23 = (r2+r3)/2 */
+              "      9 index 30 index add 0.5 mul\n" /* g23 = (g2+g3)/2 */
+              "      9 index 30 index add 0.5 mul\n" /* b23 = (b2+b3)/2 */
+              "      5 copy 5 copy 35 5 roll 25 5 roll 15 5 roll\n");
+
+  /* stack = (V3) (V13) (V23) (V13) (V23) (V13) (V23) (V2) (V1) */
+
+  gl2psPrintf("      4 index 10 index add 0.5 mul\n" /* x12 = (x1+x2)/2 */
+              "      4 index 10 index add 0.5 mul\n" /* y12 = (y1+y2)/2 */
+              "      4 index 10 index add 0.5 mul\n" /* r12 = (r1+r2)/2 */
+              "      4 index 10 index add 0.5 mul\n" /* g12 = (g1+g2)/2 */
+              "      4 index 10 index add 0.5 mul\n" /* b12 = (b1+b2)/2 */
+              "      5 copy 5 copy 40 5 roll 25 5 roll 15 5 roll 25 5 roll\n");
+  
+  /* stack = (V3) (V13) (V23) (V13) (V12) (V23) (V13) (V1) (V12) (V23) (V12) (V2) */
+
+  gl2psPrintf("      STnoshfill STnoshfill STnoshfill STnoshfill } BD\n");
+  
+  /* Gouraud shaded triangle using recursive subdivision until the difference
+     between corner colors does not exceed the thresholds:
+        x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STnoshfill  */
+
+  gl2psPrintf("/STnoshfill {\n"
+              "      2 index 8 index sub abs rThreshold gt\n" /* |r1-r2|>rth */
+              "      { STsplit }\n"
+              "      { 1 index 7 index sub abs gThreshold gt\n" /* |g1-g2|>gth */
+              "        { STsplit }\n"
+              "        { dup 6 index sub abs bThreshold gt\n" /* |b1-b2|>bth */
+              "          { STsplit }\n"
+              "          { 2 index 13 index sub abs rThreshold gt\n" /* |r1-r3|>rht */
+              "            { STsplit }\n"
+              "            { 1 index 12 index sub abs gThreshold gt\n" /* |g1-g3|>gth */
+              "              { STsplit }\n"
+              "              { dup 11 index sub abs bThreshold gt\n" /* |b1-b3|>bth */
+              "                { STsplit }\n"
+              "                { 7 index 13 index sub abs rThreshold gt\n"); /* |r2-r3|>rht */
+  gl2psPrintf("                  { STsplit }\n"
+              "                  { 6 index 12 index sub abs gThreshold gt\n" /* |g2-g3|>gth */
+              "                    { STsplit }\n"
+              "                    { 5 index 11 index sub abs bThreshold gt\n" /* |b2-b3|>bth */
+              "                      { STsplit }\n"
+              "                      { Tm }\n" /* all colors sufficiently similar */
+              "                      ifelse }\n"
+              "                    ifelse }\n"
+              "                  ifelse }\n"
+              "                ifelse }\n"
+              "              ifelse }\n"
+              "            ifelse }\n"
+              "          ifelse }\n"
+              "        ifelse }\n"
+              "      ifelse } BD\n");
+  
+  gl2psPrintf("tryPS3shading\n"
+              "{ /shfill where\n"
+              "  { /ST { STshfill } BD }\n"
+              "  { /ST { STnoshfill } BD }\n"
+              "  ifelse }\n"
+              "{ /ST { STnoshfill } BD }\n"
+              "ifelse\n");
+
+  gl2psPrintf("end\n"
+              "%%%%EndProlog\n"
+              "%%%%BeginSetup\n"
+              "/DeviceRGB setcolorspace\n"
+              "gl2psdict begin\n"
+              "%%%%EndSetup\n"
+              "%%%%Page: 1 1\n"
+              "%%%%BeginPageSetup\n");
+  
+  if(gl2ps->options & GL2PS_LANDSCAPE){
+    gl2psPrintf("%d 0 translate 90 rotate\n",
+                (int)gl2ps->viewport[3]);
+  }
+
+  gl2psPrintf("%%%%EndPageSetup\n"
+              "mark\n"
+              "gsave\n"
+              "1.0 1.0 scale\n");
+          
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    gl2psPrintf("%g %g %g C\n"
+                "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
+                "closepath fill\n",
+                gl2ps->bgcolor[0], gl2ps->bgcolor[1], gl2ps->bgcolor[2], 
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], 
+                (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3], 
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
+  }
+}
+
+static void gl2psPrintPostScriptColor(GL2PSrgba rgba)
+{
+  if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
+    gl2psSetLastColor(rgba);
+    gl2psPrintf("%g %g %g C\n", rgba[0], rgba[1], rgba[2]);
+  }
+}
+
+static void gl2psResetPostScriptColor(void)
+{
+  gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.;
+}
+
+static void gl2psEndPostScriptLine(void)
+{
+  int i;
+  if(gl2ps->lastvertex.rgba[0] >= 0.){
+    gl2psPrintf("%g %g LE\n", gl2ps->lastvertex.xyz[0], gl2ps->lastvertex.xyz[1]);
+    for(i = 0; i < 3; i++)
+      gl2ps->lastvertex.xyz[i] = -1.;
+    for(i = 0; i < 4; i++)
+      gl2ps->lastvertex.rgba[i] = -1.;
+  }
+}
+
+static void gl2psParseStipplePattern(GLushort pattern, GLint factor, 
+                                     int *nb, int array[10])
+{
+  int i, n;
+  int on[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+  int off[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+  char tmp[16];
+
+  /* extract the 16 bits from the OpenGL stipple pattern */
+  for(n = 15; n >= 0; n--){
+    tmp[n] = (char)(pattern & 0x01);
+    pattern >>= 1;
+  }
+  /* compute the on/off pixel sequence */
+  n = 0;
+  for(i = 0; i < 8; i++){
+    while(n < 16 && !tmp[n]){ off[i]++; n++; }
+    while(n < 16 && tmp[n]){ on[i]++; n++; }
+    if(n >= 15){ i++; break; }
+  }
+
+  /* store the on/off array from right to left, starting with off
+     pixels. The PostScript specification allows for at most 11
+     elements in the on/off array, so we limit ourselves to 5 on/off
+     couples (our longest possible array is thus [on4 off4 on3 off3
+     on2 off2 on1 off1 on0 off0]) */
+  *nb = 0;
+  for(n = i - 1; n >= 0; n--){
+    array[(*nb)++] = factor * on[n];
+    array[(*nb)++] = factor * off[n];
+    if(*nb == 10) break;
+  }
+}
+
+static int gl2psPrintPostScriptDash(GLushort pattern, GLint factor, char *str)
+{
+  int len = 0, i, n, array[10];
+
+  if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
+    return 0;
+  
+  gl2ps->lastpattern = pattern;
+  gl2ps->lastfactor = factor;
+  
+  if(!pattern || !factor){
+    /* solid line */
+    len += gl2psPrintf("[] 0 %s\n", str);
+  }
+  else{
+    gl2psParseStipplePattern(pattern, factor, &n, array);
+    len += gl2psPrintf("[");
+    for(i = 0; i < n; i++){
+      if(i) len += gl2psPrintf(" ");
+      len += gl2psPrintf("%d", array[i]);
+    }
+    len += gl2psPrintf("] 0 %s\n", str);
+  }
+  
+  return len;
+}
+
+static void gl2psPrintPostScriptPrimitive(void *data)
+{
+  int newline;
+  GL2PSprimitive *prim;
+
+  prim = *(GL2PSprimitive**)data;
+
+  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return;
+
+  /* Every effort is made to draw lines as connected segments (i.e.,
+     using a single PostScript path): this is the only way to get nice
+     line joins and to not restart the stippling for every line
+     segment. So if the primitive to print is not a line we must first
+     finish the current line (if any): */
+  if(prim->type != GL2PS_LINE) gl2psEndPostScriptLine();
+
+  switch(prim->type){
+  case GL2PS_POINT :
+    gl2psPrintPostScriptColor(prim->verts[0].rgba);
+    gl2psPrintf("%g %g %g P\n", 
+                prim->verts[0].xyz[0], prim->verts[0].xyz[1], 0.5 * prim->width);
+    break;
+  case GL2PS_LINE :
+    if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
+       !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
+       gl2ps->lastlinewidth != prim->width ||
+       gl2ps->lastpattern != prim->pattern ||
+       gl2ps->lastfactor != prim->factor){
+      /* End the current line if the new segment does not start where
+         the last one ended, or if the color, the width or the
+         stippling have changed (multi-stroking lines with changing
+         colors is necessary until we use /shfill for lines;
+         unfortunately this means that at the moment we can screw up
+         line stippling for smooth-shaded lines) */
+      gl2psEndPostScriptLine();
+      newline = 1;
+    }
+    else{
+      newline = 0;
+    }
+    if(gl2ps->lastlinewidth != prim->width){
+      gl2ps->lastlinewidth = prim->width;
+      gl2psPrintf("%g W\n", gl2ps->lastlinewidth);
+    }
+    gl2psPrintPostScriptDash(prim->pattern, prim->factor, "setdash");
+    gl2psPrintPostScriptColor(prim->verts[0].rgba);
+    gl2psPrintf("%g %g %s\n", prim->verts[0].xyz[0], prim->verts[0].xyz[1],
+                newline ? "LS" : "L");
+    gl2ps->lastvertex = prim->verts[1];
+    break;
+  case GL2PS_TRIANGLE :
+    if(!gl2psVertsSameColor(prim)){
+      gl2psResetPostScriptColor();
+      gl2psPrintf("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g ST\n",
+                  prim->verts[2].xyz[0], prim->verts[2].xyz[1],
+                  prim->verts[2].rgba[0], prim->verts[2].rgba[1],
+                  prim->verts[2].rgba[2], prim->verts[1].xyz[0],
+                  prim->verts[1].xyz[1], prim->verts[1].rgba[0],
+                  prim->verts[1].rgba[1], prim->verts[1].rgba[2],
+                  prim->verts[0].xyz[0], prim->verts[0].xyz[1],
+                  prim->verts[0].rgba[0], prim->verts[0].rgba[1],
+                  prim->verts[0].rgba[2]);
+    }
+    else{
+      gl2psPrintPostScriptColor(prim->verts[0].rgba);
+      gl2psPrintf("%g %g %g %g %g %g T\n",
+                  prim->verts[2].xyz[0], prim->verts[2].xyz[1],
+                  prim->verts[1].xyz[0], prim->verts[1].xyz[1],
+                  prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+    }
+    break;
+  case GL2PS_QUADRANGLE :
+    gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print");
+    break;
+  case GL2PS_PIXMAP :
+    gl2psPrintPostScriptPixmap(prim->verts[0].xyz[0], prim->verts[0].xyz[1],
+                               prim->data.image);
+    break;
+  case GL2PS_IMAGEMAP :
+    if(prim->data.image->type != GL2PS_IMAGEMAP_WRITTEN){
+      gl2psPrintPostScriptColor(prim->verts[0].rgba);
+      gl2psPrintPostScriptImagemap(prim->data.image->pixels[0],
+                                   prim->data.image->pixels[1],
+                                   prim->data.image->width, prim->data.image->height,
+                                   (const unsigned char*)(&(prim->data.image->pixels[2])));
+      prim->data.image->type = GL2PS_IMAGEMAP_WRITTEN;
+    }
+    break;
+  case GL2PS_TEXT :
+    gl2psPrintPostScriptColor(prim->verts[0].rgba);
+    gl2psPrintf("(%s) ", prim->data.text->str);
+    if(prim->data.text->angle)
+      gl2psPrintf("%g ", prim->data.text->angle);
+    gl2psPrintf("%g %g %d /%s ",
+                prim->verts[0].xyz[0], prim->verts[0].xyz[1],
+                prim->data.text->fontsize, prim->data.text->fontname);
+    switch(prim->data.text->alignment){
+    case GL2PS_TEXT_C:
+      gl2psPrintf(prim->data.text->angle ? "SCCR\n" : "SCC\n");
+      break;
+    case GL2PS_TEXT_CL:
+      gl2psPrintf(prim->data.text->angle ? "SCLR\n" : "SCL\n");
+      break;
+    case GL2PS_TEXT_CR:
+      gl2psPrintf(prim->data.text->angle ? "SCRR\n" : "SCR\n");
+      break;
+    case GL2PS_TEXT_B:
+      gl2psPrintf(prim->data.text->angle ? "SBCR\n" : "SBC\n");
+      break;
+    case GL2PS_TEXT_BR:
+      gl2psPrintf(prim->data.text->angle ? "SBRR\n" : "SBR\n");
+      break;
+    case GL2PS_TEXT_T:
+      gl2psPrintf(prim->data.text->angle ? "STCR\n" : "STC\n");
+      break;
+    case GL2PS_TEXT_TL:
+      gl2psPrintf(prim->data.text->angle ? "STLR\n" : "STL\n");
+      break;
+    case GL2PS_TEXT_TR:
+      gl2psPrintf(prim->data.text->angle ? "STRR\n" : "STR\n");
+      break;
+    case GL2PS_TEXT_BL:
+    default:
+      gl2psPrintf(prim->data.text->angle ? "SR\n" : "S\n");
+      break;
+    }
+    break;
+  case GL2PS_SPECIAL :
+    /* alignment contains the format for which the special output text
+       is intended */
+    if(prim->data.text->alignment == GL2PS_PS ||
+       prim->data.text->alignment == GL2PS_EPS)
+      gl2psPrintf("%s\n", prim->data.text->str);
+    break;
+  default :
+    break;
+  }
+}
+
+static void gl2psPrintPostScriptFooter(void)
+{
+  gl2psPrintf("grestore\n"
+              "showpage\n"
+              "cleartomark\n"
+              "%%%%PageTrailer\n"
+              "%%%%Trailer\n"
+              "end\n"
+              "%%%%EOF\n");
+
+  gl2psPrintGzipFooter();
+}
+
+static void gl2psPrintPostScriptBeginViewport(GLint viewport[4])
+{
+  GLint index;
+  GLfloat rgba[4];
+  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
+
+  glRenderMode(GL_FEEDBACK);
+
+  if(gl2ps->header){
+    gl2psPrintPostScriptHeader();
+    gl2ps->header = GL_FALSE;
+  }
+
+  gl2psPrintf("gsave\n"
+              "1.0 1.0 scale\n");
+
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
+      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
+    }
+    else{
+      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
+      rgba[0] = gl2ps->colormap[index][0];
+      rgba[1] = gl2ps->colormap[index][1];
+      rgba[2] = gl2ps->colormap[index][2];
+      rgba[3] = 1.0F;
+    }
+    gl2psPrintf("%g %g %g C\n"
+                "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
+                "closepath fill\n",
+                rgba[0], rgba[1], rgba[2], 
+                x, y, x+w, y, x+w, y+h, x, y+h);
+  }
+    
+  gl2psPrintf("newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
+              "closepath clip\n",
+              x, y, x+w, y, x+w, y+h, x, y+h);
+  
+}
+
+static GLint gl2psPrintPostScriptEndViewport(void)
+{
+  GLint res;
+
+  res = gl2psPrintPrimitives();
+  gl2psPrintf("grestore\n");
+  return res;
+}
+
+static void gl2psPrintPostScriptFinalPrimitive(void)
+{
+  /* End any remaining line, if any */
+  gl2psEndPostScriptLine();
+}
+
+/* definition of the PostScript and Encapsulated PostScript backends */
+
+static GL2PSbackend gl2psPS = {
+  gl2psPrintPostScriptHeader,
+  gl2psPrintPostScriptFooter,
+  gl2psPrintPostScriptBeginViewport,
+  gl2psPrintPostScriptEndViewport,
+  gl2psPrintPostScriptPrimitive,
+  gl2psPrintPostScriptFinalPrimitive,
+  "ps",
+  "Postscript"
+};
+
+static GL2PSbackend gl2psEPS = {
+  gl2psPrintPostScriptHeader,
+  gl2psPrintPostScriptFooter,
+  gl2psPrintPostScriptBeginViewport,
+  gl2psPrintPostScriptEndViewport,
+  gl2psPrintPostScriptPrimitive,
+  gl2psPrintPostScriptFinalPrimitive,
+  "eps",
+  "Encapsulated Postscript"
+};
+
+/********************************************************************* 
+ *
+ * LaTeX routines
+ *
+ *********************************************************************/
+
+static void gl2psPrintTeXHeader(void)
+{
+  char name[256];
+  time_t now;
+  int i;
+
+  if(gl2ps->filename && strlen(gl2ps->filename) < 256){
+    for(i = strlen(gl2ps->filename)-1; i >= 0; i--){
+      if(gl2ps->filename[i] == '.'){
+        strncpy(name, gl2ps->filename, i);
+        name[i] = '\0';
+        break;
+      }
+    }
+    if(i <= 0) strcpy(name, gl2ps->filename);
+  }
+  else{
+    strcpy(name, "untitled");
+  }
+
+  time(&now);
+
+  fprintf(gl2ps->stream, 
+          "%% Title: %s\n"
+          "%% Creator: GL2PS %d.%d.%d%s, %s\n"
+          "%% For: %s\n"
+          "%% CreationDate: %s",
+          gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
+          GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
+          gl2ps->producer, ctime(&now));
+
+  fprintf(gl2ps->stream, 
+          "\\setlength{\\unitlength}{1pt}\n"
+          "\\begin{picture}(0,0)\n"
+          "\\includegraphics{%s}\n"
+          "\\end{picture}%%\n"
+          "%s\\begin{picture}(%d,%d)(0,0)\n",
+          name, (gl2ps->options & GL2PS_LANDSCAPE) ? "\\rotatebox{90}{" : "",
+          (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
+}
+
+static void gl2psPrintTeXPrimitive(void *data)
+{
+  GL2PSprimitive *prim;
+
+  prim = *(GL2PSprimitive**)data;
+
+  switch(prim->type){
+  case GL2PS_TEXT :
+    fprintf(gl2ps->stream, "\\fontsize{%d}{0}\n\\selectfont", 
+            prim->data.text->fontsize);
+    fprintf(gl2ps->stream, "\\put(%g,%g){\\makebox(0,0)",
+            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+    switch(prim->data.text->alignment){
+    case GL2PS_TEXT_C:
+      fprintf(gl2ps->stream, "{");
+      break;
+    case GL2PS_TEXT_CL:
+      fprintf(gl2ps->stream, "[l]{");
+      break;
+    case GL2PS_TEXT_CR:
+      fprintf(gl2ps->stream, "[r]{");
+      break;
+    case GL2PS_TEXT_B:
+      fprintf(gl2ps->stream, "[b]{");
+      break;
+    case GL2PS_TEXT_BR:
+      fprintf(gl2ps->stream, "[br]{");
+      break;
+    case GL2PS_TEXT_T:
+      fprintf(gl2ps->stream, "[t]{");
+      break;
+    case GL2PS_TEXT_TL:
+      fprintf(gl2ps->stream, "[tl]{");
+      break;
+    case GL2PS_TEXT_TR:
+      fprintf(gl2ps->stream, "[tr]{");
+      break;
+    case GL2PS_TEXT_BL:
+    default:
+      fprintf(gl2ps->stream, "[bl]{");
+      break;
+    }
+    if(prim->data.text->angle)
+      fprintf(gl2ps->stream, "\\rotatebox{%g}{", prim->data.text->angle);
+    fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
+            prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2],
+            prim->data.text->str);
+    if(prim->data.text->angle)
+      fprintf(gl2ps->stream, "}");
+    fprintf(gl2ps->stream, "}}\n");
+    break;
+  case GL2PS_SPECIAL :
+    /* alignment contains the format for which the special output text
+       is intended */
+    if (prim->data.text->alignment == GL2PS_TEX)
+      fprintf(gl2ps->stream, "%s\n", prim->data.text->str);
+    break;
+  default :
+    break;
+  }
+}
+
+static void gl2psPrintTeXFooter(void)
+{
+  fprintf(gl2ps->stream, "\\end{picture}%s\n",
+          (gl2ps->options & GL2PS_LANDSCAPE) ? "}" : "");
+}
+
+static void gl2psPrintTeXBeginViewport(GLint viewport[4])
+{
+  glRenderMode(GL_FEEDBACK);
+  
+  if(gl2ps->header){
+    gl2psPrintTeXHeader();
+    gl2ps->header = GL_FALSE;
+  }
+}
+
+static GLint gl2psPrintTeXEndViewport(void)
+{
+  return gl2psPrintPrimitives();
+}
+
+static void gl2psPrintTeXFinalPrimitive(void)
+{
+}
+
+/* definition of the LaTeX backend */
+
+static GL2PSbackend gl2psTEX = {
+  gl2psPrintTeXHeader,
+  gl2psPrintTeXFooter,
+  gl2psPrintTeXBeginViewport,
+  gl2psPrintTeXEndViewport,
+  gl2psPrintTeXPrimitive,
+  gl2psPrintTeXFinalPrimitive,
+  "tex",
+  "LaTeX text"
+};
+
+/********************************************************************* 
+ *
+ * PDF routines
+ *
+ *********************************************************************/
+
+static int gl2psPrintPDFCompressorType(void)
+{
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    return fprintf(gl2ps->stream, "/Filter [/FlateDecode]\n");
+  }
+#endif
+  return 0;
+}
+
+static int gl2psPrintPDFStrokeColor(GL2PSrgba rgba)
+{
+  int i, offs = 0;
+
+  gl2psSetLastColor(rgba);
+  for(i = 0; i < 3; ++i){
+    if(GL2PS_ZERO(rgba[i]))
+      offs += gl2psPrintf("%.0f ", 0.);
+    else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */
+      offs += gl2psPrintf("%f ", rgba[i]);
+    else
+      offs += gl2psPrintf("%g ", rgba[i]);
+  }
+  offs += gl2psPrintf("RG\n");
+  return offs;
+}
+
+static int gl2psPrintPDFFillColor(GL2PSrgba rgba)
+{
+  int i, offs = 0;
+  
+  for(i = 0; i < 3; ++i){
+    if(GL2PS_ZERO(rgba[i]))
+      offs += gl2psPrintf("%.0f ", 0.);
+    else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */
+      offs += gl2psPrintf("%f ", rgba[i]);
+    else
+      offs += gl2psPrintf("%g ", rgba[i]);
+  }
+  offs += gl2psPrintf("rg\n");
+  return offs;
+}
+
+static int gl2psPrintPDFLineWidth(GLfloat lw)
+{
+  if(GL2PS_ZERO(lw))
+    return gl2psPrintf("%.0f w\n", 0.);
+  else if(lw < 1e-4 || lw > 1e6) /* avoid %e formatting */
+    return gl2psPrintf("%f w\n", lw);
+  else
+    return gl2psPrintf("%g w\n", lw);
+}
+
+static void gl2psPutPDFText(GL2PSstring *text, int cnt, GLfloat x, GLfloat y)
+{
+  gl2ps->streamlength += 
+    gl2psPrintf("BT\n"
+                "/F%d %d Tf\n"
+                "%f %f Td\n"
+                "(%s) Tj\n"
+                "ET\n", 
+                cnt, text->fontsize, x, y, text->str);  
+}
+
+static void gl2psPutPDFImage(GL2PSimage *image, int cnt, GLfloat x, GLfloat y)
+{
+  gl2ps->streamlength += 
+    gl2psPrintf("q\n"
+                "%d 0 0 %d %f %f cm\n"
+                "/Im%d Do\n"
+                "Q\n",
+                (int)image->width, (int)image->height, x, y, cnt);
+}
+
+static void gl2psPDFstacksInit(void)
+{
+  gl2ps->objects_stack = 7 /* FIXED_XREF_ENTRIES */ + 1; 
+  gl2ps->extgs_stack = 0;   
+  gl2ps->font_stack = 0;    
+  gl2ps->im_stack = 0;      
+  gl2ps->trgroupobjects_stack = 0;    
+  gl2ps->shader_stack = 0;  
+  gl2ps->mshader_stack = 0; 
+}
+
+static void gl2psPDFgroupObjectInit(GL2PSpdfgroup *gro)
+{
+  if(!gro)
+    return;
+  
+  gro->ptrlist = NULL;
+  gro->fontno = gro->gsno = gro->imno = gro->maskshno = gro->shno 
+    = gro->trgroupno = gro->fontobjno = gro->imobjno = gro->shobjno 
+    = gro->maskshobjno = gro->gsobjno = gro->trgroupobjno = -1;
+}
+
+/* Build up group objects and assign name and object numbers */
+
+static void gl2psPDFgroupListInit(void)
+{
+  int i;
+  GL2PSprimitive *p = NULL;
+  GL2PSpdfgroup gro;
+  int lasttype = GL2PS_NO_TYPE;
+  GL2PSrgba lastrgba = {-1.0F, -1.0F, -1.0F, -1.0F};
+  GLushort lastpattern = 0;
+  GLint lastfactor = 0;
+  GLfloat lastwidth = 1;
+  GL2PStriangle lastt, tmpt;
+  int lastTriangleWasNotSimpleWithSameColor = 0;
+
+  if(!gl2ps->pdfprimlist)
+    return;
+
+  gl2ps->pdfgrouplist = gl2psListCreate(500, 500, sizeof(GL2PSpdfgroup));
+  gl2psInitTriangle(&lastt);
+
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfprimlist); ++i){  
+    p = *(GL2PSprimitive**)gl2psListPointer(gl2ps->pdfprimlist, i);
+    switch(p->type){
+    case GL2PS_PIXMAP:
+      gl2psPDFgroupObjectInit(&gro);
+      gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+      gro.imno = gl2ps->im_stack++;
+      gl2psListAdd(gro.ptrlist, &p);
+      gl2psListAdd(gl2ps->pdfgrouplist, &gro);
+      break;
+    case GL2PS_TEXT:
+      gl2psPDFgroupObjectInit(&gro);
+      gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+      gro.fontno = gl2ps->font_stack++;
+      gl2psListAdd(gro.ptrlist, &p);
+      gl2psListAdd(gl2ps->pdfgrouplist, &gro);
+      break;
+    case GL2PS_LINE:
+      if(lasttype != p->type || lastwidth != p->width || 
+         lastpattern != p->pattern || lastfactor != p->factor ||
+         !gl2psSameColor(p->verts[0].rgba, lastrgba)){
+        gl2psPDFgroupObjectInit(&gro);
+        gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+        gl2psListAdd(gro.ptrlist, &p);
+        gl2psListAdd(gl2ps->pdfgrouplist, &gro);
+      }
+      else{
+        gl2psListAdd(gro.ptrlist, &p);
+      }
+      lastpattern = p->pattern;
+      lastfactor = p->factor;
+      lastwidth = p->width;
+      lastrgba[0] = p->verts[0].rgba[0];
+      lastrgba[1] = p->verts[0].rgba[1];
+      lastrgba[2] = p->verts[0].rgba[2];
+      break;
+    case GL2PS_POINT:
+      if(lasttype != p->type || lastwidth != p->width || 
+         !gl2psSameColor(p->verts[0].rgba, lastrgba)){
+        gl2psPDFgroupObjectInit(&gro);
+        gro.ptrlist = gl2psListCreate(1,2,sizeof(GL2PSprimitive*));
+        gl2psListAdd(gro.ptrlist, &p);
+        gl2psListAdd(gl2ps->pdfgrouplist, &gro);
+      }
+      else{
+        gl2psListAdd(gro.ptrlist, &p);
+      }
+      lastwidth = p->width;
+      lastrgba[0] = p->verts[0].rgba[0];
+      lastrgba[1] = p->verts[0].rgba[1];
+      lastrgba[2] = p->verts[0].rgba[2];
+      break;
+    case GL2PS_TRIANGLE:
+      gl2psFillTriangleFromPrimitive(&tmpt, p, GL_TRUE);
+      lastTriangleWasNotSimpleWithSameColor = 
+        !(tmpt.prop & T_CONST_COLOR && tmpt.prop & T_ALPHA_1) ||
+        !gl2psSameColor(tmpt.vertex[0].rgba, lastt.vertex[0].rgba);
+      if(lasttype == p->type && tmpt.prop == lastt.prop && 
+         lastTriangleWasNotSimpleWithSameColor){
+        /* TODO Check here for last alpha */
+        gl2psListAdd(gro.ptrlist, &p);
+      }
+      else{
+        gl2psPDFgroupObjectInit(&gro);
+        gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
+        gl2psListAdd(gro.ptrlist, &p);
+        gl2psListAdd(gl2ps->pdfgrouplist, &gro);
+      }
+      lastt = tmpt;
+      break;
+    default:
+      break;
+    } 
+    lasttype = p->type;
+  }
+}
+
+static void gl2psSortOutTrianglePDFgroup(GL2PSpdfgroup *gro)
+{
+  GL2PStriangle t;
+  GL2PSprimitive *prim = NULL;
+  
+  if(!gro)
+    return;
+
+  if(!gl2psListNbr(gro->ptrlist))
+    return;
+
+  prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
+
+  if(prim->type != GL2PS_TRIANGLE)
+    return;
+
+  gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
+  
+  if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){        
+    gro->gsno = gl2ps->extgs_stack++; 
+    gro->gsobjno = gl2ps->objects_stack ++;
+  }
+  else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){              
+    gro->gsno = gl2ps->extgs_stack++;
+    gro->gsobjno = gl2ps->objects_stack++;
+    gro->trgroupno = gl2ps->trgroupobjects_stack++; 
+    gro->trgroupobjno = gl2ps->objects_stack++;
+    gro->maskshno = gl2ps->mshader_stack++;
+    gro->maskshobjno = gl2ps->objects_stack++;
+  }
+  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){          
+    gro->shno = gl2ps->shader_stack++;
+    gro->shobjno = gl2ps->objects_stack++;
+  }
+  else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){             
+    gro->gsno = gl2ps->extgs_stack++;
+    gro->gsobjno = gl2ps->objects_stack++;
+    gro->shno = gl2ps->shader_stack++; 
+    gro->shobjno = gl2ps->objects_stack++;
+  }
+  else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){                
+    gro->gsno = gl2ps->extgs_stack++;
+    gro->gsobjno = gl2ps->objects_stack++;
+    gro->shno = gl2ps->shader_stack++; 
+    gro->shobjno = gl2ps->objects_stack++;
+    gro->trgroupno = gl2ps->trgroupobjects_stack++; 
+    gro->trgroupobjno = gl2ps->objects_stack++;
+    gro->maskshno = gl2ps->mshader_stack++;
+    gro->maskshobjno = gl2ps->objects_stack++;
+  }
+}
+
+/* Main stream data */
+
+static void gl2psPDFgroupListWriteMainStream(void)
+{
+  int i, j, lastel;
+  GL2PSprimitive *prim = NULL, *prev = NULL;
+  GL2PSpdfgroup *gro;
+  GL2PStriangle t;
+
+  if(!gl2ps->pdfgrouplist)
+    return;
+
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+
+    lastel = gl2psListNbr(gro->ptrlist) - 1;
+    if(lastel < 0)
+      continue;
+
+    prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
+
+    switch(prim->type){
+    case GL2PS_POINT:
+      gl2ps->streamlength += gl2psPrintf("1 J\n");
+      gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
+      gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
+      for(j = 0; j <= lastel; ++j){  
+        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+        gl2ps->streamlength +=
+          gl2psPrintf("%f %f m %f %f l\n",
+                      prim->verts[0].xyz[0], prim->verts[0].xyz[1],
+                      prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+      }
+      gl2ps->streamlength += gl2psPrintf("S\n"); 
+      gl2ps->streamlength += gl2psPrintf("0 J\n");
+      break;
+    case GL2PS_LINE:
+      /* We try to use as few paths as possible to draw lines, in
+         order to get nice stippling even when the individual segments
+         are smaller than the stipple */
+      gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
+      gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
+      gl2ps->streamlength += gl2psPrintPostScriptDash(prim->pattern, prim->factor, "d");
+      /* start new path */
+      gl2ps->streamlength += 
+        gl2psPrintf("%f %f m\n", 
+                    prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+      
+      for(j = 1; j <= lastel; ++j){
+        prev = prim;
+        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+        if(!gl2psSamePosition(prim->verts[0].xyz, prev->verts[1].xyz)){
+          /* the starting point of the new segment does not match the
+             end point of the previous line, so we end the current
+             path and start a new one */
+          gl2ps->streamlength += 
+            gl2psPrintf("%f %f l\n", 
+                        prev->verts[1].xyz[0], prev->verts[1].xyz[1]);
+          gl2ps->streamlength += 
+            gl2psPrintf("%f %f m\n", 
+                        prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+        }
+        else{
+          /* the two segements are connected, so we just append to the
+             current path */
+          gl2ps->streamlength += 
+            gl2psPrintf("%f %f l\n",
+                        prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+        }
+      }
+      /* end last path */
+      gl2ps->streamlength += 
+        gl2psPrintf("%f %f l\n", 
+                    prim->verts[1].xyz[0], prim->verts[1].xyz[1]);
+      gl2ps->streamlength += gl2psPrintf("S\n");
+      break;
+    case GL2PS_TRIANGLE:
+      gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
+      gl2psSortOutTrianglePDFgroup(gro);
+      
+      /* No alpha and const color: Simple PDF draw orders  */
+      if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_1){         
+        gl2ps->streamlength += gl2psPrintPDFFillColor(t.vertex[0].rgba);        
+        for(j = 0; j <= lastel; ++j){  
+          prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+          gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
+          gl2ps->streamlength 
+            += gl2psPrintf("%f %f m\n"
+                           "%f %f l\n"
+                           "%f %f l\n"
+                           "h f\n",
+                           t.vertex[0].xyz[0], t.vertex[0].xyz[1],
+                           t.vertex[1].xyz[0], t.vertex[1].xyz[1],
+                           t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
+        }
+      }
+      /* Const alpha < 1 and const color: Simple PDF draw orders 
+         and an extra extended Graphics State for the alpha const */
+      else if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){               
+        gl2ps->streamlength += gl2psPrintf("q\n"
+                                           "/GS%d gs\n",
+                                           gro->gsno);
+        gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
+        for(j = 0; j <= lastel; ++j){  
+          prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+          gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
+          gl2ps->streamlength 
+            += gl2psPrintf("%f %f m\n"
+                           "%f %f l\n"
+                           "%f %f l\n"
+                           "h f\n",
+                           t.vertex[0].xyz[0], t.vertex[0].xyz[1],
+                           t.vertex[1].xyz[0], t.vertex[1].xyz[1],
+                           t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
+        }
+        gl2ps->streamlength += gl2psPrintf("Q\n");
+      }
+      /* Variable alpha and const color: Simple PDF draw orders 
+         and an extra extended Graphics State + Xobject + Shader 
+         object for the alpha mask */
+      else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){          
+        gl2ps->streamlength += gl2psPrintf("q\n"
+                                           "/GS%d gs\n"
+                                           "/TrG%d Do\n",
+                                           gro->gsno, gro->trgroupno);
+        gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
+        for(j = 0; j <= lastel; ++j){  
+          prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+          gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
+          gl2ps->streamlength 
+            += gl2psPrintf("%f %f m\n"
+                           "%f %f l\n"
+                           "%f %f l\n"
+                           "h f\n",
+                           t.vertex[0].xyz[0], t.vertex[0].xyz[1],
+                           t.vertex[1].xyz[0], t.vertex[1].xyz[1],
+                           t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
+        }
+        gl2ps->streamlength += gl2psPrintf("Q\n");
+      }
+      /* Variable color and no alpha: Shader Object for the colored
+         triangle(s) */
+      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){              
+        gl2ps->streamlength += gl2psPrintf("/Sh%d sh\n", gro->shno);
+      }
+      /* Variable color and const alpha < 1: Shader Object for the 
+         colored triangle(s) and an extra extended Graphics State 
+         for the alpha const */
+      else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){         
+        gl2ps->streamlength += gl2psPrintf("q\n"
+                                           "/GS%d gs\n"
+                                           "/Sh%d sh\n"
+                                           "Q\n",
+                                           gro->gsno, gro->shno);
+      }
+      /* Variable alpha and color: Shader Object for the colored 
+         triangle(s) and an extra extended Graphics State 
+         + Xobject + Shader object for the alpha mask */
+      else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){            
+        gl2ps->streamlength += gl2psPrintf("q\n"
+                                           "/GS%d gs\n"
+                                           "/TrG%d Do\n"
+                                           "/Sh%d sh\n"
+                                           "Q\n",
+                                           gro->gsno, gro->trgroupno, gro->shno);
+      }
+      break;
+    case GL2PS_PIXMAP:
+      for(j = 0; j <= lastel; ++j){
+        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+        gl2psPutPDFImage(prim->data.image, gro->imno, prim->verts[0].xyz[0], 
+                         prim->verts[0].xyz[1]);
+      }
+      break;
+    case GL2PS_TEXT:
+      for(j = 0; j <= lastel; ++j){  
+        prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+        gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
+        gl2psPutPDFText(prim->data.text, gro->fontno, prim->verts[0].xyz[0],
+                        prim->verts[0].xyz[1]);
+      }
+      break;
+    default:
+      break;
+    } 
+  }
+}
+
+/* Graphics State names */
+
+static int gl2psPDFgroupListWriteGStateResources(void)
+{
+  GL2PSpdfgroup *gro;
+  int offs = 0;
+  int i;
+
+  offs += fprintf(gl2ps->stream,
+                  "/ExtGState\n" 
+                  "<<\n"
+                  "/GSa 7 0 R\n");
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
+    if(gro->gsno >= 0)
+      offs += fprintf(gl2ps->stream, "/GS%d %d 0 R\n", gro->gsno, gro->gsobjno);
+  }
+  offs += fprintf(gl2ps->stream, ">>\n"); 
+  return offs;
+}
+
+/* Main Shader names */
+
+static int gl2psPDFgroupListWriteShaderResources(void)
+{
+  GL2PSpdfgroup *gro;
+  int offs = 0;
+  int i;
+
+  offs += fprintf(gl2ps->stream,
+                  "/Shading\n"
+                  "<<\n");
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
+    if(gro->shno >= 0)
+      offs += fprintf(gl2ps->stream, "/Sh%d %d 0 R\n", gro->shno, gro->shobjno);
+    if(gro->maskshno >= 0)
+      offs += fprintf(gl2ps->stream, "/TrSh%d %d 0 R\n", gro->maskshno, gro->maskshobjno);
+  }
+  offs += fprintf(gl2ps->stream,">>\n");  
+  return offs;
+}
+
+/* Images & Mask Shader XObject names */
+
+static int gl2psPDFgroupListWriteXObjectResources(void)
+{
+  int i;
+  GL2PSprimitive *p = NULL;
+  GL2PSpdfgroup *gro;
+  int offs = 0;
+
+  offs += fprintf(gl2ps->stream,
+                  "/XObject\n"
+                  "<<\n");
+
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
+    if(!gl2psListNbr(gro->ptrlist))
+      continue;
+    p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
+    switch(p->type){
+    case GL2PS_PIXMAP:
+      gro->imobjno = gl2ps->objects_stack++;
+      if(GL_RGBA == p->data.image->format)  /* reserve one object for image mask */
+        gl2ps->objects_stack++;
+      offs += fprintf(gl2ps->stream, "/Im%d %d 0 R\n", gro->imno, gro->imobjno);
+    case GL2PS_TRIANGLE:
+      if(gro->trgroupno >=0)
+        offs += fprintf(gl2ps->stream, "/TrG%d %d 0 R\n", gro->trgroupno, gro->trgroupobjno);
+      break;
+    default:
+      break;
+    }
+  }
+  offs += fprintf(gl2ps->stream,">>\n");
+  return offs;
+}
+
+/* Font names */
+
+static int gl2psPDFgroupListWriteFontResources(void)
+{
+  int i;
+  GL2PSpdfgroup *gro;
+  int offs = 0;
+
+  offs += fprintf(gl2ps->stream, "/Font\n<<\n");
+
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
+    if(gro->fontno < 0)
+      continue;
+    gro->fontobjno = gl2ps->objects_stack++;
+    offs += fprintf(gl2ps->stream, "/F%d %d 0 R\n", gro->fontno, gro->fontobjno);
+  }
+  offs += fprintf(gl2ps->stream, ">>\n");
+
+  return offs;
+}
+
+static void gl2psPDFgroupListDelete(void)
+{
+  int i;
+  GL2PSpdfgroup *gro = NULL;
+  
+  if(!gl2ps->pdfgrouplist)
+    return;
+
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){ 
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist,i);
+    gl2psListDelete(gro->ptrlist);
+  }
+
+  gl2psListDelete(gl2ps->pdfgrouplist);
+  gl2ps->pdfgrouplist = NULL;
+}
+
+/* Print 1st PDF object - file info */
+
+static int gl2psPrintPDFInfo(void)
+{
+  int offs;
+  time_t now;
+  struct tm *newtime;
+  
+  time(&now);
+  newtime = gmtime(&now);
+  
+  offs = fprintf(gl2ps->stream,
+                 "1 0 obj\n"
+                 "<<\n"
+                 "/Title (%s)\n"
+                 "/Creator (GL2PS %d.%d.%d%s, %s)\n"
+                 "/Producer (%s)\n",
+                 gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
+                 GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
+                 gl2ps->producer);
+  
+  if(!newtime){
+    offs += fprintf(gl2ps->stream, 
+                    ">>\n"
+                    "endobj\n");
+    return offs;
+  }
+  
+  offs += fprintf(gl2ps->stream, 
+                  "/CreationDate (D:%d%02d%02d%02d%02d%02d)\n"
+                  ">>\n"
+                  "endobj\n",
+                  newtime->tm_year+1900, 
+                  newtime->tm_mon+1, 
+                  newtime->tm_mday,
+                  newtime->tm_hour,
+                  newtime->tm_min,
+                  newtime->tm_sec);
+  return offs;
+}
+
+/* Create catalog and page structure - 2nd and 3th PDF object */
+
+static int gl2psPrintPDFCatalog(void)
+{
+  return fprintf(gl2ps->stream, 
+                 "2 0 obj\n"
+                 "<<\n"
+                 "/Type /Catalog\n"
+                 "/Pages 3 0 R\n"
+                 ">>\n"
+                 "endobj\n");
+}
+
+static int gl2psPrintPDFPages(void)
+{
+  return fprintf(gl2ps->stream, 
+                 "3 0 obj\n"
+                 "<<\n" 
+                 "/Type /Pages\n"
+                 "/Kids [6 0 R]\n"
+                 "/Count 1\n"
+                 ">>\n"
+                 "endobj\n");
+}
+
+/* Open stream for data - graphical objects, fonts etc. PDF object 4 */
+
+static int gl2psOpenPDFDataStream(void)
+{
+  int offs = 0;
+  
+  offs += fprintf(gl2ps->stream, 
+                  "4 0 obj\n"
+                  "<<\n" 
+                  "/Length 5 0 R\n" );
+  offs += gl2psPrintPDFCompressorType();
+  offs += fprintf(gl2ps->stream, 
+                  ">>\n"
+                  "stream\n");
+  return offs;
+}
+
+/* Stream setup - Graphics state, fill background if allowed */
+
+static int gl2psOpenPDFDataStreamWritePreface(void)
+{
+  int offs;
+
+  offs = gl2psPrintf("/GSa gs\n");
+  
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    offs += gl2psPrintPDFFillColor(gl2ps->bgcolor);
+    offs += gl2psPrintf("%d %d %d %d re\n",
+                        (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
+                        (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
+    offs += gl2psPrintf("f\n");  
+  }
+  return offs;
+}
+
+/* Use the functions above to create the first part of the PDF*/
+
+static void gl2psPrintPDFHeader(void)
+{
+  int offs = 0;
+  gl2ps->pdfprimlist = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
+  gl2psPDFstacksInit();
+
+  gl2ps->xreflist = (int*)gl2psMalloc(sizeof(int) * gl2ps->objects_stack); 
+
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    gl2psSetupCompress();
+  }
+#endif    
+  gl2ps->xreflist[0] = 0;
+  offs += fprintf(gl2ps->stream, "%%PDF-1.4\n");
+  gl2ps->xreflist[1] = offs;
+  
+  offs += gl2psPrintPDFInfo();
+  gl2ps->xreflist[2] = offs;
+  
+  offs += gl2psPrintPDFCatalog();
+  gl2ps->xreflist[3] = offs;
+  
+  offs += gl2psPrintPDFPages();
+  gl2ps->xreflist[4] = offs;
+  
+  offs += gl2psOpenPDFDataStream();
+  gl2ps->xreflist[5] = offs; /* finished in gl2psPrintPDFFooter */
+  gl2ps->streamlength = gl2psOpenPDFDataStreamWritePreface();
+}
+
+/* The central primitive drawing */
+
+static void gl2psPrintPDFPrimitive(void *data)
+{
+  GL2PSprimitive *prim = *(GL2PSprimitive**)data;
+
+  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) 
+    return;
+
+  prim = gl2psCopyPrimitive(prim); /* deep copy */
+  gl2psListAdd(gl2ps->pdfprimlist, &prim);
+}
+
+/* close stream and ... */
+
+static int gl2psClosePDFDataStream(void)
+{
+  int offs = 0;
+ 
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    if(Z_OK != gl2psDeflate())
+      gl2psMsg(GL2PS_ERROR, "Zlib deflate error");
+    else
+      fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, 1, gl2ps->stream);
+    gl2ps->streamlength += gl2ps->compress->destLen;
+    
+    offs += gl2ps->streamlength;
+    gl2psFreeCompress();
+  }
+#endif 
+  
+  offs += fprintf(gl2ps->stream, 
+                  "endstream\n"
+                  "endobj\n");
+  return offs;
+}
+
+/* ... write the now known length object */
+
+static int gl2psPrintPDFDataStreamLength(int val)
+{
+  return fprintf(gl2ps->stream,
+                 "5 0 obj\n"
+                 "%d\n"
+                 "endobj\n", val);
+}
+
+/* Put the info created before in PDF objects */
+
+static int gl2psPrintPDFOpenPage(void)
+{
+  int offs;
+  
+  /* Write fixed part */
+  
+  offs = fprintf(gl2ps->stream, 
+                 "6 0 obj\n"
+                 "<<\n" 
+                 "/Type /Page\n"
+                 "/Parent 3 0 R\n"
+                 "/MediaBox [%d %d %d %d]\n",
+                 (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
+                 (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
+  
+  if(gl2ps->options & GL2PS_LANDSCAPE)
+    offs += fprintf(gl2ps->stream, "/Rotate -90\n");
+  
+  offs += fprintf(gl2ps->stream,
+                  "/Contents 4 0 R\n"
+                  "/Resources\n" 
+                  "<<\n" 
+                  "/ProcSet [/PDF /Text /ImageB /ImageC]  %%/ImageI\n");
+  
+  return offs;
+
+  /* End fixed part, proceeds in gl2psPDFgroupListWriteVariableResources() */
+}
+
+static int gl2psPDFgroupListWriteVariableResources(void)
+{
+  int offs = 0;
+  
+  /* a) Graphics States for shader alpha masks*/
+  offs += gl2psPDFgroupListWriteGStateResources();  
+  
+  /* b) Shader and shader masks */ 
+  offs += gl2psPDFgroupListWriteShaderResources();  
+ 
+  /* c) XObjects (Images & Shader Masks) */
+  offs += gl2psPDFgroupListWriteXObjectResources();
+  
+  /* d) Fonts */
+  offs += gl2psPDFgroupListWriteFontResources();
+  
+  /* End resources and page */
+  offs += fprintf(gl2ps->stream,
+                  ">>\n"
+                  ">>\n"
+                  "endobj\n");
+  return offs;
+}
+
+/* Standard Graphics State */
+
+static int gl2psPrintPDFGSObject(void)
+{
+  return fprintf(gl2ps->stream,
+                 "7 0 obj\n"
+                 "<<\n"
+                 "/Type /ExtGState\n"
+                 "/SA false\n"
+                 "/SM 0.02\n"
+                 "/OP false\n"
+                 "/op false\n"
+                 "/OPM 0\n"
+                 "/BG2 /Default\n"
+                 "/UCR2 /Default\n"
+                 "/TR2 /Default\n"
+                 ">>\n"
+                 "endobj\n");
+}
+
+/* Put vertex' edge flag (8bit) and coordinates (32bit) in shader stream */
+
+static int gl2psPrintPDFShaderStreamDataCoord(GL2PSvertex *vertex, 
+                                              size_t (*action)(unsigned long data, 
+                                                               size_t size), 
+                                              GLfloat dx, GLfloat dy, 
+                                              GLfloat xmin, GLfloat ymin)
+{
+  int offs = 0;
+  unsigned long imap;
+  GLfloat diff;
+  double dmax = ~1UL;
+  char edgeflag = 0;
+
+  /* FIXME: temp bux fix for 64 bit archs: */
+  if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
+
+  offs += (*action)(edgeflag, 1);
+
+  /* The Shader stream in PDF requires to be in a 'big-endian'
+     order */
+    
+  if(GL2PS_ZERO(dx*dy)){
+    offs += (*action)(0, 4);
+    offs += (*action)(0, 4);
+  }
+  else{
+    diff = (vertex->xyz[0] - xmin) / dx;
+    if(diff > 1)
+      diff = 1.0F;
+    else if(diff < 0)
+      diff = 0.0F;
+    imap = (unsigned long)(diff * dmax);
+    offs += (*action)(imap, 4);
+      
+    diff = (vertex->xyz[1] - ymin) / dy;
+    if(diff > 1)
+      diff = 1.0F;
+    else if(diff < 0)
+      diff = 0.0F;
+    imap = (unsigned long)(diff * dmax);
+    offs += (*action)(imap, 4);
+  }
+  
+  return offs;
+}
+
+/* Put vertex' rgb value (8bit for every component) in shader stream */
+
+static int gl2psPrintPDFShaderStreamDataRGB(GL2PSvertex *vertex,
+                                            size_t (*action)(unsigned long data, 
+                                                             size_t size))
+{
+  int offs = 0;
+  unsigned long imap;
+  double dmax = ~1UL;
+
+  /* FIXME: temp bux fix for 64 bit archs: */
+  if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
+
+  imap = (unsigned long)((vertex->rgba[0]) * dmax);
+  offs += (*action)(imap, 1);
+    
+  imap = (unsigned long)((vertex->rgba[1]) * dmax);
+  offs += (*action)(imap, 1);
+    
+  imap = (unsigned long)((vertex->rgba[2]) * dmax);
+  offs += (*action)(imap, 1);
+  
+  return offs;
+}
+
+/* Put vertex' alpha (8/16bit) in shader stream */
+
+static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex, 
+                                              size_t (*action)(unsigned long data, 
+                                                               size_t size),
+                                              int sigbyte)
+{
+  int offs = 0;
+  unsigned long imap;
+  double dmax = ~1UL;
+
+  /* FIXME: temp bux fix for 64 bit archs: */
+  if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
+
+  if(sigbyte != 8 && sigbyte != 16)
+    sigbyte = 8;
+        
+  sigbyte /= 8;
+  
+  imap = (unsigned long)((vertex->rgba[3]) * dmax);
+  
+  offs += (*action)(imap, sigbyte);
+  
+  return offs;
+}
+
+/* Put a triangles raw data in shader stream */
+
+static int gl2psPrintPDFShaderStreamData(GL2PStriangle *triangle, 
+                                         GLfloat dx, GLfloat dy, 
+                                         GLfloat xmin, GLfloat ymin,
+                                         size_t (*action)(unsigned long data, 
+                                                          size_t size),
+                                         int gray)
+{
+  int i, offs = 0;
+  GL2PSvertex v;
+  
+  if(gray && gray != 8 && gray != 16)
+    gray = 8;
+  
+  for(i = 0; i < 3; ++i){
+    offs += gl2psPrintPDFShaderStreamDataCoord(&triangle->vertex[i], action,
+                                               dx, dy, xmin, ymin);
+    if(gray){ 
+      v = triangle->vertex[i];
+      offs += gl2psPrintPDFShaderStreamDataAlpha(&v, action, gray); 
+    }
+    else{
+      offs += gl2psPrintPDFShaderStreamDataRGB(&triangle->vertex[i], action);
+    }
+  }
+  
+  return offs;
+}
+
+static void gl2psPDFRectHull(GLfloat *xmin, GLfloat *xmax, 
+                             GLfloat *ymin, GLfloat *ymax, 
+                             GL2PStriangle *triangles, int cnt)
+{
+  int i, j;
+
+  *xmin = triangles[0].vertex[0].xyz[0];
+  *xmax = triangles[0].vertex[0].xyz[0];
+  *ymin = triangles[0].vertex[0].xyz[1];
+  *ymax = triangles[0].vertex[0].xyz[1];
+  
+  for(i = 0; i < cnt; ++i){
+    for(j = 0; j < 3; ++j){
+      if(*xmin > triangles[i].vertex[j].xyz[0])
+        *xmin = triangles[i].vertex[j].xyz[0];
+      if(*xmax < triangles[i].vertex[j].xyz[0])
+        *xmax = triangles[i].vertex[j].xyz[0];
+      if(*ymin > triangles[i].vertex[j].xyz[1])
+        *ymin = triangles[i].vertex[j].xyz[1];
+      if(*ymax < triangles[i].vertex[j].xyz[1])
+        *ymax = triangles[i].vertex[j].xyz[1];
+    }
+  }
+}
+
+/* Writes shaded triangle 
+   gray == 0 means write RGB triangles
+   gray == 8             8bit-grayscale (for alpha masks)
+   gray == 16            16bit-grayscale (for alpha masks) */
+
+static int gl2psPrintPDFShader(int obj, GL2PStriangle *triangles, 
+                               int size, int gray)
+{
+  int i, offs = 0, vertexbytes, done = 0;
+  GLfloat xmin, xmax, ymin, ymax;
+        
+  switch(gray){
+  case 0:
+    vertexbytes = 1+4+4+1+1+1;
+    break;
+  case 8:
+    vertexbytes = 1+4+4+1;
+    break;
+  case 16:
+    vertexbytes = 1+4+4+2;
+    break;
+  default:
+    gray = 8;
+    vertexbytes = 1+4+4+1;
+    break;
+  }
+  
+  gl2psPDFRectHull(&xmin, &xmax, &ymin, &ymax, triangles, size);
+  
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<< "
+                  "/ShadingType 4 "
+                  "/ColorSpace %s "
+                  "/BitsPerCoordinate 32 "
+                  "/BitsPerComponent %d "
+                  "/BitsPerFlag 8 "
+                  "/Decode [%f %f %f %f 0 1 %s] ",
+                  obj,
+                  (gray) ? "/DeviceGray" : "/DeviceRGB", 
+                  (gray) ? gray : 8,
+                  xmin, xmax, ymin, ymax,
+                  (gray) ? "" : "0 1 0 1");
+  
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    gl2psAllocCompress(vertexbytes * size * 3);
+
+    for(i = 0; i < size; ++i)
+      gl2psPrintPDFShaderStreamData(&triangles[i],
+                                    xmax-xmin, ymax-ymin, xmin, ymin, 
+                                    gl2psWriteBigEndianCompress, gray);
+
+    if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
+      offs += gl2psPrintPDFCompressorType();
+      offs += fprintf(gl2ps->stream,
+                      "/Length %d "
+                      ">>\n"
+                      "stream\n",
+                      (int)gl2ps->compress->destLen);
+      offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, 
+                                                gl2ps->compress->destLen, 
+                                                1, gl2ps->stream);
+      done = 1;
+    }
+    gl2psFreeCompress();
+  }
+#endif
+
+  if(!done){
+    /* no compression, or too long after compression, or compress error
+       -> write non-compressed entry */
+    offs += fprintf(gl2ps->stream,
+                    "/Length %d "
+                    ">>\n"
+                    "stream\n",
+                    vertexbytes * 3 * size);
+    for(i = 0; i < size; ++i)
+      offs += gl2psPrintPDFShaderStreamData(&triangles[i],
+                                            xmax-xmin, ymax-ymin, xmin, ymin,
+                                            gl2psWriteBigEndian, gray);
+  }
+  
+  offs += fprintf(gl2ps->stream,
+                  "\nendstream\n"
+                  "endobj\n");
+  
+  return offs;
+}
+
+/* Writes a XObject for a shaded triangle mask */
+
+static int gl2psPrintPDFShaderMask(int obj, int childobj)
+{
+  int offs = 0, len;
+  
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<<\n"
+                  "/Type /XObject\n"
+                  "/Subtype /Form\n"
+                  "/BBox [ %d %d %d %d ]\n"
+                  "/Group \n<<\n/S /Transparency /CS /DeviceRGB\n"
+                  ">>\n",
+                  obj,
+                  (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
+                  (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
+  
+  len = (childobj>0) 
+    ? strlen("/TrSh sh\n") + (int)log10((double)childobj)+1
+    : strlen("/TrSh0 sh\n"); 
+  
+  offs += fprintf(gl2ps->stream,
+                  "/Length %d\n"
+                  ">>\n"
+                  "stream\n",
+                  len);
+  offs += fprintf(gl2ps->stream,
+                  "/TrSh%d sh\n",
+                  childobj);
+  offs += fprintf(gl2ps->stream,
+                  "endstream\n"
+                  "endobj\n");
+  
+  return offs;
+}
+
+/* Writes a Extended graphics state for a shaded triangle mask if
+   simplealpha ist true the childobj argument is ignored and a /ca
+   statement will be written instead */
+
+static int gl2psPrintPDFShaderExtGS(int obj, int childobj)
+{
+  int offs = 0;
+  
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<<\n",
+                  obj);
+  
+  offs += fprintf(gl2ps->stream,
+                  "/SMask << /S /Alpha /G %d 0 R >> ",
+                  childobj);
+  
+  offs += fprintf(gl2ps->stream,
+                  ">>\n"
+                  "endobj\n");
+  return offs;
+}
+
+/* a simple graphics state */
+
+static int gl2psPrintPDFShaderSimpleExtGS(int obj, GLfloat alpha)
+{
+  int offs = 0;
+  
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<<\n"
+                  "/ca %g"
+                  ">>\n"
+                  "endobj\n",
+                  obj, alpha);
+  return offs;
+}
+
+/* Similar groups of functions for pixmaps and text */
+
+static int gl2psPrintPDFPixmapStreamData(GL2PSimage *im,
+                                         size_t (*action)(unsigned long data, 
+                                                          size_t size), 
+                                         int gray)
+{
+  int x, y;
+  GLfloat r, g, b, a;
+
+  if(im->format != GL_RGBA && gray)
+    return 0;
+
+  if(gray && gray !=8 && gray != 16)
+    gray = 8;
+
+  gray /= 8;
+  
+  for(y = 0; y < im->height; ++y){
+    for(x = 0; x < im->width; ++x){
+      a = gl2psGetRGB(im, x, y, &r, &g, &b);
+      if(im->format == GL_RGBA && gray){
+        (*action)((unsigned long)(a*255) << 24, gray);
+      }
+      else{
+        (*action)((unsigned long)(r*255) << 24, 1);
+        (*action)((unsigned long)(g*255) << 24, 1);
+        (*action)((unsigned long)(b*255) << 24, 1);
+      }
+    }
+  }
+
+  switch(gray){
+  case 0: return 3 * im->width * im->height;
+  case 1: return im->width * im->height;
+  case 2: return 2 * im->width * im->height;
+  default: return 3 * im->width * im->height;
+  }
+}
+
+static int gl2psPrintPDFPixmap(int obj, int childobj, GL2PSimage *im, int gray)
+{
+  int offs = 0, done = 0, sigbytes = 3;
+
+  if(gray && gray !=8 && gray != 16)
+    gray = 8;
+  
+  if(gray)
+    sigbytes = gray / 8; 
+  
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<<\n"
+                  "/Type /XObject\n"
+                  "/Subtype /Image\n"
+                  "/Width %d\n"
+                  "/Height %d\n"
+                  "/ColorSpace %s \n"
+                  "/BitsPerComponent 8\n",
+                  obj,
+                  (int)im->width, (int)im->height,
+                  (gray) ? "/DeviceGray" : "/DeviceRGB" );
+  if(GL_RGBA == im->format && gray == 0){
+    offs += fprintf(gl2ps->stream,
+                    "/SMask %d 0 R\n",
+                    childobj);
+  }
+  
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    gl2psAllocCompress((int)(im->width * im->height * sigbytes));
+    
+    gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndianCompress, gray);
+    
+    if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
+      offs += gl2psPrintPDFCompressorType();
+      offs += fprintf(gl2ps->stream,
+                      "/Length %d "
+                      ">>\n"
+                      "stream\n",
+                      (int)gl2ps->compress->destLen);
+      offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, gl2ps->compress->destLen,
+                                                1, gl2ps->stream);
+      done = 1;
+    }
+    gl2psFreeCompress();
+  }
+#endif
+  
+  if(!done){
+    /* no compression, or too long after compression, or compress error
+       -> write non-compressed entry */
+    offs += fprintf(gl2ps->stream,
+                    "/Length %d "
+                    ">>\n"
+                    "stream\n",
+                    (int)(im->width * im->height * sigbytes));
+    offs += gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndian, gray);
+  }
+  
+  offs += fprintf(gl2ps->stream,
+                  "\nendstream\n"
+                  "endobj\n");
+  
+  return offs;
+}
+
+static int gl2psPrintPDFText(int obj, GL2PSstring *s, int fontnumber)
+{
+  int offs = 0;
+  
+  offs += fprintf(gl2ps->stream,
+                  "%d 0 obj\n"
+                  "<<\n"
+                  "/Type /Font\n"
+                  "/Subtype /Type1\n"
+                  "/Name /F%d\n"
+                  "/BaseFont /%s\n"
+                  "/Encoding /MacRomanEncoding\n"
+                  ">>\n"
+                  "endobj\n",
+                  obj, fontnumber, s->fontname);
+  return offs;
+}
+
+/* Write the physical objects */
+
+static int gl2psPDFgroupListWriteObjects(int entryoffs)
+{
+  int i,j;
+  GL2PSprimitive *p = NULL;
+  GL2PSpdfgroup *gro;
+  int offs = entryoffs;
+  GL2PStriangle *triangles;
+  int size = 0;
+
+  if(!gl2ps->pdfgrouplist)
+    return offs;
+  
+  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){  
+    gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i); 
+    if(!gl2psListNbr(gro->ptrlist))
+      continue;
+    p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
+    switch(p->type){
+    case GL2PS_POINT:
+      break;
+    case GL2PS_LINE:
+      break;
+    case GL2PS_TRIANGLE:
+      size = gl2psListNbr(gro->ptrlist);
+      triangles = (GL2PStriangle*)gl2psMalloc(sizeof(GL2PStriangle) * size);
+      for(j = 0; j < size; ++j){  
+        p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+        gl2psFillTriangleFromPrimitive(&triangles[j], p, GL_TRUE);
+      }
+      if(triangles[0].prop & T_VAR_COLOR){
+        gl2ps->xreflist[gro->shobjno] = offs;
+        offs += gl2psPrintPDFShader(gro->shobjno, triangles, size, 0);
+      }
+      if(triangles[0].prop & T_ALPHA_LESS_1){
+        gl2ps->xreflist[gro->gsobjno] = offs;
+        offs += gl2psPrintPDFShaderSimpleExtGS(gro->gsobjno, triangles[0].vertex[0].rgba[3]);
+      }
+      if(triangles[0].prop & T_VAR_ALPHA){
+        gl2ps->xreflist[gro->gsobjno] = offs;
+        offs += gl2psPrintPDFShaderExtGS(gro->gsobjno, gro->trgroupobjno);
+        gl2ps->xreflist[gro->trgroupobjno] = offs;
+        offs += gl2psPrintPDFShaderMask(gro->trgroupobjno, gro->maskshno);
+        gl2ps->xreflist[gro->maskshobjno] = offs;
+        offs += gl2psPrintPDFShader(gro->maskshobjno, triangles, size, 8);
+      }
+      gl2psFree(triangles);
+      break;
+    case GL2PS_PIXMAP:
+      gl2ps->xreflist[gro->imobjno] = offs;
+      offs += gl2psPrintPDFPixmap(gro->imobjno, gro->imobjno+1, p->data.image, 0);
+      if(p->data.image->format == GL_RGBA){
+        gl2ps->xreflist[gro->imobjno+1] = offs;
+        offs += gl2psPrintPDFPixmap(gro->imobjno+1, -1, p->data.image, 8);
+      }
+      break;
+    case GL2PS_TEXT:
+      gl2ps->xreflist[gro->fontobjno] = offs;
+      offs += gl2psPrintPDFText(gro->fontobjno,p->data.text,gro->fontno);
+      break;
+    case GL2PS_SPECIAL :
+      /* alignment contains the format for which the special output text
+         is intended */
+      if(p->data.text->alignment == GL2PS_PDF)
+        offs += fprintf(gl2ps->stream, "%s\n", p->data.text->str);
+      break;
+    default:
+      break;
+    } 
+  }
+  return offs;
+}
+
+/* All variable data has been written at this point and all required
+   functioninality has been gathered, so we can write now file footer
+   with cross reference table and trailer */
+
+static void gl2psPrintPDFFooter(void)
+{
+  int i, offs;  
+
+  gl2psPDFgroupListInit();
+  gl2psPDFgroupListWriteMainStream();
+ 
+  offs = gl2ps->xreflist[5] + gl2ps->streamlength; 
+  offs += gl2psClosePDFDataStream();
+  gl2ps->xreflist[5] = offs;
+  
+  offs += gl2psPrintPDFDataStreamLength(gl2ps->streamlength);
+  gl2ps->xreflist[6] = offs;
+  gl2ps->streamlength = 0;
+  
+  offs += gl2psPrintPDFOpenPage();
+  offs += gl2psPDFgroupListWriteVariableResources();
+  gl2ps->xreflist = (int*)gl2psRealloc(gl2ps->xreflist,
+                                       sizeof(int) * (gl2ps->objects_stack + 1));
+  gl2ps->xreflist[7] = offs;
+  
+  offs += gl2psPrintPDFGSObject();
+  gl2ps->xreflist[8] = offs;
+  
+  gl2ps->xreflist[gl2ps->objects_stack] = 
+    gl2psPDFgroupListWriteObjects(gl2ps->xreflist[8]);
+
+  /* Start cross reference table. The file has to been opened in
+     binary mode to preserve the 20 digit string length! */
+  fprintf(gl2ps->stream,
+          "xref\n"
+          "0 %d\n"
+          "%010d 65535 f \n", gl2ps->objects_stack, 0);
+  
+  for(i = 1; i < gl2ps->objects_stack; ++i)
+    fprintf(gl2ps->stream, "%010d 00000 n \n", gl2ps->xreflist[i]);
+  
+  fprintf(gl2ps->stream,
+          "trailer\n"
+          "<<\n" 
+          "/Size %d\n"
+          "/Info 1 0 R\n"
+          "/Root 2 0 R\n"
+          ">>\n"
+          "startxref\n%d\n"
+          "%%%%EOF\n",
+          gl2ps->objects_stack, gl2ps->xreflist[gl2ps->objects_stack]);
+  
+  /* Free auxiliary lists and arrays */    
+  gl2psFree(gl2ps->xreflist);
+  gl2psListDelete(gl2ps->pdfprimlist);
+  gl2psPDFgroupListDelete();
+  
+#if defined(GL2PS_HAVE_ZLIB)
+  if(gl2ps->options & GL2PS_COMPRESS){
+    gl2psFreeCompress();
+    gl2psFree(gl2ps->compress);
+    gl2ps->compress = NULL;
+  }
+#endif
+}
+
+/* PDF begin viewport */
+
+static void gl2psPrintPDFBeginViewport(GLint viewport[4])
+{
+  int offs = 0;
+  GLint index;
+  GLfloat rgba[4];
+  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
+  
+  glRenderMode(GL_FEEDBACK);
+  
+  if(gl2ps->header){
+    gl2psPrintPDFHeader();
+    gl2ps->header = GL_FALSE;
+  }
+
+  offs += gl2psPrintf("q\n");
+  
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
+      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
+    }
+    else{
+      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
+      rgba[0] = gl2ps->colormap[index][0];
+      rgba[1] = gl2ps->colormap[index][1];
+      rgba[2] = gl2ps->colormap[index][2];
+      rgba[3] = 1.0F;
+    }
+    offs += gl2psPrintPDFFillColor(rgba);
+    offs += gl2psPrintf("%d %d %d %d re\n"
+                        "W\n"
+                        "f\n",
+                        x, y, w, h);
+  }
+  else{
+    offs += gl2psPrintf("%d %d %d %d re\n"
+                        "W\n"   
+                        "n\n",
+                        x, y, w, h);            
+  }
+  
+  gl2ps->streamlength += offs;
+}
+
+static GLint gl2psPrintPDFEndViewport(void)
+{
+  GLint res;
+  
+  res = gl2psPrintPrimitives();
+  gl2ps->streamlength += gl2psPrintf("Q\n");
+  return res;
+}
+
+static void gl2psPrintPDFFinalPrimitive(void)
+{
+}
+
+/* definition of the PDF backend */
+
+static GL2PSbackend gl2psPDF = {
+  gl2psPrintPDFHeader,
+  gl2psPrintPDFFooter,
+  gl2psPrintPDFBeginViewport,
+  gl2psPrintPDFEndViewport,
+  gl2psPrintPDFPrimitive,
+  gl2psPrintPDFFinalPrimitive,
+  "pdf",
+  "Portable Document Format"
+};
+
+/********************************************************************* 
+ *
+ * SVG routines
+ *
+ *********************************************************************/
+
+static void gl2psSVGGetCoordsAndColors(int n, GL2PSvertex *verts, 
+                                       GL2PSxyz *xyz, GL2PSrgba *rgba)
+{
+  int i, j;
+
+  for(i = 0; i < n; i++){
+    xyz[i][0] = verts[i].xyz[0];
+    xyz[i][1] = gl2ps->viewport[3] - verts[i].xyz[1];
+    xyz[i][2] = 0.0F;
+    for(j = 0; j < 4; j++)
+      rgba[i][j] = verts[i].rgba[j];
+  }
+}
+
+static void gl2psSVGGetColorString(GL2PSrgba rgba, char str[32])
+{
+  int r = (int)(255. * rgba[0]);
+  int g = (int)(255. * rgba[1]);
+  int b = (int)(255. * rgba[2]);
+  int rc = (r < 0) ? 0 : (r > 255) ? 255 : r;
+  int gc = (g < 0) ? 0 : (g > 255) ? 255 : g;
+  int bc = (b < 0) ? 0 : (b > 255) ? 255 : b;
+  sprintf(str, "#%2.2x%2.2x%2.2x", rc, gc, bc);
+}
+
+static void gl2psPrintSVGHeader(void)
+{
+  int x, y, width, height;
+  char col[32];
+  time_t now;
+  
+  time(&now);
+  
+  if (gl2ps->options & GL2PS_LANDSCAPE){
+    x = (int)gl2ps->viewport[1];
+    y = (int)gl2ps->viewport[0];
+    width = (int)gl2ps->viewport[3];
+    height = (int)gl2ps->viewport[2];
+  }
+  else{
+    x = (int)gl2ps->viewport[0];
+    y = (int)gl2ps->viewport[1];
+    width = (int)gl2ps->viewport[2];
+    height = (int)gl2ps->viewport[3];
+  }
+  
+  /* Compressed SVG files (.svgz) are simply gzipped SVG files */
+  gl2psPrintGzipHeader();
+  
+  gl2psPrintf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
+  gl2psPrintf("<svg xmlns=\"http://www.w3.org/2000/svg\"\n");
+  gl2psPrintf("     xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
+              "     width=\"%dpx\" height=\"%dpx\" viewBox=\"%d %d %d %d\">\n",
+              width, height, x, y, width, height);
+  gl2psPrintf("<title>%s</title>\n", gl2ps->title);
+  gl2psPrintf("<desc>\n");
+  gl2psPrintf("Creator: GL2PS %d.%d.%d%s, %s\n"
+              "For: %s\n"
+              "CreationDate: %s",
+              GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, GL2PS_PATCH_VERSION,
+              GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT, gl2ps->producer, ctime(&now));
+  gl2psPrintf("</desc>\n");
+  gl2psPrintf("<defs>\n");
+  gl2psPrintf("</defs>\n");
+
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    gl2psSVGGetColorString(gl2ps->bgcolor, col);
+    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], 
+                (int)gl2ps->viewport[2], (int)gl2ps->viewport[1], 
+                (int)gl2ps->viewport[2], (int)gl2ps->viewport[3], 
+                (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
+  }
+
+  gl2psPrintf("<g>\n");
+}
+
+static void gl2psPrintSVGSmoothTriangle(GL2PSxyz xyz[3], GL2PSrgba rgba[3])
+{
+  int i;
+  GL2PSxyz xyz2[3];
+  GL2PSrgba rgba2[3];
+  char col[32];
+
+  /* Apparently there is no easy way to do Gouraud shading in SVG
+     without explicitly pre-defining gradients, so for now we just do
+     recursive subdivision */
+
+  if(gl2psSameColorThreshold(3, rgba, gl2ps->threshold)){
+    gl2psSVGGetColorString(rgba[0], col);
+    gl2psPrintf("<polygon fill=\"%s\" ", col);
+    if(rgba[0][3] < 1.0F) gl2psPrintf("fill-opacity=\"%g\" ", rgba[0][3]);
+    gl2psPrintf("points=\"%g,%g %g,%g %g,%g\"/>\n", xyz[0][0], xyz[0][1], 
+                xyz[1][0], xyz[1][1], xyz[2][0], xyz[2][1]);
+  }
+  else{
+    /* subdivide into 4 subtriangles */
+    for(i = 0; i < 3; i++){
+      xyz2[0][i] = xyz[0][i]; 
+      xyz2[1][i] = 0.5f * (xyz[0][i] + xyz[1][i]);
+      xyz2[2][i] = 0.5f * (xyz[0][i] + xyz[2][i]);
+    }
+    for(i = 0; i < 4; i++){
+      rgba2[0][i] = rgba[0][i]; 
+      rgba2[1][i] = 0.5f * (rgba[0][i] + rgba[1][i]);
+      rgba2[2][i] = 0.5f * (rgba[0][i] + rgba[2][i]);
+    }
+    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
+    for(i = 0; i < 3; i++){
+      xyz2[0][i] = 0.5f * (xyz[0][i] + xyz[1][i]);
+      xyz2[1][i] = xyz[1][i]; 
+      xyz2[2][i] = 0.5f * (xyz[1][i] + xyz[2][i]);
+    }
+    for(i = 0; i < 4; i++){
+      rgba2[0][i] = 0.5f * (rgba[0][i] + rgba[1][i]);
+      rgba2[1][i] = rgba[1][i]; 
+      rgba2[2][i] = 0.5f * (rgba[1][i] + rgba[2][i]);
+    }
+    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
+    for(i = 0; i < 3; i++){
+      xyz2[0][i] = 0.5f * (xyz[0][i] + xyz[2][i]);
+      xyz2[1][i] = xyz[2][i]; 
+      xyz2[2][i] = 0.5f * (xyz[1][i] + xyz[2][i]);
+    }
+    for(i = 0; i < 4; i++){
+      rgba2[0][i] = 0.5f * (rgba[0][i] + rgba[2][i]);
+      rgba2[1][i] = rgba[2][i]; 
+      rgba2[2][i] = 0.5f * (rgba[1][i] + rgba[2][i]);
+    }
+    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
+    for(i = 0; i < 3; i++){
+      xyz2[0][i] = 0.5f * (xyz[0][i] + xyz[1][i]);
+      xyz2[1][i] = 0.5f * (xyz[1][i] + xyz[2][i]); 
+      xyz2[2][i] = 0.5f * (xyz[0][i] + xyz[2][i]);
+    }
+    for(i = 0; i < 4; i++){
+      rgba2[0][i] = 0.5f * (rgba[0][i] + rgba[1][i]);
+      rgba2[1][i] = 0.5f * (rgba[1][i] + rgba[2][i]); 
+      rgba2[2][i] = 0.5f * (rgba[0][i] + rgba[2][i]);
+    }
+    gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
+  }
+}
+
+static void gl2psPrintSVGDash(GLushort pattern, GLint factor)
+{
+  int i, n, array[10];
+
+  if(!pattern || !factor) return; /* solid line */
+
+  gl2psParseStipplePattern(pattern, factor, &n, array);
+  gl2psPrintf("stroke-dasharray=\"");
+  for(i = 0; i < n; i++){
+    if(i) gl2psPrintf(",");
+    gl2psPrintf("%d", array[i]);
+  }
+  gl2psPrintf("\" ");
+}
+
+static void gl2psEndSVGLine(void)
+{
+  int i;
+  if(gl2ps->lastvertex.rgba[0] >= 0.){
+    gl2psPrintf("%g,%g\"/>\n", gl2ps->lastvertex.xyz[0], 
+                gl2ps->viewport[3] - gl2ps->lastvertex.xyz[1]);
+    for(i = 0; i < 3; i++)
+      gl2ps->lastvertex.xyz[i] = -1.;
+    for(i = 0; i < 4; i++)
+      gl2ps->lastvertex.rgba[i] = -1.;
+  }
+}
+
+static void gl2psPrintSVGPixmap(GLfloat x, GLfloat y, GL2PSimage *pixmap)
+{
+#if defined(GL2PS_HAVE_LIBPNG)
+  GL2PSlist *png;
+  unsigned char c;
+  int i;
+
+  /* The only image types supported by the SVG standard are JPEG, PNG
+     and SVG. Here we choose PNG, and since we want to embed the image
+     directly in the SVG stream (and not link to an external image
+     file), we need to encode the pixmap into PNG in memory, then
+     encode it into base64. */
+
+  png = gl2psListCreate(pixmap->width * pixmap->height * 3, 1000, 
+                        sizeof(unsigned char));
+  gl2psConvertPixmapToPNG(pixmap, png);
+  gl2psListEncodeBase64(png);
+  gl2psPrintf("<image x=\"%g\" y=\"%g\" width=\"%d\" height=\"%d\"\n",
+              x, y - pixmap->height, pixmap->width, pixmap->height);
+  gl2psPrintf("xlink:href=\"data:image/png;base64,");
+  for(i = 0; i < gl2psListNbr(png); i++){
+    gl2psListRead(png, i, &c);
+    gl2psPrintf("%c", c);
+  }
+  gl2psPrintf("\"/>\n");
+  gl2psListDelete(png);
+#else
+  gl2psMsg(GL2PS_WARNING, "GL2PS has to be compiled with PNG support in "
+           "order to embed images in SVG streams");
+#endif
+}
+
+static void gl2psPrintSVGPrimitive(void *data)
+{
+  GL2PSprimitive *prim;
+  GL2PSxyz xyz[4];
+  GL2PSrgba rgba[4];
+  char col[32];
+  int newline;
+
+  prim = *(GL2PSprimitive**)data;
+
+  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return;
+
+  /* We try to draw connected lines as a single path to get nice line
+     joins and correct stippling. So if the primitive to print is not
+     a line we must first finish the current line (if any): */
+  if(prim->type != GL2PS_LINE) gl2psEndSVGLine();
+
+  gl2psSVGGetCoordsAndColors(prim->numverts, prim->verts, xyz, rgba);
+
+  switch(prim->type){
+  case GL2PS_POINT :
+    gl2psSVGGetColorString(rgba[0], col);
+    gl2psPrintf("<circle fill=\"%s\" ", col);
+    if(rgba[0][3] < 1.0F) gl2psPrintf("fill-opacity=\"%g\" ", rgba[0][3]);
+    gl2psPrintf("cx=\"%g\" cy=\"%g\" r=\"%g\"/>\n",
+                xyz[0][0], xyz[0][1], 0.5 * prim->width);
+    break;
+  case GL2PS_LINE :
+    if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
+       !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
+       gl2ps->lastlinewidth != prim->width ||
+       gl2ps->lastpattern != prim->pattern ||
+       gl2ps->lastfactor != prim->factor){
+      /* End the current line if the new segment does not start where
+         the last one ended, or if the color, the width or the
+         stippling have changed (we will need to use multi-point
+         gradients for smooth-shaded lines) */
+      gl2psEndSVGLine();
+      newline = 1;
+    }
+    else{
+      newline = 0;
+    }
+    gl2ps->lastvertex = prim->verts[1];
+    gl2psSetLastColor(prim->verts[0].rgba);
+    gl2ps->lastlinewidth = prim->width;
+    gl2ps->lastpattern = prim->pattern;
+    gl2ps->lastfactor = prim->factor;
+    if(newline){
+      gl2psSVGGetColorString(rgba[0], col);
+      gl2psPrintf("<polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%g\" ", 
+                  col, prim->width);
+      if(rgba[0][3] < 1.0F) gl2psPrintf("stroke-opacity=\"%g\" ", rgba[0][3]);
+      gl2psPrintSVGDash(prim->pattern, prim->factor);
+      gl2psPrintf("points=\"%g,%g ", xyz[0][0], xyz[0][1]);
+    }
+    else{
+      gl2psPrintf("%g,%g ", xyz[0][0], xyz[0][1]);
+    }
+    break;
+  case GL2PS_TRIANGLE :
+    gl2psPrintSVGSmoothTriangle(xyz, rgba);
+    break;
+  case GL2PS_QUADRANGLE :
+    gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print");
+    break;
+  case GL2PS_PIXMAP :
+    gl2psPrintSVGPixmap(xyz[0][0], xyz[0][1], prim->data.image);
+    break;
+  case GL2PS_TEXT :
+    gl2psSVGGetColorString(prim->verts[0].rgba, col);
+    gl2psPrintf("<text fill=\"%s\" x=\"%g\" y=\"%g\" "
+                "font-size=\"%d\" font-family=\"%s\">%s</text>\n",
+                col, xyz[0][0], xyz[0][1],
+                prim->data.text->fontsize,
+                prim->data.text->fontname,
+                prim->data.text->str);
+    break;
+  case GL2PS_SPECIAL :
+    /* alignment contains the format for which the special output text
+       is intended */
+    if(prim->data.text->alignment == GL2PS_SVG)
+      gl2psPrintf("%s\n", prim->data.text->str);
+    break;
+  default :
+    break;
+  }
+}
+
+static void gl2psPrintSVGFooter(void)
+{
+  gl2psPrintf("</g>\n");
+  gl2psPrintf("</svg>\n");  
+  
+  gl2psPrintGzipFooter();
+}
+
+static void gl2psPrintSVGBeginViewport(GLint viewport[4])
+{
+  GLint index;
+  char col[32];
+  GLfloat rgba[4];
+  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
+
+  glRenderMode(GL_FEEDBACK);
+  
+  if(gl2ps->header){
+    gl2psPrintSVGHeader();
+    gl2ps->header = GL_FALSE;
+  }
+
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
+      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
+    }
+    else{
+      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
+      rgba[0] = gl2ps->colormap[index][0];
+      rgba[1] = gl2ps->colormap[index][1];
+      rgba[2] = gl2ps->colormap[index][2];
+      rgba[3] = 1.0F;
+    }
+    gl2psSVGGetColorString(rgba, col);
+    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col, 
+                x, gl2ps->viewport[3] - y, 
+                x + w, gl2ps->viewport[3] - y, 
+                x + w, gl2ps->viewport[3] - (y + h), 
+                x, gl2ps->viewport[3] - (y + h));
+  }
+
+  gl2psPrintf("<clipPath id=\"cp%d%d%d%d\">\n", x, y, w, h);
+  gl2psPrintf("  <polygon points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", 
+              x, gl2ps->viewport[3] - y, 
+              x + w, gl2ps->viewport[3] - y, 
+              x + w, gl2ps->viewport[3] - (y + h), 
+              x, gl2ps->viewport[3] - (y + h));
+  gl2psPrintf("</clipPath>\n");
+  gl2psPrintf("<g clip-path=\"url(#cp%d%d%d%d)\">\n", x, y, w, h);
+}
+
+static GLint gl2psPrintSVGEndViewport(void)
+{
+  GLint res;
+
+  res = gl2psPrintPrimitives();
+  gl2psPrintf("</g>\n");
+  return res;
+}
+
+static void gl2psPrintSVGFinalPrimitive(void)
+{
+  /* End any remaining line, if any */
+  gl2psEndSVGLine();
+}
+
+/* definition of the SVG backend */
+
+static GL2PSbackend gl2psSVG = {
+  gl2psPrintSVGHeader,
+  gl2psPrintSVGFooter,
+  gl2psPrintSVGBeginViewport,
+  gl2psPrintSVGEndViewport,
+  gl2psPrintSVGPrimitive,
+  gl2psPrintSVGFinalPrimitive,
+  "svg",
+  "Scalable Vector Graphics"
+};
+
+/*********************************************************************
+ *
+ * PGF routines
+ *
+ *********************************************************************/
+
+static void gl2psPrintPGFColor(GL2PSrgba rgba)
+{
+  if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
+    gl2psSetLastColor(rgba);
+    fprintf(gl2ps->stream, "\\color[rgb]{%f,%f,%f}\n", rgba[0], rgba[1], rgba[2]);
+  }
+}
+
+static void gl2psPrintPGFHeader(void)
+{
+  time_t now;
+
+  time(&now);
+
+  fprintf(gl2ps->stream, 
+          "%% Title: %s\n"
+          "%% Creator: GL2PS %d.%d.%d%s, %s\n"
+          "%% For: %s\n"
+          "%% CreationDate: %s",
+          gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
+          GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
+          gl2ps->producer, ctime(&now));
+
+  fprintf(gl2ps->stream, "\\begin{pgfpicture}\n");
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    gl2psPrintPGFColor(gl2ps->bgcolor);
+    fprintf(gl2ps->stream,
+            "\\pgfpathrectanglecorners{"
+            "\\pgfpoint{%dpt}{%dpt}}{\\pgfpoint{%dpt}{%dpt}}\n"
+            "\\pgfusepath{fill}\n",
+            (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
+            (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
+  }
+}
+
+static void gl2psPrintPGFDash(GLushort pattern, GLint factor)
+{
+  int i, n, array[10];
+
+  if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
+    return;
+
+  gl2ps->lastpattern = pattern;
+  gl2ps->lastfactor = factor;
+
+  if(!pattern || !factor){
+    /* solid line */
+    fprintf(gl2ps->stream, "\\pgfsetdash{}{0pt}\n");
+  }
+  else{
+    gl2psParseStipplePattern(pattern, factor, &n, array);
+    fprintf(gl2ps->stream, "\\pgfsetdash{");
+    for(i = 0; i < n; i++) fprintf(gl2ps->stream, "{%dpt}", array[i]);
+    fprintf(gl2ps->stream, "}{0pt}\n");
+  }
+}
+
+static const char *gl2psPGFTextAlignment(int align)
+{
+  switch(align){
+  case GL2PS_TEXT_C  : return "center";
+  case GL2PS_TEXT_CL : return "west";
+  case GL2PS_TEXT_CR : return "east";
+  case GL2PS_TEXT_B  : return "south";
+  case GL2PS_TEXT_BR : return "south east";
+  case GL2PS_TEXT_T  : return "north";
+  case GL2PS_TEXT_TL : return "north west";
+  case GL2PS_TEXT_TR : return "north east";
+  case GL2PS_TEXT_BL : 
+  default            : return "south west";
+  }
+}
+
+static void gl2psPrintPGFPrimitive(void *data)
+{
+  GL2PSprimitive *prim;
+
+  prim = *(GL2PSprimitive**)data;
+
+  switch(prim->type){
+  case GL2PS_POINT :
+    /* Points in openGL are rectangular */
+    gl2psPrintPGFColor(prim->verts[0].rgba);
+    fprintf(gl2ps->stream, 
+            "\\pgfpathrectangle{\\pgfpoint{%fpt}{%fpt}}"
+            "{\\pgfpoint{%fpt}{%fpt}}\n\\pgfusepath{fill}\n",
+            prim->verts[0].xyz[0]-0.5*prim->width,
+            prim->verts[0].xyz[1]-0.5*prim->width,
+            prim->width,prim->width);
+    break;
+  case GL2PS_LINE :
+    gl2psPrintPGFColor(prim->verts[0].rgba);
+    if(gl2ps->lastlinewidth != prim->width){
+      gl2ps->lastlinewidth = prim->width;
+      fprintf(gl2ps->stream, "\\pgfsetlinewidth{%fpt}\n", gl2ps->lastlinewidth);
+    }
+    gl2psPrintPGFDash(prim->pattern, prim->factor);
+    fprintf(gl2ps->stream, 
+            "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
+            "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
+            "\\pgfusepath{stroke}\n",
+            prim->verts[1].xyz[0], prim->verts[1].xyz[1],
+            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+    break;
+  case GL2PS_TRIANGLE :
+    if(gl2ps->lastlinewidth != 0){
+      gl2ps->lastlinewidth = 0;
+      fprintf(gl2ps->stream, "\\pgfsetlinewidth{0.01pt}\n");
+    }
+    gl2psPrintPGFColor(prim->verts[0].rgba);
+    fprintf(gl2ps->stream, 
+            "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
+            "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
+            "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
+            "\\pgfpathclose\n"
+            "\\pgfusepath{fill,stroke}\n",
+            prim->verts[2].xyz[0], prim->verts[2].xyz[1],
+            prim->verts[1].xyz[0], prim->verts[1].xyz[1],
+            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+    break;
+  case GL2PS_TEXT :
+    fprintf(gl2ps->stream, "{\n\\pgftransformshift{\\pgfpoint{%fpt}{%fpt}}\n",
+            prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+
+    if(prim->data.text->angle)
+      fprintf(gl2ps->stream, "\\pgftransformrotate{%f}{", prim->data.text->angle);
+
+    fprintf(gl2ps->stream, "\\pgfnode{rectangle}{%s}{\\fontsize{%d}{0}\\selectfont",
+            gl2psPGFTextAlignment(prim->data.text->alignment),
+            prim->data.text->fontsize);
+
+    fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
+            prim->verts[0].rgba[0], prim->verts[0].rgba[1],
+            prim->verts[0].rgba[2], prim->data.text->str);
+
+    fprintf(gl2ps->stream, "}{}{\\pgfusepath{discard}}}\n");
+    break;
+  case GL2PS_SPECIAL :
+    /* alignment contains the format for which the special output text
+       is intended */
+    if (prim->data.text->alignment == GL2PS_PGF)
+      fprintf(gl2ps->stream, "%s\n", prim->data.text->str);
+    break;
+  default :
+    break;
+  }
+}
+
+static void gl2psPrintPGFFooter(void)
+{
+  fprintf(gl2ps->stream, "\\end{pgfpicture}\n");
+}
+
+static void gl2psPrintPGFBeginViewport(GLint viewport[4])
+{
+  GLint index;
+  GLfloat rgba[4];
+  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
+
+  glRenderMode(GL_FEEDBACK);
+
+  if(gl2ps->header){
+    gl2psPrintPGFHeader();
+    gl2ps->header = GL_FALSE;
+  }
+
+  fprintf(gl2ps->stream, "\\begin{pgfscope}\n");
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
+      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
+    }
+    else{
+      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
+      rgba[0] = gl2ps->colormap[index][0];
+      rgba[1] = gl2ps->colormap[index][1];
+      rgba[2] = gl2ps->colormap[index][2];
+      rgba[3] = 1.0F;
+    }
+    gl2psPrintPGFColor(rgba);
+    fprintf(gl2ps->stream, 
+            "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
+            "{\\pgfpoint{%dpt}{%dpt}}\n"
+            "\\pgfusepath{fill}\n",
+            x, y, w, h);
+  }
+  
+  fprintf(gl2ps->stream, 
+          "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
+          "{\\pgfpoint{%dpt}{%dpt}}\n"
+          "\\pgfusepath{clip}\n",
+          x, y, w, h);
+}
+
+static GLint gl2psPrintPGFEndViewport(void)
+{
+  GLint res;
+  res = gl2psPrintPrimitives();
+  fprintf(gl2ps->stream, "\\end{pgfscope}\n");
+  return res;
+}
+
+static void gl2psPrintPGFFinalPrimitive(void)
+{
+}
+
+/* definition of the PGF backend */
+
+static GL2PSbackend gl2psPGF = {
+  gl2psPrintPGFHeader,
+  gl2psPrintPGFFooter,
+  gl2psPrintPGFBeginViewport,
+  gl2psPrintPGFEndViewport,
+  gl2psPrintPGFPrimitive,
+  gl2psPrintPGFFinalPrimitive,
+  "tex",
+  "PGF Latex Graphics"
+};
+
+/********************************************************************* 
+ *
+ * General primitive printing routine
+ *
+ *********************************************************************/
+
+/* Warning: the ordering of the backends must match the format
+   #defines in gl2ps.h */
+
+static GL2PSbackend *gl2psbackends[] = {
+  &gl2psPS,  /* 0 */
+  &gl2psEPS, /* 1 */
+  &gl2psTEX, /* 2 */
+  &gl2psPDF, /* 3 */
+  &gl2psSVG, /* 4 */
+  &gl2psPGF  /* 5 */
+};
+
+static void gl2psComputeTightBoundingBox(void *data)
+{
+  GL2PSprimitive *prim;
+  int i;
+
+  prim = *(GL2PSprimitive**)data;
+
+  for(i = 0; i < prim->numverts; i++){
+    if(prim->verts[i].xyz[0] < gl2ps->viewport[0])
+      gl2ps->viewport[0] = (GLint)prim->verts[i].xyz[0];
+    if(prim->verts[i].xyz[0] > gl2ps->viewport[2])
+      gl2ps->viewport[2] = (GLint)(prim->verts[i].xyz[0] + 0.5F);
+    if(prim->verts[i].xyz[1] < gl2ps->viewport[1])
+      gl2ps->viewport[1] = (GLint)prim->verts[i].xyz[1];
+    if(prim->verts[i].xyz[1] > gl2ps->viewport[3])
+      gl2ps->viewport[3] = (GLint)(prim->verts[i].xyz[1] + 0.5F);
+  }
+}  
+
+static GLint gl2psPrintPrimitives(void)
+{
+  GL2PSbsptree *root;
+  GL2PSxyz eye = {0.0F, 0.0F, 100.0F * GL2PS_ZSCALE};
+  GLint used;
+
+  used = glRenderMode(GL_RENDER);
+
+  if(used < 0){
+    gl2psMsg(GL2PS_INFO, "OpenGL feedback buffer overflow");
+    return GL2PS_OVERFLOW;
+  }
+
+  if(used > 0)
+    gl2psParseFeedbackBuffer(used);
+
+  gl2psRescaleAndOffset();
+
+  if(gl2ps->header){
+    if(gl2psListNbr(gl2ps->primitives) && 
+       (gl2ps->options & GL2PS_TIGHT_BOUNDING_BOX)){
+      gl2ps->viewport[0] = gl2ps->viewport[1] = 100000;
+      gl2ps->viewport[2] = gl2ps->viewport[3] = -100000;
+      gl2psListAction(gl2ps->primitives, gl2psComputeTightBoundingBox);
+    }
+    (gl2psbackends[gl2ps->format]->printHeader)();
+    gl2ps->header = GL_FALSE;
+  }
+
+  if(!gl2psListNbr(gl2ps->primitives)){
+    /* empty feedback buffer and/or nothing else to print */
+    return GL2PS_NO_FEEDBACK;
+  }
+
+  switch(gl2ps->sort){
+  case GL2PS_NO_SORT :
+    gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
+    gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
+    /* reset the primitive list, waiting for the next viewport */
+    gl2psListReset(gl2ps->primitives);
+    break;
+  case GL2PS_SIMPLE_SORT :
+    gl2psListSort(gl2ps->primitives, gl2psCompareDepth);
+    if(gl2ps->options & GL2PS_OCCLUSION_CULL){
+      gl2psListActionInverse(gl2ps->primitives, gl2psAddInImageTree);
+      gl2psFreeBspImageTree(&gl2ps->imagetree);
+    }
+    gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
+    gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
+    /* reset the primitive list, waiting for the next viewport */
+    gl2psListReset(gl2ps->primitives);
+    break;
+  case GL2PS_BSP_SORT :
+    root = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
+    gl2psBuildBspTree(root, gl2ps->primitives);
+    if(GL_TRUE == gl2ps->boundary) gl2psBuildPolygonBoundary(root);
+    if(gl2ps->options & GL2PS_OCCLUSION_CULL){
+      gl2psTraverseBspTree(root, eye, -GL2PS_EPSILON, gl2psLess,
+                           gl2psAddInImageTree, 1);
+      gl2psFreeBspImageTree(&gl2ps->imagetree);
+    }
+    gl2psTraverseBspTree(root, eye, GL2PS_EPSILON, gl2psGreater, 
+                         gl2psbackends[gl2ps->format]->printPrimitive, 0);
+    gl2psFreeBspTree(&root);
+    /* reallocate the primitive list (it's been deleted by
+       gl2psBuildBspTree) in case there is another viewport */
+    gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
+    break;
+  }
+  gl2psbackends[gl2ps->format]->printFinalPrimitive();
+
+  return GL2PS_SUCCESS;
+}
+
+/********************************************************************* 
+ *
+ * Public routines
+ *
+ *********************************************************************/
+
+GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, 
+                                  GLint viewport[4], GLint format, GLint sort,
+                                  GLint options, GLint colormode,
+                                  GLint colorsize, GL2PSrgba *colormap,
+                                  GLint nr, GLint ng, GLint nb, GLint buffersize,
+                                  FILE *stream, const char *filename)
+{
+  GLint index;
+  int i;
+
+  if(gl2ps){
+    gl2psMsg(GL2PS_ERROR, "gl2psBeginPage called in wrong program state");
+    return GL2PS_ERROR;
+  }
+
+  gl2ps = (GL2PScontext*)gl2psMalloc(sizeof(GL2PScontext));
+
+  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends)/sizeof(gl2psbackends[0]))){
+    gl2ps->format = format;
+  }
+  else {
+    gl2psMsg(GL2PS_ERROR, "Unknown output format: %d", format);
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
+  switch(sort){
+  case GL2PS_NO_SORT :
+  case GL2PS_SIMPLE_SORT :
+  case GL2PS_BSP_SORT :
+    gl2ps->sort = sort;
+    break;
+  default :
+    gl2psMsg(GL2PS_ERROR, "Unknown sorting algorithm: %d", sort);
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
+  if(stream){
+    gl2ps->stream = stream;
+  }
+  else{
+    gl2psMsg(GL2PS_ERROR, "Bad file pointer");
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
+  gl2ps->header = GL_TRUE;
+  gl2ps->maxbestroot = 10;
+  gl2ps->options = options;
+  gl2ps->compress = NULL;
+  gl2ps->imagemap_head = NULL;
+  gl2ps->imagemap_tail = NULL;
+
+  if(gl2ps->options & GL2PS_USE_CURRENT_VIEWPORT){
+    glGetIntegerv(GL_VIEWPORT, gl2ps->viewport);
+  }
+  else{
+    for(i = 0; i < 4; i++){
+      gl2ps->viewport[i] = viewport[i];
+    }
+  }
+
+  if(!gl2ps->viewport[2] || !gl2ps->viewport[3]){
+    gl2psMsg(GL2PS_ERROR, "Incorrect viewport (x=%d, y=%d, width=%d, height=%d)",
+             gl2ps->viewport[0], gl2ps->viewport[1], 
+             gl2ps->viewport[2], gl2ps->viewport[3]);
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
+  gl2ps->threshold[0] = nr ? 1.0F/(GLfloat)nr : 0.064F;
+  gl2ps->threshold[1] = ng ? 1.0F/(GLfloat)ng : 0.034F;
+  gl2ps->threshold[2] = nb ? 1.0F/(GLfloat)nb : 0.100F;
+  gl2ps->colormode = colormode;
+  gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048;
+  for(i = 0; i < 3; i++){
+    gl2ps->lastvertex.xyz[i] = -1.0F;
+  }
+  for(i = 0; i < 4; i++){
+    gl2ps->lastvertex.rgba[i] = -1.0F;
+    gl2ps->lastrgba[i] = -1.0F;
+  }
+  gl2ps->lastlinewidth = -1.0F;
+  gl2ps->lastpattern = 0;
+  gl2ps->lastfactor = 0;
+  gl2ps->imagetree = NULL;
+  gl2ps->primitivetoadd = NULL;
+  gl2ps->zerosurfacearea = GL_FALSE;  
+  gl2ps->pdfprimlist = NULL;
+  gl2ps->pdfgrouplist = NULL;
+  gl2ps->xreflist = NULL;
+  
+  /* get default blending mode from current OpenGL state (enabled by
+     default for SVG) */
+  gl2ps->blending = (gl2ps->format == GL2PS_SVG) ? GL_TRUE : glIsEnabled(GL_BLEND);
+  glGetIntegerv(GL_BLEND_SRC, &gl2ps->blendfunc[0]);
+  glGetIntegerv(GL_BLEND_DST, &gl2ps->blendfunc[1]);
+
+  if(gl2ps->colormode == GL_RGBA){
+    gl2ps->colorsize = 0;
+    gl2ps->colormap = NULL;
+    glGetFloatv(GL_COLOR_CLEAR_VALUE, gl2ps->bgcolor);
+  }
+  else if(gl2ps->colormode == GL_COLOR_INDEX){
+    if(!colorsize || !colormap){
+      gl2psMsg(GL2PS_ERROR, "Missing colormap for GL_COLOR_INDEX rendering");
+      gl2psFree(gl2ps);
+      gl2ps = NULL;
+      return GL2PS_ERROR;
+    }
+    gl2ps->colorsize = colorsize;
+    gl2ps->colormap = (GL2PSrgba*)gl2psMalloc(gl2ps->colorsize * sizeof(GL2PSrgba));
+    memcpy(gl2ps->colormap, colormap, gl2ps->colorsize * sizeof(GL2PSrgba));
+    glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
+    gl2ps->bgcolor[0] = gl2ps->colormap[index][0];
+    gl2ps->bgcolor[1] = gl2ps->colormap[index][1];
+    gl2ps->bgcolor[2] = gl2ps->colormap[index][2];
+    gl2ps->bgcolor[3] = 1.0F;
+  }
+  else{
+    gl2psMsg(GL2PS_ERROR, "Unknown color mode in gl2psBeginPage");
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
+  if(!title){
+    gl2ps->title = (char*)gl2psMalloc(sizeof(char));
+    gl2ps->title[0] = '\0';
+  }
+  else{
+    gl2ps->title = (char*)gl2psMalloc((strlen(title)+1)*sizeof(char));
+    strcpy(gl2ps->title, title);
+  }
+    
+  if(!producer){
+    gl2ps->producer = (char*)gl2psMalloc(sizeof(char));
+    gl2ps->producer[0] = '\0';
+  }
+  else{
+    gl2ps->producer = (char*)gl2psMalloc((strlen(producer)+1)*sizeof(char));
+    strcpy(gl2ps->producer, producer);
+  }
+  
+  if(!filename){
+    gl2ps->filename = (char*)gl2psMalloc(sizeof(char));
+    gl2ps->filename[0] = '\0';
+  }
+  else{
+    gl2ps->filename = (char*)gl2psMalloc((strlen(filename)+1)*sizeof(char));
+    strcpy(gl2ps->filename, filename);
+  }
+
+  gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
+  gl2ps->auxprimitives = gl2psListCreate(100, 100, sizeof(GL2PSprimitive*));
+  gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat));
+  glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback);
+  glRenderMode(GL_FEEDBACK);  
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psEndPage(void)
+{
+  GLint res;
+
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  res = gl2psPrintPrimitives();
+
+  if(res != GL2PS_OVERFLOW)
+    (gl2psbackends[gl2ps->format]->printFooter)();
+  
+  fflush(gl2ps->stream);
+
+  gl2psListDelete(gl2ps->primitives);
+  gl2psListDelete(gl2ps->auxprimitives);
+  gl2psFreeImagemap(gl2ps->imagemap_head);
+  gl2psFree(gl2ps->colormap);
+  gl2psFree(gl2ps->title);
+  gl2psFree(gl2ps->producer);
+  gl2psFree(gl2ps->filename);
+  gl2psFree(gl2ps->feedback);
+  gl2psFree(gl2ps);
+  gl2ps = NULL;
+
+  return res;
+}
+
+GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4])
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  (gl2psbackends[gl2ps->format]->beginViewport)(viewport);
+  
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psEndViewport(void)
+{
+  GLint res;
+
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  res = (gl2psbackends[gl2ps->format]->endViewport)();
+
+  return res;
+}
+
+GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, 
+                                GLshort fontsize, GLint alignment, GLfloat angle)
+{
+  return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle);
+}
+
+GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize)
+{
+  return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, GL2PS_TEXT_BL, 0.0F);
+}
+
+GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str)
+{
+  return gl2psAddText(GL2PS_SPECIAL, str, "", 0, format, 0.0F);
+}
+
+GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
+                                   GLint xorig, GLint yorig,
+                                   GLenum format, GLenum type, 
+                                   const void *pixels)
+{
+  int size, i;
+  GLfloat pos[4], *piv;
+  GL2PSprimitive *prim;
+  GLboolean valid;
+
+  if(!gl2ps || !pixels) return GL2PS_UNINITIALIZED;
+
+  if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
+
+  if(gl2ps->options & GL2PS_NO_PIXMAP) return GL2PS_SUCCESS;
+
+  if((format != GL_RGB && format != GL_RGBA) || type != GL_FLOAT){
+    gl2psMsg(GL2PS_ERROR, "gl2psDrawPixels only implemented for "
+             "GL_RGB/GL_RGBA, GL_FLOAT pixels");
+    return GL2PS_ERROR;
+  }
+
+  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
+  if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
+
+  glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
+
+  prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+  prim->type = GL2PS_PIXMAP;
+  prim->boundary = 0;
+  prim->numverts = 1;
+  prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
+  prim->verts[0].xyz[0] = pos[0] + xorig;
+  prim->verts[0].xyz[1] = pos[1] + yorig;
+  prim->verts[0].xyz[2] = pos[2];
+  prim->culled = 0;
+  prim->offset = 0;
+  prim->pattern = 0;
+  prim->factor = 0;
+  prim->width = 1;
+  glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
+  prim->data.image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
+  prim->data.image->width = width;
+  prim->data.image->height = height;
+  prim->data.image->format = format;
+  prim->data.image->type = type;
+
+  switch(format){
+  case GL_RGBA:
+    if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){
+      /* special case: blending turned off */
+      prim->data.image->format = GL_RGB;
+      size = height * width * 3;
+      prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
+      piv = (GLfloat*)pixels;
+      for(i = 0; i < size; ++i, ++piv){
+        prim->data.image->pixels[i] = *piv;
+        if(!((i+1)%3))
+          ++piv;
+      }   
+    }
+    else{
+      size = height * width * 4;
+      prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
+      memcpy(prim->data.image->pixels, pixels, size * sizeof(GLfloat));
+    }
+    break;
+  case GL_RGB:
+  default:
+    size = height * width * 3;
+    prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
+    memcpy(prim->data.image->pixels, pixels, size * sizeof(GLfloat));
+    break;
+  }
+
+  gl2psListAdd(gl2ps->auxprimitives, &prim);
+  glPassThrough(GL2PS_DRAW_PIXELS_TOKEN);
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
+                                     const GLfloat position[3],
+                                     const unsigned char *imagemap){
+  int size, i;
+  int sizeoffloat = sizeof(GLfloat);
+  
+  if(!gl2ps || !imagemap) return GL2PS_UNINITIALIZED;
+
+  if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
+  
+  size = height + height * ((width-1)/8);
+  glPassThrough(GL2PS_IMAGEMAP_TOKEN);
+  glBegin(GL_POINTS);
+  glVertex3f(position[0], position[1],position[2]);
+  glEnd();
+  glPassThrough((GLfloat)width);
+  glPassThrough((GLfloat)height);
+  for(i = 0; i < size; i += sizeoffloat){
+    float *value = (float*)imagemap;
+    glPassThrough(*value);
+    imagemap += sizeoffloat;
+  }
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psEnable(GLint mode)
+{
+  GLint tmp;
+
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  switch(mode){
+  case GL2PS_POLYGON_OFFSET_FILL :
+    glPassThrough(GL2PS_BEGIN_OFFSET_TOKEN);
+    glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &gl2ps->offset[0]);
+    glGetFloatv(GL_POLYGON_OFFSET_UNITS, &gl2ps->offset[1]);
+    break;
+  case GL2PS_POLYGON_BOUNDARY :
+    glPassThrough(GL2PS_BEGIN_BOUNDARY_TOKEN);
+    break;
+  case GL2PS_LINE_STIPPLE :
+    glPassThrough(GL2PS_BEGIN_STIPPLE_TOKEN);
+    glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &tmp);
+    glPassThrough((GLfloat)tmp);
+    glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &tmp);
+    glPassThrough((GLfloat)tmp);
+    break;
+  case GL2PS_BLEND :
+    glPassThrough(GL2PS_BEGIN_BLEND_TOKEN);
+    break;
+  default :
+    gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psEnable: %d", mode);
+    return GL2PS_WARNING;
+  }
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psDisable(GLint mode)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  switch(mode){
+  case GL2PS_POLYGON_OFFSET_FILL :
+    glPassThrough(GL2PS_END_OFFSET_TOKEN);
+    break;
+  case GL2PS_POLYGON_BOUNDARY :
+    glPassThrough(GL2PS_END_BOUNDARY_TOKEN);
+    break;
+  case GL2PS_LINE_STIPPLE :
+    glPassThrough(GL2PS_END_STIPPLE_TOKEN);
+    break;
+  case GL2PS_BLEND :
+    glPassThrough(GL2PS_END_BLEND_TOKEN);
+    break;
+  default :
+    gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psDisable: %d", mode);
+    return GL2PS_WARNING;
+  }
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psPointSize(GLfloat value)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  glPassThrough(GL2PS_POINT_SIZE_TOKEN);
+  glPassThrough(value);
+  
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psLineWidth(GLfloat value)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  glPassThrough(GL2PS_LINE_WIDTH_TOKEN);
+  glPassThrough(value);
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  if(GL_FALSE == gl2psSupportedBlendMode(sfactor, dfactor))
+    return GL2PS_WARNING;
+
+  glPassThrough(GL2PS_SRC_BLEND_TOKEN);
+  glPassThrough((GLfloat)sfactor);
+  glPassThrough(GL2PS_DST_BLEND_TOKEN);
+  glPassThrough((GLfloat)dfactor);
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psSetOptions(GLint options)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  gl2ps->options = options;
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API const char *gl2psGetFileExtension(GLint format)
+{
+  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends)/sizeof(gl2psbackends[0])))
+    return gl2psbackends[format]->file_extension;
+  else
+    return "Unknown format";
+}
+
+GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format)
+{
+  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends)/sizeof(gl2psbackends[0])))
+    return gl2psbackends[format]->description;
+  else
+    return "Unknown format";
+}
diff --git a/3rdparty/gl2ps/gl2ps.h b/3rdparty/gl2ps/gl2ps.h
new file mode 100644
index 0000000..7818a88
--- /dev/null
+++ b/3rdparty/gl2ps/gl2ps.h
@@ -0,0 +1,199 @@
+/* $Id: gl2ps.h 173 2007-05-20 15:51:51Z krischnamurti $ */
+/*
+ * GL2PS, an OpenGL to PostScript Printing Library
+ * Copyright (C) 1999-2006 Christophe Geuzaine <geuz at geuz.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of either:
+ *
+ * a) the GNU Library General Public License as published by the Free
+ * Software Foundation, either version 2 of the License, or (at your
+ * option) any later version; or
+ *
+ * b) the GL2PS License as published by Christophe Geuzaine, either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See either
+ * the GNU Library General Public License or the GL2PS License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library in the file named "COPYING.LGPL";
+ * if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+ * Cambridge, MA 02139, USA.
+ *
+ * You should have received a copy of the GL2PS License with this
+ * library in the file named "COPYING.GL2PS"; if not, I will be glad
+ * to provide one.
+ *
+ * For the latest info about gl2ps, see http://www.geuz.org/gl2ps/.
+ * Please report all bugs and problems to <gl2ps at geuz.org>.
+ */
+
+#ifndef __GL2PS_H__
+#define __GL2PS_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Define GL2PSDLL at compile time to build a Windows DLL */
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
+#  if defined(_MSC_VER)
+#    pragma warning(disable:4115)
+#    if (_MSC_VER >= 1400) /* VS8 - not sure about VC7 */
+#      pragma warning(disable: 4996) /* MS security enhancements */
+#    endif
+#  endif
+#  include <windows.h>
+#  if defined(GL2PSDLL)
+#    if defined(GL2PSDLL_EXPORTS)
+#      define GL2PSDLL_API __declspec(dllexport)
+#    else
+#      define GL2PSDLL_API __declspec(dllimport)
+#    endif
+#  else
+#    define GL2PSDLL_API
+#  endif
+#else
+#  define GL2PSDLL_API
+#endif
+
+#if defined(__APPLE__) || defined(HAVE_OPENGL_GL_H)
+#  include <OpenGL/gl.h>
+#else
+#  include <GL/gl.h>
+#endif
+
+/* Support for compressed PostScript/PDF/SVG and for embedded PNG
+   images in SVG */
+
+#if defined(HAVE_ZLIB) || defined(HAVE_LIBZ)
+#  define GL2PS_HAVE_ZLIB
+#  if defined(HAVE_LIBPNG) || defined(HAVE_PNG)
+#    define GL2PS_HAVE_LIBPNG
+#  endif
+#endif
+
+/* Version number */
+
+#define GL2PS_MAJOR_VERSION 1
+#define GL2PS_MINOR_VERSION 3
+#define GL2PS_PATCH_VERSION 2
+#define GL2PS_EXTRA_VERSION ""
+
+#define GL2PS_VERSION (GL2PS_MAJOR_VERSION + \
+                       0.01 * GL2PS_MINOR_VERSION + \
+                       0.0001 * GL2PS_PATCH_VERSION)
+
+#define GL2PS_COPYRIGHT "(C) 1999-2006 Christophe Geuzaine (geuz at geuz.org)"
+
+/* Output file formats (the values and the ordering are important!) */
+
+#define GL2PS_PS  0
+#define GL2PS_EPS 1
+#define GL2PS_TEX 2
+#define GL2PS_PDF 3
+#define GL2PS_SVG 4
+#define GL2PS_PGF 5
+
+/* Sorting algorithms */
+
+#define GL2PS_NO_SORT     1
+#define GL2PS_SIMPLE_SORT 2
+#define GL2PS_BSP_SORT    3
+
+/* Message levels and error codes */
+
+#define GL2PS_SUCCESS       0
+#define GL2PS_INFO          1
+#define GL2PS_WARNING       2
+#define GL2PS_ERROR         3
+#define GL2PS_NO_FEEDBACK   4
+#define GL2PS_OVERFLOW      5
+#define GL2PS_UNINITIALIZED 6
+
+/* Options for gl2psBeginPage */
+
+#define GL2PS_NONE                 0
+#define GL2PS_DRAW_BACKGROUND      (1<<0)
+#define GL2PS_SIMPLE_LINE_OFFSET   (1<<1)
+#define GL2PS_SILENT               (1<<2)
+#define GL2PS_BEST_ROOT            (1<<3)
+#define GL2PS_OCCLUSION_CULL       (1<<4)
+#define GL2PS_NO_TEXT              (1<<5)
+#define GL2PS_LANDSCAPE            (1<<6)
+#define GL2PS_NO_PS3_SHADING       (1<<7)
+#define GL2PS_NO_PIXMAP            (1<<8)
+#define GL2PS_USE_CURRENT_VIEWPORT (1<<9)
+#define GL2PS_COMPRESS             (1<<10)
+#define GL2PS_NO_BLENDING          (1<<11)
+#define GL2PS_TIGHT_BOUNDING_BOX   (1<<12)
+
+/* Arguments for gl2psEnable/gl2psDisable */
+
+#define GL2PS_POLYGON_OFFSET_FILL 1
+#define GL2PS_POLYGON_BOUNDARY    2
+#define GL2PS_LINE_STIPPLE        3
+#define GL2PS_BLEND               4
+
+/* Text alignment (o=raster position; default mode is BL):
+   +---+ +---+ +---+ +---+ +---+ +---+ +-o-+ o---+ +---o 
+   | o | o   | |   o |   | |   | |   | |   | |   | |   | 
+   +---+ +---+ +---+ +-o-+ o---+ +---o +---+ +---+ +---+ 
+    C     CL    CR    B     BL    BR    T     TL    TR */
+
+#define GL2PS_TEXT_C  1
+#define GL2PS_TEXT_CL 2
+#define GL2PS_TEXT_CR 3
+#define GL2PS_TEXT_B  4
+#define GL2PS_TEXT_BL 5
+#define GL2PS_TEXT_BR 6
+#define GL2PS_TEXT_T  7
+#define GL2PS_TEXT_TL 8
+#define GL2PS_TEXT_TR 9
+
+typedef GLfloat GL2PSrgba[4];
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, 
+                                  GLint viewport[4], GLint format, GLint sort,
+                                  GLint options, GLint colormode,
+                                  GLint colorsize, GL2PSrgba *colormap, 
+                                  GLint nr, GLint ng, GLint nb, GLint buffersize,
+                                  FILE *stream, const char *filename);
+GL2PSDLL_API GLint gl2psEndPage(void);
+GL2PSDLL_API GLint gl2psSetOptions(GLint options);
+GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]);
+GL2PSDLL_API GLint gl2psEndViewport(void);
+GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, 
+                             GLshort fontsize);
+GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, 
+                                GLshort fontsize, GLint align, GLfloat angle);
+GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str);
+GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
+                                   GLint xorig, GLint yorig,
+                                   GLenum format, GLenum type, const void *pixels);
+GL2PSDLL_API GLint gl2psEnable(GLint mode);
+GL2PSDLL_API GLint gl2psDisable(GLint mode);
+GL2PSDLL_API GLint gl2psPointSize(GLfloat value);
+GL2PSDLL_API GLint gl2psLineWidth(GLfloat value);
+GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor);
+
+/* undocumented */
+GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
+                                     const GLfloat position[3],
+                                     const unsigned char *imagemap);
+GL2PSDLL_API const char *gl2psGetFileExtension(GLint format);
+GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __GL2PS_H__ */
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..6bd8ac1
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,23 @@
+/* 
+  
+  QwtPlot3D license -- January 5th, 2005
+
+  Copyright (C) 2003-2005 Michael Bieber
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the author be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+*/
diff --git a/debian/README.Debian b/debian/README.Debian
deleted file mode 100644
index 771fe48..0000000
--- a/debian/README.Debian
+++ /dev/null
@@ -1,27 +0,0 @@
-qwtplot3d for Debian
-------------------
-
-A postfix has been added to the library names according to the version of Qt:
-* libqwtplot3d-qt5.so* is QwtPlot3D 0.2.6 compiled against Qt5
-libqwtplot3d-qt4 and libqwtplot3d-qt5 were earlier coinstalled. Now qt4 has been
-removed but the namechange will stay.
-
-In that way, all these qwtplot3d libraries can coexist but you can only have a single 
-development package for each Qt version. 
-
-The include files are placed in the following directory:
-* /usr/include/qwtplot3d
-
-If you have a precompiled binary file, linked against libqwt then you may need to add 
-a symbolic link to the corresponding library.
-
-To compile the examples you need to copy them to a local directory and do the
-following steps:
-$cp -r /usr/share/doc/libqwtplot3d-doc/examples .
-$cd examples
-$qmake-qt5 examples.pro
-
-The sources for gl2ps are in the source tree but it is not compiled. Please refer to
-http://www.geuz.org/gl2ps for reference.
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Mon, 18 Dec 2006 22:21:51 +0100
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 79a9eef..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,147 +0,0 @@
-qwtplot3d (0.2.7+svn191+gcc7-2) unstable; urgency=medium
-
-  * Add symbols files
-  * Remove support for Qt4 (Closes: #875167)
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Mon, 25 Dec 2017 09:19:11 +0100
-
-qwtplot3d (0.2.7+svn191+gcc7-1.0) unstable; urgency=medium
-
-  * Non-maintainer upload.
-  * No change in the source, but ...
-  * Changed the version string to prevent collisions with variants
-    of qwtplot3d-0.2.7+svn191, especially in backports. Reinitialized
-    .symbols files. Closes: #853635
-  * Updated debhelper version, Standards-Version.
-
- -- Georges Khaznadar <georgesk at debian.org>  Tue, 19 Sep 2017 17:21:48 +0200
-
-qwtplot3d (0.2.7+svn191-10.1) unstable; urgency=low
-
-  * Non-maintainer upload.
-  * Apply patch from Graham Inggs <ginggs at debian.org> to update symbols
-    for gcc 6 (Closes: #811986)
-
- -- Arto Jantunen <viiru at debian.org>  Fri, 23 Dec 2016 14:26:35 +0200
-
-qwtplot3d (0.2.7+svn191-10) unstable; urgency=medium
-
-  * Disable qt5 library on architectures armel and armhf. 
-    It doesn't compile on these architectures because of opengl problems.
-  * Bump standards version to 3.9.7,no changes needed.
-  * Change VCS field to https
-  * Change hardening to +all
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Thu, 24 Mar 2016 14:01:55 +0100
-
-qwtplot3d (0.2.7+svn191-9) unstable; urgency=medium
-
-  * Add Qt5 library
-  * Add support for Qt5 to examples patch
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Sat, 05 Sep 2015 13:15:52 +0100
-
-qwtplot3d (0.2.7+svn191-8) unstable; urgency=medium
-
-  * Make svn references canonical
-  * Bump standards version to 3.9.6
-  * Change debhelper dependency to 9
-  * Add hardening flags
-  * Add symbols control file
-  * Update build system
-  * Add pkg-kde-tools to build system
-  * Change qt4 package name to libqwtplot3d-qt4-0v5 (Closes:  #791264)
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Wed, 02 Sep 2015 07:04:48 +0100
-
-qwtplot3d (0.2.7+svn191-7) unstable; urgency=low
-
-  * Remove -lGLU from examples/common.pro, Reverting
-    last change.
-  * Add -lGLU to qwtplot3d.pro and add dependency on
-    libglu1-mesa-dev | libglu-dev (Closes: #672873)
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Wed, 16 May 2012 05:08:10 +0200
-
-qwtplot3d (0.2.7+svn191-6) unstable; urgency=low
-
-  * Fix ftbs (Closes: #672023, #665750)
-  * Bump standards version to 3.9.3
-  * Set debhelper dependency to >=8
-  * Add build-arch and build-indep to rules
-  * Change copyright to copyright-format 1.0
-  * Add -lGLU to examples library dependencies
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Sat, 12 May 2012 08:11:28 +0200
-
-qwtplot3d (0.2.7+svn191-5) unstable; urgency=low
-
-  * Remove qt3 support (Closes: #604380)
-  * Bump standards version to 3.9.1
-  * Remove README.source
-  * Switch to dpkg-source 3.0 (quilt) format
-  * Rewrite patches in quilt format
-  * Add dependency on zlib1g-dev
-  * Upgrade copyright file to current format
-  * Add watch file
-  * Add misc Depends
-  * Add doc-base file
-  * Remove qt3 related things from patches
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Thu, 03 Mar 2011 09:47:22 +0100
-
-qwtplot3d (0.2.7+svn191-4) unstable; urgency=low
-
-  * Add conflicts and replaces on the old packages libqwtplot3d-qt{3,4}
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Sat, 21 Nov 2009 17:44:53 +0100
-
-qwtplot3d (0.2.7+svn191-3) unstable; urgency=low
-
-  [ Gudjon I. Gudjonsson ]
-  * Create patch 03_fix_ftbs to fix FTBS with gcc-4.4 (Closes: 504912)
-  * Bump standards version to 3.8.3, no changes needed
-  * Add README.source
-  * Add Vcs fields for debian-science
-
-  [ Andreas Tille ]
-  * Group maintenance in Debian Science team with permission of maintainer
-  * Debhelper 7
-  * Rename package libqwtplot3d-qt[34] to libqwtplot3d-qt[34]-0 to match
-    soname
-  * Remove unneeded debian/*.dirs files because theses dirs will be
-    created by dh_install automatically anyway
-
- -- Andreas Tille <tille at debian.org>  Fri, 20 Nov 2009 11:44:36 +0100
-
-qwtplot3d (0.2.7+svn191-2) unstable; urgency=low
-
-  * Added dependency on libqt4-opengl-dev. (Closes: #482252)
-  * Bump standards version to 3.7.3. No changes needed.
-  * Add a homepage field to control file.
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Tue, 27 May 2008 10:24:26 +0200
-
-qwtplot3d (0.2.7+svn191-1) unstable; urgency=low
-
-  * An SVN version. Includes patches necessary for PyQwt3d.
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Thu, 23 Aug 2007 12:36:37 +0200
-
-qwtplot3d (0.2.7-1) unstable; urgency=low
-
-  * New upstream release.
-  * Changed the rules file. The original tgz file can be used directly now.
-  * Repatched the new release.
-  * Changed line endings with dos2unix in original tarball.
-  * Examples are not gzipped anymore.
-  * Changed maintainers email.
-
- -- Gudjon I. Gudjonsson <gudjon at gudjon.org>  Wed, 27 Jun 2007 10:19:39 +0200
-
-qwtplot3d (0.2.6+svn170-1) unstable; urgency=low
-
-  * Initial release (Closes: #408538)
-
- -- Gudjon I. Gudjonsson <gudjon at mc2.chalmers.se>  Fri, 26 Jan 2007 13:37:18 +0100
-
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index ec63514..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-9
diff --git a/debian/control b/debian/control
deleted file mode 100644
index 04387ee..0000000
--- a/debian/control
+++ /dev/null
@@ -1,52 +0,0 @@
-Source: qwtplot3d
-Priority: optional
-Maintainer: Debian Science Team <debian-science-maintainers at lists.alioth.debian.org>
-Uploaders: Gudjon I. Gudjonsson <gudjon at gudjon.org>,
-           Andreas Tille <tille at debian.org>
-Build-Depends: debhelper (>= 10),
-               doxygen,
-               libglu1-mesa-dev | libglu-dev,
-               libjs-jquery,
-               pkg-kde-tools,
-               zlib1g-dev,
-               libqt5opengl5-dev
-Standards-Version: 4.1.2
-Section: libs
-Homepage: http://qwtplot3d.sourceforge.net
-Vcs-Svn: svn://anonscm.debian.org/debian-science/packages/qwtplot3d/trunk/
-Vcs-Browser: https://anonscm.debian.org/viewvc/debian-science/packages/qwtplot3d/trunk
-
-Package: libqwtplot3d-qt5-dev
-Section: libdevel
-Architecture: any-amd64 any-i386 arm64 mips mipsel powerpc ppc64el s390x alpha hppa m68k mips64el ppc64 sh4 sparc64 x32
-Depends: libqwtplot3d-qt5-0 (= ${binary:Version}), ${misc:Depends}
-Description: 3D plotting library based on Qt5/OpenGL (development)
- QwtPlot3D is a feature rich Qt/OpenGL-based C++ programming
- library, providing essentially a bunch of 3D-widgets for
- programmers.
- .
- This package contains the QwtPlot3D development files for Qt5.
-
-Package: libqwtplot3d-qt5-0
-Architecture: any-amd64 any-i386 arm64 mips mipsel powerpc ppc64el s390x alpha hppa m68k mips64el ppc64 sh4 sparc64 x32
-Depends: ${misc:Depends}, ${shlibs:Depends}
-Description: 3D plotting library based on Qt5/OpenGL (runtime)
- QwtPlot3D is a feature rich Qt/OpenGL-based C++ programming
- library, providing essentially a bunch of 3D-widgets for
- programmers.
- .
- This package contains the files necessary for running applications that
- use the QwtPlot3D library and Qt5.
-
-Package: libqwtplot3d-doc
-Section: doc
-Architecture: all
-Depends: ${misc:Depends}
-Recommends: w3m | www-browser
-Description: 3D plotting library based on Qt/OpenGL (documentation)
- QwtPlot3D is a feature rich Qt/OpenGL-based C++ programming
- library, providing essentially a bunch of 3D-widgets for
- programmers.
- .
- This package contains the html documentation and example
- programs.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index c153cdf..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,72 +0,0 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Source: http://qwtplot3d.sourceforge.net/
-
-Files: *
-Copyright: Michael Bieber <krischnamurti at users.sourceforge.net>
-License: QwtPlot3D
-
-Files: 3rdparty/gl2ps/*
-Copyright: 1999-2006 Christophe Geuzaine <geuz at geuz.org>
-License: GPL-2+ or GL2PS-2
-
-Files: debian/*
-Copyright: 2007-2012 Gudjon I. Gudjonsson <gudjon at gudjon.org>
-License: GPL-2
-
-License: GPL-2
- On Debian systems, the full text of the GNU General Public
- License version 2 can be found in the file
- `/usr/share/common-licenses/GPL-2'.
-
-License: GPL-2+
- This program is free software; you can redistribute it
- and/or modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later
- version.
- .
- On Debian systems, the full text of the GNU General Public
- License version 2 can be found in the file
- `/usr/share/common-licenses/GPL-2'.
-
-License: GL2PS-2
- Version 2, November 2003
- .
- Copyright (C) 2003, Christophe Geuzaine
- .
- Permission to use, copy, and distribute this software and its
- documentation for any purpose with or without fee is hereby granted,
- provided that the copyright notice appear in all copies and that both
- that copyright notice and this permission notice appear in supporting
- documentation.
- .
- Permission to modify and distribute modified versions of this software
- is granted, provided that:
- .
- 1) the modifications are licensed under the same terms as this
- software;
- .
- 2) you make available the source code of any modifications that you
- distribute, either on the same media as you distribute any executable
- or other form of this software, or via a mechanism generally accepted
- in the software development community for the electronic transfer of
- data.
- .
- This software is provided "as is" without express or implied warranty.
-
-License: QwtPlot3D
- This software is provided 'as-is', without any express or implied
- warranty.  In no event will the author be held liable for any damages
- arising from the use of this software.
- .
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- .
- 1. The origin of this software must not be misrepresented; you must not
-    claim that you wrote the original software. If you use this software
-    in a product, an acknowledgment in the product documentation would be
-    appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
-    misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
diff --git a/debian/libqwtplot3d-doc.doc-base b/debian/libqwtplot3d-doc.doc-base
deleted file mode 100644
index 056b995..0000000
--- a/debian/libqwtplot3d-doc.doc-base
+++ /dev/null
@@ -1,9 +0,0 @@
-Document: qwtplot3d
-Title: Debian qwtplot3d Manual
-Author: Michael Bieber
-Abstract: QwtPlot3D, three dimensional plotting library for Qt.
-Section: Programming
-
-Format: HTML
-Index: /usr/share/doc/libqwtplot3d-doc/html/index.html
-Files: /usr/share/doc/libqwtplot3d-doc/html/*.html
diff --git a/debian/libqwtplot3d-doc.examples b/debian/libqwtplot3d-doc.examples
deleted file mode 100644
index e39721e..0000000
--- a/debian/libqwtplot3d-doc.examples
+++ /dev/null
@@ -1 +0,0 @@
-examples/*
diff --git a/debian/libqwtplot3d-doc.install b/debian/libqwtplot3d-doc.install
deleted file mode 100644
index c5f944e..0000000
--- a/debian/libqwtplot3d-doc.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/share/doc/libqwtplot3d-doc/html
diff --git a/debian/libqwtplot3d-qt5-0.install b/debian/libqwtplot3d-qt5-0.install
deleted file mode 100644
index ef17f57..0000000
--- a/debian/libqwtplot3d-qt5-0.install
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/lib*qt5.so.*
diff --git a/debian/libqwtplot3d-qt5-0.symbols b/debian/libqwtplot3d-qt5-0.symbols
deleted file mode 100644
index 57087bd..0000000
--- a/debian/libqwtplot3d-qt5-0.symbols
+++ /dev/null
@@ -1,604 +0,0 @@
-# SymbolsHelper-Confirmed: 0.2.7 amd64
-libqwtplot3d-qt5.so.0 libqwtplot3d-qt5-0 #MINVER#
- _ZN10QByteArrayD1Ev at Base 0.2.7
- _ZN10QByteArrayD2Ev at Base 0.2.7
- (optional=templinst)_ZN5QListI10QByteArrayE13detach_helperEi at Base 0.2.7
- (optional=templinst)_ZN5QListI10QByteArrayED1Ev at Base 0.2.7
- (optional=templinst)_ZN5QListI10QByteArrayED2Ev at Base 0.2.7
- (optional=templinst)_ZN5QListI7QStringE18detach_helper_growEii at Base 0.2.7
- (optional=templinst)_ZN5QListI7QStringE6appendERKS0_ at Base 0.2.7
- (optional=templinst)_ZN5QListI7QStringED1Ev at Base 0.2.7
- (optional=templinst)_ZN5QListI7QStringED2Ev at Base 0.2.7
- _ZN5Qwt3D10Enrichment6assignERKNS_6Plot3DE at Base 0.2.7
- _ZN5Qwt3D10Enrichment7drawEndEv at Base 0.2.7
- _ZN5Qwt3D10Enrichment9drawBeginEv at Base 0.2.7
- _ZN5Qwt3D11ColorLegend12setAutoScaleEb at Base 0.2.7
- _ZN5Qwt3D11ColorLegend12setTitleFontERK7QStringiib at Base 0.2.7
- _ZN5Qwt3D11ColorLegend14setOrientationENS0_11ORIENTATIONENS0_13SCALEPOSITIONE at Base 0.2.7
- _ZN5Qwt3D11ColorLegend14setRelPositionENS_5TupleES1_ at Base 0.2.7
- _ZN5Qwt3D11ColorLegend14setTitleStringERK7QString at Base 0.2.7
- _ZN5Qwt3D11ColorLegend19setGeometryInternalEv at Base 0.2.7
- _ZN5Qwt3D11ColorLegend4drawEv at Base 0.2.7
- _ZN5Qwt3D11ColorLegend8setScaleENS_9SCALETYPEE at Base 0.2.7
- _ZN5Qwt3D11ColorLegend8setScaleEPNS_5ScaleE at Base 0.2.7
- _ZN5Qwt3D11ColorLegend9setLimitsEdd at Base 0.2.7
- _ZN5Qwt3D11ColorLegend9setMajorsEi at Base 0.2.7
- _ZN5Qwt3D11ColorLegend9setMinorsEi at Base 0.2.7
- _ZN5Qwt3D11ColorLegendC1Ev at Base 0.2.7
- _ZN5Qwt3D11ColorLegendC2Ev at Base 0.2.7
- _ZN5Qwt3D11ColorLegendD0Ev at Base 0.2.7
- _ZN5Qwt3D11ColorLegendD1Ev at Base 0.2.7
- _ZN5Qwt3D11ColorLegendD2Ev at Base 0.2.7
- _ZN5Qwt3D11GridMapping13restrictRangeERKNS_14ParallelEpipedE at Base 0.2.7
- _ZN5Qwt3D11GridMapping7setMeshEjj at Base 0.2.7
- _ZN5Qwt3D11GridMapping9setDomainEdddd at Base 0.2.7
- _ZN5Qwt3D11GridMappingC1Ev at Base 0.2.7
- _ZN5Qwt3D11GridMappingC2Ev at Base 0.2.7
- _ZN5Qwt3D11GridMappingD0Ev at Base 0.2.7
- _ZN5Qwt3D11GridMappingD1Ev at Base 0.2.7
- _ZN5Qwt3D11GridMappingD2Ev at Base 0.2.7
- _ZN5Qwt3D11LinearScale9autoscaleERdS1_ddi at Base 0.2.7
- _ZN5Qwt3D11LinearScale9calculateEv at Base 0.2.7
- _ZN5Qwt3D11LinearScaleD0Ev at Base 0.2.7
- _ZN5Qwt3D11LinearScaleD1Ev at Base 0.2.7
- _ZN5Qwt3D11LinearScaleD2Ev at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot10createDataEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot11Data2FloorCEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot11Data2FloorGEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot11calcNormalsERNS_8GridDataE at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot11createDataCEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot11createDataGEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot11qt_metacallEN11QMetaObject4CallEiPPv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot11qt_metacastEPKc at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot11sewPeriodicERNS_8GridDataE at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot11showNormalsEb at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot12createPointsEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot12loadFromDataEPPNS_6TripleEjjbb at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot12loadFromDataEPPdjjdddd at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot12loadFromDataERKSt6vectorINS_6TripleESaIS2_EERKS1_IS1_IjSaIjEESaIS8_EE at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot13calculateHullEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot13setResolutionEi at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot13updateNormalsEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot14createNormalsCEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot14createNormalsGEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot15Isolines2FloorCEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot15Isolines2FloorGEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot15createFloorDataEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot15setNormalLengthEd at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot16createEnrichmentERNS_10EnrichmentE at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot16createFloorDataCEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot16createFloorDataGEv at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot16setNormalQualityEi at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot16staticMetaObjectE at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot17resolutionChangedEi at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot19setColorFromVertexCEib at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot19setColorFromVertexGEiib at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot6readInERNS_8GridDataEPPNS_6TripleEjj at Base 0.2.7
- _ZN5Qwt3D11SurfacePlot6readInERNS_8GridDataEPPdjjdddd at Base 0.2.7
- _ZN5Qwt3D11SurfacePlotC1EP7QWidgetPK9QGLWidget at Base 0.2.7
- _ZN5Qwt3D11SurfacePlotC2EP7QWidgetPK9QGLWidget at Base 0.2.7
- _ZN5Qwt3D11SurfacePlotD0Ev at Base 0.2.7
- _ZN5Qwt3D11SurfacePlotD1Ev at Base 0.2.7
- _ZN5Qwt3D11SurfacePlotD2Ev at Base 0.2.7
- _ZN5Qwt3D12NativeReader11collectInfoERP8_IO_FILERK7QStringRjS7_RdS8_S8_S8_ at Base 0.2.7
- _ZN5Qwt3D12NativeReader11magicstringE at Base 0.2.7
- _ZN5Qwt3D12NativeReaderC1Ev at Base 0.2.7
- _ZN5Qwt3D12NativeReaderC2Ev at Base 0.2.7
- _ZN5Qwt3D12NativeReaderD0Ev at Base 0.2.7
- _ZN5Qwt3D12NativeReaderD1Ev at Base 0.2.7
- _ZN5Qwt3D12NativeReaderD2Ev at Base 0.2.7
- _ZN5Qwt3D12NativeReaderclEPNS_6Plot3DERK7QString at Base 0.2.7
- _ZN5Qwt3D12PixmapWriter10setQualityEi at Base 0.2.7
- _ZN5Qwt3D12PixmapWriterD0Ev at Base 0.2.7
- _ZN5Qwt3D12PixmapWriterD1Ev at Base 0.2.7
- _ZN5Qwt3D12PixmapWriterD2Ev at Base 0.2.7
- _ZN5Qwt3D12PixmapWriterclEPNS_6Plot3DERK7QString at Base 0.2.7
- _ZN5Qwt3D12VectorWriter11setTextModeENS0_8TEXTMODEE7QString at Base 0.2.7
- _ZN5Qwt3D12VectorWriter13setCompressedEb at Base 0.2.7
- _ZN5Qwt3D12VectorWriter9setFormatERK7QString at Base 0.2.7
- _ZN5Qwt3D12VectorWriterC1Ev at Base 0.2.7
- _ZN5Qwt3D12VectorWriterC2Ev at Base 0.2.7
- _ZN5Qwt3D12VectorWriterD0Ev at Base 0.2.7
- _ZN5Qwt3D12VectorWriterD1Ev at Base 0.2.7
- _ZN5Qwt3D12VectorWriterD2Ev at Base 0.2.7
- _ZN5Qwt3D12VectorWriterclEPNS_6Plot3DERK7QString at Base 0.2.7
- _ZN5Qwt3D12convexhull2dERSt6vectorIjSaIjEERKS0_INS_5TupleESaIS4_EE at Base 0.2.7
- _ZN5Qwt3D13StandardColor12createVectorERSt6vectorINS_4RGBAESaIS2_EE at Base 0.2.7
- _ZN5Qwt3D13StandardColor14setColorVectorERKSt6vectorINS_4RGBAESaIS2_EE at Base 0.2.7
- _ZN5Qwt3D13StandardColor5resetEj at Base 0.2.7
- _ZN5Qwt3D13StandardColor8setAlphaEd at Base 0.2.7
- _ZN5Qwt3D13StandardColorC1EPNS_6Plot3DEj at Base 0.2.7
- _ZN5Qwt3D13StandardColorC2EPNS_6Plot3DEj at Base 0.2.7
- _ZN5Qwt3D13StandardColorD0Ev at Base 0.2.7
- _ZN5Qwt3D13StandardColorD1Ev at Base 0.2.7
- _ZN5Qwt3D13StandardColorD2Ev at Base 0.2.7
- _ZN5Qwt3D14GLStateBewarerD1Ev at Base 0.2.7
- _ZN5Qwt3D14GLStateBewarerD2Ev at Base 0.2.7
- _ZN5Qwt3D14drawDeviceTextEPKcS1_iNS_6TripleENS_4RGBAENS_6ANCHOREd at Base 0.2.7
- _ZN5Qwt3D15tesselationSizeERKSt6vectorIS0_IjSaIjEESaIS2_EE at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem10chooseAxesEv at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem11setPositionENS_6TripleES1_ at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem12adjustLabelsEi at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem12setAutoScaleEb at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem12setAxesColorENS_4RGBAE at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem12setGridLinesEbbi at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem12setLabelFontERK5QFont at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem12setLabelFontERK7QStringiib at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem12setLineWidthEddd at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem12setTicLengthEdd at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem13adjustNumbersEi at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem13setLabelColorENS_4RGBAE at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem13setNumberFontERK5QFont at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem13setNumberFontERK7QStringiib at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem14setNumberColorENS_4RGBAE at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem16setStandardScaleEv at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem18drawMajorGridLinesERNS_4AxisES2_ at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem18drawMajorGridLinesEv at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem18drawMinorGridLinesERNS_4AxisES2_ at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem18drawMinorGridLinesEv at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem19recalculateAxesTicsEv at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem23autoDecorateExposedAxisERNS_4AxisEb at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem4drawEv at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem4initENS_6TripleES1_ at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem7destroyEv at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystem8setStyleENS_10COORDSTYLEENS_4AXISES2_S2_ at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystemC1ENS_6TripleES1_NS_10COORDSTYLEE at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystemC2ENS_6TripleES1_NS_10COORDSTYLEE at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystemD0Ev at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystemD1Ev at Base 0.2.7
- _ZN5Qwt3D16CoordinateSystemD2Ev at Base 0.2.7
- _ZN5Qwt3D16LinearAutoScaler11anchorvalueEddi at Base 0.2.7
- _ZN5Qwt3D16LinearAutoScaler4initEddi at Base 0.2.7
- _ZN5Qwt3D16LinearAutoScaler7executeERdS1_ddi at Base 0.2.7
- _ZN5Qwt3D16LinearAutoScaler8segmentsERiS1_ddddi at Base 0.2.7
- _ZN5Qwt3D16LinearAutoScalerC1ERSt6vectorIdSaIdEE at Base 0.2.7
- _ZN5Qwt3D16LinearAutoScalerC1Ev at Base 0.2.7
- _ZN5Qwt3D16LinearAutoScalerC2ERSt6vectorIdSaIdEE at Base 0.2.7
- _ZN5Qwt3D16LinearAutoScalerC2Ev at Base 0.2.7
- _ZN5Qwt3D16LinearAutoScalerD0Ev at Base 0.2.7
- _ZN5Qwt3D16LinearAutoScalerD1Ev at Base 0.2.7
- _ZN5Qwt3D16LinearAutoScalerD2Ev at Base 0.2.7
- _ZN5Qwt3D16drawDevicePixelsEiijjPKv at Base 0.2.7
- _ZN5Qwt3D17ParametricSurface11setPeriodicEbb at Base 0.2.7
- _ZN5Qwt3D17ParametricSurface6assignEPNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D17ParametricSurface6assignERNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D17ParametricSurface6createERNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D17ParametricSurface6createEv at Base 0.2.7
- _ZN5Qwt3D17ParametricSurfaceC1EPNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D17ParametricSurfaceC1ERNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D17ParametricSurfaceC1Ev at Base 0.2.7
- _ZN5Qwt3D17ParametricSurfaceC2EPNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D17ParametricSurfaceC2ERNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D17ParametricSurfaceC2Ev at Base 0.2.7
- _ZN5Qwt3D18setDeviceLineWidthEf at Base 0.2.7
- _ZN5Qwt3D18setDevicePointSizeEf at Base 0.2.7
- _ZN5Qwt3D22setDevicePolygonOffsetEff at Base 0.2.7
- _ZN5Qwt3D2IO10add_uniqueERSt6vectorINS0_5EntryESaIS2_EERKS2_ at Base 0.2.7
- _ZN5Qwt3D2IO12inputHandlerERK7QString at Base 0.2.7
- _ZN5Qwt3D2IO12setupHandlerEv at Base 0.2.7
- _ZN5Qwt3D2IO13FormatCompareC1ERKNS0_5EntryE at Base 0.2.7
- _ZN5Qwt3D2IO13FormatCompareC2ERKNS0_5EntryE at Base 0.2.7
- _ZN5Qwt3D2IO13FormatCompareclERKNS0_5EntryE at Base 0.2.7
- _ZN5Qwt3D2IO13outputHandlerERK7QString at Base 0.2.7
- _ZN5Qwt3D2IO14FormatCompare2C1E7QString at Base 0.2.7
- _ZN5Qwt3D2IO14FormatCompare2C2E7QString at Base 0.2.7
- _ZN5Qwt3D2IO14FormatCompare2clERKNS0_5EntryE at Base 0.2.7
- _ZN5Qwt3D2IO15inputFormatListEv at Base 0.2.7
- _ZN5Qwt3D2IO16outputFormatListEv at Base 0.2.7
- _ZN5Qwt3D2IO18defineInputHandlerERK7QStringPFbPNS_6Plot3DES3_E at Base 0.2.7
- _ZN5Qwt3D2IO18defineInputHandlerERK7QStringRKNS0_7FunctorE at Base 0.2.7
- _ZN5Qwt3D2IO19defineOutputHandlerERK7QStringPFbPNS_6Plot3DES3_E at Base 0.2.7
- _ZN5Qwt3D2IO19defineOutputHandlerERK7QStringRKNS0_7FunctorE at Base 0.2.7
- _ZN5Qwt3D2IO4findERSt6vectorINS0_5EntryESaIS2_EERK7QString at Base 0.2.7
- _ZN5Qwt3D2IO4loadEPNS_6Plot3DERK7QStringS5_ at Base 0.2.7
- _ZN5Qwt3D2IO4saveEPNS_6Plot3DERK7QStringS5_ at Base 0.2.7
- _ZN5Qwt3D2IO5EntryC1ERK7QStringPFbPNS_6Plot3DES4_E at Base 0.2.7
- _ZN5Qwt3D2IO5EntryC1ERK7QStringRKNS0_7FunctorE at Base 0.2.7
- _ZN5Qwt3D2IO5EntryC1ERKS1_ at Base 0.2.7
- _ZN5Qwt3D2IO5EntryC1Ev at Base 0.2.7
- _ZN5Qwt3D2IO5EntryC2ERK7QStringPFbPNS_6Plot3DES4_E at Base 0.2.7
- _ZN5Qwt3D2IO5EntryC2ERK7QStringRKNS0_7FunctorE at Base 0.2.7
- _ZN5Qwt3D2IO5EntryC2ERKS1_ at Base 0.2.7
- _ZN5Qwt3D2IO5EntryC2Ev at Base 0.2.7
- _ZN5Qwt3D2IO5EntryD1Ev at Base 0.2.7
- _ZN5Qwt3D2IO5EntryD2Ev at Base 0.2.7
- _ZN5Qwt3D2IO5EntryaSERKS1_ at Base 0.2.7
- _ZN5Qwt3D2IO5rlistEv at Base 0.2.7
- _ZN5Qwt3D2IO5wlistEv at Base 0.2.7
- _ZN5Qwt3D2IO7WrapperD0Ev at Base 0.2.7
- _ZN5Qwt3D2IO7WrapperD1Ev at Base 0.2.7
- _ZN5Qwt3D2IO7WrapperD2Ev at Base 0.2.7
- _ZN5Qwt3D2IO7WrapperclEPNS_6Plot3DERK7QString at Base 0.2.7
- _ZN5Qwt3D3Dot4drawERKNS_6TripleE at Base 0.2.7
- _ZN5Qwt3D3Dot7drawEndEv at Base 0.2.7
- _ZN5Qwt3D3Dot9configureEdb at Base 0.2.7
- _ZN5Qwt3D3Dot9drawBeginEv at Base 0.2.7
- _ZN5Qwt3D3DotC1Edb at Base 0.2.7
- _ZN5Qwt3D3DotC1Ev at Base 0.2.7
- _ZN5Qwt3D3DotC2Edb at Base 0.2.7
- _ZN5Qwt3D3DotC2Ev at Base 0.2.7
- _ZN5Qwt3D3DotD0Ev at Base 0.2.7
- _ZN5Qwt3D3DotD1Ev at Base 0.2.7
- _ZN5Qwt3D3DotD2Ev at Base 0.2.7
- _ZN5Qwt3D4Axis11setPositionERKNS_6TripleES3_ at Base 0.2.7
- _ZN5Qwt3D4Axis12drawTicLabelENS_6TripleEi at Base 0.2.7
- _ZN5Qwt3D4Axis12setLabelFontERK5QFont at Base 0.2.7
- _ZN5Qwt3D4Axis12setLabelFontERK7QStringiib at Base 0.2.7
- _ZN5Qwt3D4Axis12setLineWidthEddd at Base 0.2.7
- _ZN5Qwt3D4Axis12setTicLengthEdd at Base 0.2.7
- _ZN5Qwt3D4Axis13setLabelColorENS_4RGBAE at Base 0.2.7
- _ZN5Qwt3D4Axis13setNumberFontERK5QFont at Base 0.2.7
- _ZN5Qwt3D4Axis13setNumberFontERK7QStringiib at Base 0.2.7
- _ZN5Qwt3D4Axis14setLabelStringERK7QString at Base 0.2.7
- _ZN5Qwt3D4Axis14setNumberColorENS_4RGBAE at Base 0.2.7
- _ZN5Qwt3D4Axis15recalculateTicsEv at Base 0.2.7
- _ZN5Qwt3D4Axis16setLabelPositionERKNS_6TripleENS_6ANCHORE at Base 0.2.7
- _ZN5Qwt3D4Axis17setTicOrientationERKNS_6TripleE at Base 0.2.7
- _ZN5Qwt3D4Axis17setTicOrientationEddd at Base 0.2.7
- _ZN5Qwt3D4Axis18prepTicCalculationERNS_6TripleE at Base 0.2.7
- _ZN5Qwt3D4Axis19biggestNumberStringEv at Base 0.2.7
- _ZN5Qwt3D4Axis4drawEv at Base 0.2.7
- _ZN5Qwt3D4Axis4initEv at Base 0.2.7
- _ZN5Qwt3D4Axis7drawTicENS_6TripleEd at Base 0.2.7
- _ZN5Qwt3D4Axis8drawBaseEv at Base 0.2.7
- _ZN5Qwt3D4Axis8drawTicsEv at Base 0.2.7
- _ZN5Qwt3D4Axis8setScaleENS_9SCALETYPEE at Base 0.2.7
- _ZN5Qwt3D4Axis8setScaleEPNS_5ScaleE at Base 0.2.7
- _ZN5Qwt3D4Axis9drawLabelEv at Base 0.2.7
- _ZN5Qwt3D4Axis9setMajorsEi at Base 0.2.7
- _ZN5Qwt3D4Axis9setMinorsEi at Base 0.2.7
- _ZN5Qwt3D4AxisC1ENS_6TripleES1_ at Base 0.2.7
- _ZN5Qwt3D4AxisC1Ev at Base 0.2.7
- _ZN5Qwt3D4AxisC2ENS_6TripleES1_ at Base 0.2.7
- _ZN5Qwt3D4AxisC2Ev at Base 0.2.7
- _ZN5Qwt3D4AxisD0Ev at Base 0.2.7
- _ZN5Qwt3D4AxisD1Ev at Base 0.2.7
- _ZN5Qwt3D4AxisD2Ev at Base 0.2.7
- _ZN5Qwt3D4Cone4drawERKNS_6TripleE at Base 0.2.7
- _ZN5Qwt3D4Cone9configureEdj at Base 0.2.7
- _ZN5Qwt3D4ConeC1Edj at Base 0.2.7
- _ZN5Qwt3D4ConeC1Ev at Base 0.2.7
- _ZN5Qwt3D4ConeC2Edj at Base 0.2.7
- _ZN5Qwt3D4ConeC2Ev at Base 0.2.7
- _ZN5Qwt3D4ConeD0Ev at Base 0.2.7
- _ZN5Qwt3D4ConeD1Ev at Base 0.2.7
- _ZN5Qwt3D4ConeD2Ev at Base 0.2.7
- _ZN5Qwt3D5Arrow12calcRotationERNS_6TripleERKNS_10FreeVectorE at Base 0.2.7
- _ZN5Qwt3D5Arrow4drawERKNS_6TripleE at Base 0.2.7
- _ZN5Qwt3D5Arrow9configureEiddd at Base 0.2.7
- _ZN5Qwt3D5ArrowC1Ev at Base 0.2.7
- _ZN5Qwt3D5ArrowC2Ev at Base 0.2.7
- _ZN5Qwt3D5ArrowD0Ev at Base 0.2.7
- _ZN5Qwt3D5ArrowD1Ev at Base 0.2.7
- _ZN5Qwt3D5ArrowD2Ev at Base 0.2.7
- _ZN5Qwt3D5GL2QtEddd at Base 0.2.7
- _ZN5Qwt3D5Label11setPositionENS_6TripleENS_6ANCHORE at Base 0.2.7
- _ZN5Qwt3D5Label12devicefonts_E at Base 0.2.7
- _ZN5Qwt3D5Label14convert2screenEv at Base 0.2.7
- _ZN5Qwt3D5Label14setRelPositionENS_5TupleENS_6ANCHORE at Base 0.2.7
- _ZN5Qwt3D5Label14useDeviceFontsEb at Base 0.2.7
- _ZN5Qwt3D5Label4drawEv at Base 0.2.7
- _ZN5Qwt3D5Label4initERK7QStringiib at Base 0.2.7
- _ZN5Qwt3D5Label4initEv at Base 0.2.7
- _ZN5Qwt3D5Label6adjustEi at Base 0.2.7
- _ZN5Qwt3D5Label6updateEv at Base 0.2.7
- _ZN5Qwt3D5Label7setFontERK7QStringiib at Base 0.2.7
- _ZN5Qwt3D5Label8setColorENS_4RGBAE at Base 0.2.7
- _ZN5Qwt3D5Label8setColorEdddd at Base 0.2.7
- _ZN5Qwt3D5Label9setStringERK7QString at Base 0.2.7
- _ZN5Qwt3D5LabelC1ERK7QStringiib at Base 0.2.7
- _ZN5Qwt3D5LabelC1Ev at Base 0.2.7
- _ZN5Qwt3D5LabelC2ERK7QStringiib at Base 0.2.7
- _ZN5Qwt3D5LabelC2Ev at Base 0.2.7
- _ZN5Qwt3D5LabelD0Ev at Base 0.2.7
- _ZN5Qwt3D5LabelD1Ev at Base 0.2.7
- _ZN5Qwt3D5LabelD2Ev at Base 0.2.7
- _ZN5Qwt3D5Qt2GLE6QColor at Base 0.2.7
- _ZN5Qwt3D5Scale14setMajorLimitsEdd at Base 0.2.7
- _ZN5Qwt3D5Scale9autoscaleERdS1_ddi at Base 0.2.7
- _ZN5Qwt3D5Scale9setLimitsEdd at Base 0.2.7
- _ZN5Qwt3D5Scale9setMajorsEi at Base 0.2.7
- _ZN5Qwt3D5Scale9setMinorsEi at Base 0.2.7
- _ZN5Qwt3D5ScaleC1Ev at Base 0.2.7
- _ZN5Qwt3D5ScaleC2Ev at Base 0.2.7
- _ZN5Qwt3D5ScaleD0Ev at Base 0.2.7
- _ZN5Qwt3D5ScaleD1Ev at Base 0.2.7
- _ZN5Qwt3D5ScaleD2Ev at Base 0.2.7
- _ZN5Qwt3D6Plot3D10applyLightEj at Base 0.2.7
- _ZN5Qwt3D6Plot3D10illuminateEj at Base 0.2.7
- _ZN5Qwt3D6Plot3D10savePixmapERK7QStringS3_ at Base 0.2.7
- _ZN5Qwt3D6Plot3D10saveVectorERK7QStringS3_NS_12VectorWriter8TEXTMODEENS4_8SORTMODEE at Base 0.2.7
- _ZN5Qwt3D6Plot3D10setShadingENS_12SHADINGSTYLEE at Base 0.2.7
- _ZN5Qwt3D6Plot3D10updateDataEv at Base 0.2.7
- _ZN5Qwt3D6Plot3D10wheelEventEP11QWheelEvent at Base 0.2.7
- _ZN5Qwt3D6Plot3D11applyLightsEv at Base 0.2.7
- _ZN5Qwt3D6Plot3D11assignMouseENS_10MouseStateES1_S1_S1_S1_S1_S1_S1_S1_ at Base 0.2.7
- _ZN5Qwt3D6Plot3D11enableMouseEb at Base 0.2.7
- _ZN5Qwt3D6Plot3D11qt_metacallEN11QMetaObject4CallEiPPv at Base 0.2.7
- _ZN5Qwt3D6Plot3D11qt_metacastEPKc at Base 0.2.7
- _ZN5Qwt3D6Plot3D11setIsolinesEi at Base 0.2.7
- _ZN5Qwt3D6Plot3D11setKeySpeedEddd at Base 0.2.7
- _ZN5Qwt3D6Plot3D11setRotationEddd at Base 0.2.7
- _ZN5Qwt3D6Plot3D11zoomChangedEd at Base 0.2.7
- _ZN5Qwt3D6Plot3D12disableMouseEb at Base 0.2.7
- _ZN5Qwt3D6Plot3D12initializeGLEv at Base 0.2.7
- _ZN5Qwt3D6Plot3D12renderPixmapEiib at Base 0.2.7
- _ZN5Qwt3D6Plot3D12scaleChangedEddd at Base 0.2.7
- _ZN5Qwt3D6Plot3D12setDataColorEPNS_5ColorE at Base 0.2.7
- _ZN5Qwt3D6Plot3D12setMeshColorENS_4RGBAE at Base 0.2.7
- _ZN5Qwt3D6Plot3D12setPlotStyleENS_9PLOTSTYLEE at Base 0.2.7
- _ZN5Qwt3D6Plot3D12setPlotStyleERKNS_10EnrichmentE at Base 0.2.7
- _ZN5Qwt3D6Plot3D12setShininessEd at Base 0.2.7
- _ZN5Qwt3D6Plot3D12setTitleFontERK7QStringiib at Base 0.2.7
- _ZN5Qwt3D6Plot3D12shiftChangedEddd at Base 0.2.7
- _ZN5Qwt3D6Plot3D13addEnrichmentERKNS_10EnrichmentE at Base 0.2.7
- _ZN5Qwt3D6Plot3D13keyPressEventEP9QKeyEvent at Base 0.2.7
- _ZN5Qwt3D6Plot3D13setLightShiftEdddj at Base 0.2.7
- _ZN5Qwt3D6Plot3D13setScaleMouseENS_10MouseStateEd6QPoint at Base 0.2.7
- _ZN5Qwt3D6Plot3D13setShiftMouseENS_10MouseStateEd6QPoint at Base 0.2.7
- _ZN5Qwt3D6Plot3D14assignKeyboardENS_13KeyboardStateES1_S1_S1_S1_S1_S1_S1_S1_S1_S1_S1_S1_S1_S1_S1_S1_S1_ at Base 0.2.7
- _ZN5Qwt3D6Plot3D14enableKeyboardEb at Base 0.2.7
- _ZN5Qwt3D6Plot3D14enableLightingEb at Base 0.2.7
- _ZN5Qwt3D6Plot3D14mouseMoveEventEP11QMouseEvent at Base 0.2.7
- _ZN5Qwt3D6Plot3D15disableKeyboardEb at Base 0.2.7
- _ZN5Qwt3D6Plot3D15disableLightingEb at Base 0.2.7
- _ZN5Qwt3D6Plot3D15mousePressEventEP11QMouseEvent at Base 0.2.7
- _ZN5Qwt3D6Plot3D15rotationChangedEddd at Base 0.2.7
- _ZN5Qwt3D6Plot3D15showColorLegendEb at Base 0.2.7
- _ZN5Qwt3D6Plot3D16createEnrichmentERNS_10EnrichmentE at Base 0.2.7
- _ZN5Qwt3D6Plot3D16setLightRotationEdddj at Base 0.2.7
- _ZN5Qwt3D6Plot3D16setMeshLineWidthEd at Base 0.2.7
- _ZN5Qwt3D6Plot3D16setPolygonOffsetEd at Base 0.2.7
- _ZN5Qwt3D6Plot3D16setRotationMouseENS_10MouseStateEd6QPoint at Base 0.2.7
- _ZN5Qwt3D6Plot3D16setScaleKeyboardENS_13KeyboardStateEd at Base 0.2.7
- _ZN5Qwt3D6Plot3D16setShiftKeyboardENS_13KeyboardStateEd at Base 0.2.7
- _ZN5Qwt3D6Plot3D16setTitlePositionEddNS_6ANCHORE at Base 0.2.7
- _ZN5Qwt3D6Plot3D16setViewportShiftEdd at Base 0.2.7
- _ZN5Qwt3D6Plot3D16staticMetaObjectE at Base 0.2.7
- _ZN5Qwt3D6Plot3D17createEnrichmentsEv at Base 0.2.7
- _ZN5Qwt3D6Plot3D17mouseReleaseEventEP11QMouseEvent at Base 0.2.7
- _ZN5Qwt3D6Plot3D17projectionChangedEb at Base 0.2.7
- _ZN5Qwt3D6Plot3D17setLightComponentEjddddj at Base 0.2.7
- _ZN5Qwt3D6Plot3D17setLightComponentEjdj at Base 0.2.7
- _ZN5Qwt3D6Plot3D18setBackgroundColorENS_4RGBAE at Base 0.2.7
- _ZN5Qwt3D6Plot3D18setCoordinateStyleENS_10COORDSTYLEE at Base 0.2.7
- _ZN5Qwt3D6Plot3D19setRotationKeyboardENS_13KeyboardStateEd at Base 0.2.7
- _ZN5Qwt3D6Plot3D19vieportShiftChangedEdd at Base 0.2.7
- _ZN5Qwt3D6Plot3D20setMaterialComponentEjd at Base 0.2.7
- _ZN5Qwt3D6Plot3D20setMaterialComponentEjdddd at Base 0.2.7
- _ZN5Qwt3D6Plot3D22createCoordinateSystemENS_6TripleES1_ at Base 0.2.7
- _ZN5Qwt3D6Plot3D22createCoordinateSystemEv at Base 0.2.7
- _ZN5Qwt3D6Plot3D4saveERK7QStringS3_ at Base 0.2.7
- _ZN5Qwt3D6Plot3D7blowoutEj at Base 0.2.7
- _ZN5Qwt3D6Plot3D7degradeEPNS_10EnrichmentE at Base 0.2.7
- _ZN5Qwt3D6Plot3D7paintGLEv at Base 0.2.7
- _ZN5Qwt3D6Plot3D7setZoomEd at Base 0.2.7
- _ZN5Qwt3D6Plot3D8resizeGLEii at Base 0.2.7
- _ZN5Qwt3D6Plot3D8setOrthoEb at Base 0.2.7
- _ZN5Qwt3D6Plot3D8setScaleEddd at Base 0.2.7
- _ZN5Qwt3D6Plot3D8setShiftEddd at Base 0.2.7
- _ZN5Qwt3D6Plot3DC1EP7QWidgetPK9QGLWidget at Base 0.2.7
- _ZN5Qwt3D6Plot3DC2EP7QWidgetPK9QGLWidget at Base 0.2.7
- _ZN5Qwt3D6Plot3DD0Ev at Base 0.2.7
- _ZN5Qwt3D6Plot3DD1Ev at Base 0.2.7
- _ZN5Qwt3D6Plot3DD2Ev at Base 0.2.7
- _ZN5Qwt3D8CellData5clearEv at Base 0.2.7
- _ZN5Qwt3D8CellDataD0Ev at Base 0.2.7
- _ZN5Qwt3D8CellDataD1Ev at Base 0.2.7
- _ZN5Qwt3D8CellDataD2Ev at Base 0.2.7
- _ZN5Qwt3D8CellDataclEjj at Base 0.2.7
- _ZN5Qwt3D8Drawable11saveGLStateEv at Base 0.2.7
- _ZN5Qwt3D8Drawable14ViewPort2WorldENS_6TripleEPb at Base 0.2.7
- _ZN5Qwt3D8Drawable14World2ViewPortENS_6TripleEPb at Base 0.2.7
- _ZN5Qwt3D8Drawable14restoreGLStateEv at Base 0.2.7
- _ZN5Qwt3D8Drawable16relativePositionENS_6TripleE at Base 0.2.7
- _ZN5Qwt3D8Drawable4drawEv at Base 0.2.7
- _ZN5Qwt3D8Drawable6EnableEjh at Base 0.2.7
- _ZN5Qwt3D8Drawable6attachEPS0_ at Base 0.2.7
- _ZN5Qwt3D8Drawable6detachEPS0_ at Base 0.2.7
- _ZN5Qwt3D8Drawable8setColorENS_4RGBAE at Base 0.2.7
- _ZN5Qwt3D8Drawable8setColorEdddd at Base 0.2.7
- _ZN5Qwt3D8Drawable9detachAllEv at Base 0.2.7
- _ZN5Qwt3D8DrawableD0Ev at Base 0.2.7
- _ZN5Qwt3D8DrawableD1Ev at Base 0.2.7
- _ZN5Qwt3D8DrawableD2Ev at Base 0.2.7
- _ZN5Qwt3D8Function6assignEPNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D8Function6assignERNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D8Function6createERNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D8Function6createEv at Base 0.2.7
- _ZN5Qwt3D8Function7setMaxZEd at Base 0.2.7
- _ZN5Qwt3D8Function7setMinZEd at Base 0.2.7
- _ZN5Qwt3D8FunctionC1EPNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D8FunctionC1ERNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D8FunctionC1Ev at Base 0.2.7
- _ZN5Qwt3D8FunctionC2EPNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D8FunctionC2ERNS_11SurfacePlotE at Base 0.2.7
- _ZN5Qwt3D8FunctionC2Ev at Base 0.2.7
- _ZN5Qwt3D8GridData5clearEv at Base 0.2.7
- _ZN5Qwt3D8GridData7setSizeEjj at Base 0.2.7
- _ZN5Qwt3D8GridDataC1Ejj at Base 0.2.7
- _ZN5Qwt3D8GridDataC1Ev at Base 0.2.7
- _ZN5Qwt3D8GridDataC2Ejj at Base 0.2.7
- _ZN5Qwt3D8GridDataC2Ev at Base 0.2.7
- _ZN5Qwt3D8GridDataD0Ev at Base 0.2.7
- _ZN5Qwt3D8GridDataD1Ev at Base 0.2.7
- _ZN5Qwt3D8GridDataD2Ev at Base 0.2.7
- _ZN5Qwt3D8LogScale12setupCounterERdRi at Base 0.2.7
- _ZN5Qwt3D8LogScale9calculateEv at Base 0.2.7
- _ZN5Qwt3D8LogScale9setMinorsEi at Base 0.2.7
- _ZN5Qwt3D8LogScaleC1Ev at Base 0.2.7
- _ZN5Qwt3D8LogScaleC2Ev at Base 0.2.7
- _ZN5Qwt3D8LogScaleD0Ev at Base 0.2.7
- _ZN5Qwt3D8LogScaleD1Ev at Base 0.2.7
- _ZN5Qwt3D8LogScaleD2Ev at Base 0.2.7
- _ZN5Qwt3D9CrossHair4drawERKNS_6TripleE at Base 0.2.7
- _ZN5Qwt3D9CrossHair7drawEndEv at Base 0.2.7
- _ZN5Qwt3D9CrossHair9configureEddbb at Base 0.2.7
- _ZN5Qwt3D9CrossHair9drawBeginEv at Base 0.2.7
- _ZN5Qwt3D9CrossHairC1Eddbb at Base 0.2.7
- _ZN5Qwt3D9CrossHairC1Ev at Base 0.2.7
- _ZN5Qwt3D9CrossHairC2Eddbb at Base 0.2.7
- _ZN5Qwt3D9CrossHairC2Ev at Base 0.2.7
- _ZN5Qwt3D9CrossHairD0Ev at Base 0.2.7
- _ZN5Qwt3D9CrossHairD1Ev at Base 0.2.7
- _ZN5Qwt3D9CrossHairD2Ev at Base 0.2.7
- _ZN7QStringD1Ev at Base 0.2.7
- _ZN7QStringD2Ev at Base 0.2.7
- _ZNK5Qwt3D11LinearScale5cloneEv at Base 0.2.7
- _ZNK5Qwt3D11SurfacePlot10metaObjectEv at Base 0.2.7
- _ZNK5Qwt3D11SurfacePlot6facetsEv at Base 0.2.7
- _ZNK5Qwt3D12NativeReader5cloneEv at Base 0.2.7
- _ZNK5Qwt3D12PixmapWriter5cloneEv at Base 0.2.7
- _ZNK5Qwt3D12VectorWriter5cloneEv at Base 0.2.7
- _ZNK5Qwt3D13StandardColorclEddd at Base 0.2.7
- _ZNK5Qwt3D16LinearAutoScaler5cloneEv at Base 0.2.7
- _ZNK5Qwt3D16VertexEnrichment4typeEv at Base 0.2.7
- _ZNK5Qwt3D2IO7Wrapper5cloneEv at Base 0.2.7
- _ZNK5Qwt3D3Dot5cloneEv at Base 0.2.7
- _ZNK5Qwt3D4Cone5cloneEv at Base 0.2.7
- _ZNK5Qwt3D5Arrow5cloneEv at Base 0.2.7
- _ZNK5Qwt3D5ColorclERKNS_6TripleE at Base 0.2.7
- _ZNK5Qwt3D5Label5widthEv at Base 0.2.7
- _ZNK5Qwt3D5Label6heightEv at Base 0.2.7
- _ZNK5Qwt3D5Scale8ticLabelEj at Base 0.2.7
- _ZNK5Qwt3D6Plot3D10metaObjectEv at Base 0.2.7
- _ZNK5Qwt3D6Plot3D12mouseEnabledEv at Base 0.2.7
- _ZNK5Qwt3D6Plot3D15keyboardEnabledEv at Base 0.2.7
- _ZNK5Qwt3D6Plot3D15lightingEnabledEv at Base 0.2.7
- _ZNK5Qwt3D6Plot3D8keySpeedERdS1_S1_ at Base 0.2.7
- _ZNK5Qwt3D7Mapping4nameEv at Base 0.2.7
- _ZNK5Qwt3D8CellData5emptyEv at Base 0.2.7
- _ZNK5Qwt3D8GridData4rowsEv at Base 0.2.7
- _ZNK5Qwt3D8GridData5emptyEv at Base 0.2.7
- _ZNK5Qwt3D8GridData7columnsEv at Base 0.2.7
- _ZNK5Qwt3D8LogScale5cloneEv at Base 0.2.7
- _ZNK5Qwt3D8LogScale8ticLabelEj at Base 0.2.7
- _ZNK5Qwt3D9CrossHair5cloneEv at Base 0.2.7
- _ZNK7QStringeqEPKc at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIN5Qwt3D2IO5EntryESaIS2_EE17_M_realloc_insertIJRKS2_EEEvN9__gnu_cxx17__normal_iteratorIPS2_S4_EEDpOT_ at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIN5Qwt3D2IO5EntryESaIS2_EED1Ev at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIN5Qwt3D2IO5EntryESaIS2_EED2Ev at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIN5Qwt3D4RGBAESaIS1_EEaSERKS3_ at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIN5Qwt3D5LabelESaIS1_EE17_M_default_appendEm at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIN5Qwt3D5LabelESaIS1_EED1Ev at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIN5Qwt3D5LabelESaIS1_EED2Ev at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIN5Qwt3D6TripleESaIS1_EE12emplace_backIJS1_EEEvDpOT_ at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIN5Qwt3D6TripleESaIS1_EE17_M_realloc_insertIJRKS1_EEEvN9__gnu_cxx17__normal_iteratorIPS1_S3_EEDpOT_ at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIN5Qwt3D6TripleESaIS1_EEaSERKS3_ at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIS_IPdSaIS0_EESaIS2_EED1Ev at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIS_IPdSaIS0_EESaIS2_EED2Ev at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIS_IjSaIjEESaIS1_EEaSERKS3_ at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIdSaIdEE17_M_realloc_insertIJRKdEEEvN9__gnu_cxx17__normal_iteratorIPdS1_EEDpOT_ at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIdSaIdEEaSERKS1_ at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIjSaIjEE17_M_realloc_insertIJjEEEvN9__gnu_cxx17__normal_iteratorIPjS1_EEDpOT_ at Base 0.2.7
- (optional=templinst)_ZNSt6vectorIjSaIjEEaSERKS1_ at Base 0.2.7
- (optional=templinst)_ZSt9__find_ifIN9__gnu_cxx17__normal_iteratorIPN5Qwt3D2IO5EntryESt6vectorIS4_SaIS4_EEEENS0_5__ops10_Iter_predINS3_13FormatCompareEEEET_SE_SE_T0_St26random_access_iterator_tag at Base 0.2.7
- (optional=templinst)_ZSt9__find_ifIN9__gnu_cxx17__normal_iteratorIPN5Qwt3D2IO5EntryESt6vectorIS4_SaIS4_EEEENS0_5__ops10_Iter_predINS3_14FormatCompare2EEEET_SE_SE_T0_St26random_access_iterator_tag at Base 0.2.7
- _ZTIN5Qwt3D10AutoScalerE at Base 0.2.7
- _ZTIN5Qwt3D10EnrichmentE at Base 0.2.7
- _ZTIN5Qwt3D11ColorLegendE at Base 0.2.7
- _ZTIN5Qwt3D11GridMappingE at Base 0.2.7
- _ZTIN5Qwt3D11LinearScaleE at Base 0.2.7
- _ZTIN5Qwt3D11SurfacePlotE at Base 0.2.7
- _ZTIN5Qwt3D12NativeReaderE at Base 0.2.7
- _ZTIN5Qwt3D12PixmapWriterE at Base 0.2.7
- _ZTIN5Qwt3D12VectorWriterE at Base 0.2.7
- _ZTIN5Qwt3D13StandardColorE at Base 0.2.7
- _ZTIN5Qwt3D16CoordinateSystemE at Base 0.2.7
- _ZTIN5Qwt3D16LinearAutoScalerE at Base 0.2.7
- _ZTIN5Qwt3D16VertexEnrichmentE at Base 0.2.7
- _ZTIN5Qwt3D17ParametricSurfaceE at Base 0.2.7
- _ZTIN5Qwt3D2IO7FunctorE at Base 0.2.7
- _ZTIN5Qwt3D2IO7WrapperE at Base 0.2.7
- _ZTIN5Qwt3D3DotE at Base 0.2.7
- _ZTIN5Qwt3D4AxisE at Base 0.2.7
- _ZTIN5Qwt3D4ConeE at Base 0.2.7
- _ZTIN5Qwt3D4DataE at Base 0.2.7
- _ZTIN5Qwt3D5ArrowE at Base 0.2.7
- _ZTIN5Qwt3D5ColorE at Base 0.2.7
- _ZTIN5Qwt3D5LabelE at Base 0.2.7
- _ZTIN5Qwt3D5ScaleE at Base 0.2.7
- _ZTIN5Qwt3D6Plot3DE at Base 0.2.7
- _ZTIN5Qwt3D7MappingE at Base 0.2.7
- _ZTIN5Qwt3D8CellDataE at Base 0.2.7
- _ZTIN5Qwt3D8DrawableE at Base 0.2.7
- _ZTIN5Qwt3D8FunctionE at Base 0.2.7
- _ZTIN5Qwt3D8GridDataE at Base 0.2.7
- _ZTIN5Qwt3D8LogScaleE at Base 0.2.7
- _ZTIN5Qwt3D9CrossHairE at Base 0.2.7
- _ZTSN5Qwt3D10AutoScalerE at Base 0.2.7
- _ZTSN5Qwt3D10EnrichmentE at Base 0.2.7
- _ZTSN5Qwt3D11ColorLegendE at Base 0.2.7
- _ZTSN5Qwt3D11GridMappingE at Base 0.2.7
- _ZTSN5Qwt3D11LinearScaleE at Base 0.2.7
- _ZTSN5Qwt3D11SurfacePlotE at Base 0.2.7
- _ZTSN5Qwt3D12NativeReaderE at Base 0.2.7
- _ZTSN5Qwt3D12PixmapWriterE at Base 0.2.7
- _ZTSN5Qwt3D12VectorWriterE at Base 0.2.7
- _ZTSN5Qwt3D13StandardColorE at Base 0.2.7
- _ZTSN5Qwt3D16CoordinateSystemE at Base 0.2.7
- _ZTSN5Qwt3D16LinearAutoScalerE at Base 0.2.7
- _ZTSN5Qwt3D16VertexEnrichmentE at Base 0.2.7
- _ZTSN5Qwt3D17ParametricSurfaceE at Base 0.2.7
- _ZTSN5Qwt3D2IO7FunctorE at Base 0.2.7
- _ZTSN5Qwt3D2IO7WrapperE at Base 0.2.7
- _ZTSN5Qwt3D3DotE at Base 0.2.7
- _ZTSN5Qwt3D4AxisE at Base 0.2.7
- _ZTSN5Qwt3D4ConeE at Base 0.2.7
- _ZTSN5Qwt3D4DataE at Base 0.2.7
- _ZTSN5Qwt3D5ArrowE at Base 0.2.7
- _ZTSN5Qwt3D5ColorE at Base 0.2.7
- _ZTSN5Qwt3D5LabelE at Base 0.2.7
- _ZTSN5Qwt3D5ScaleE at Base 0.2.7
- _ZTSN5Qwt3D6Plot3DE at Base 0.2.7
- _ZTSN5Qwt3D7MappingE at Base 0.2.7
- _ZTSN5Qwt3D8CellDataE at Base 0.2.7
- _ZTSN5Qwt3D8DrawableE at Base 0.2.7
- _ZTSN5Qwt3D8FunctionE at Base 0.2.7
- _ZTSN5Qwt3D8GridDataE at Base 0.2.7
- _ZTSN5Qwt3D8LogScaleE at Base 0.2.7
- _ZTSN5Qwt3D9CrossHairE at Base 0.2.7
- _ZTVN5Qwt3D11ColorLegendE at Base 0.2.7
- _ZTVN5Qwt3D11GridMappingE at Base 0.2.7
- _ZTVN5Qwt3D11LinearScaleE at Base 0.2.7
- _ZTVN5Qwt3D11SurfacePlotE at Base 0.2.7
- _ZTVN5Qwt3D12NativeReaderE at Base 0.2.7
- _ZTVN5Qwt3D12PixmapWriterE at Base 0.2.7
- _ZTVN5Qwt3D12VectorWriterE at Base 0.2.7
- _ZTVN5Qwt3D13StandardColorE at Base 0.2.7
- _ZTVN5Qwt3D16CoordinateSystemE at Base 0.2.7
- _ZTVN5Qwt3D16LinearAutoScalerE at Base 0.2.7
- _ZTVN5Qwt3D17ParametricSurfaceE at Base 0.2.7
- _ZTVN5Qwt3D2IO7WrapperE at Base 0.2.7
- _ZTVN5Qwt3D3DotE at Base 0.2.7
- _ZTVN5Qwt3D4AxisE at Base 0.2.7
- _ZTVN5Qwt3D4ConeE at Base 0.2.7
- _ZTVN5Qwt3D5ArrowE at Base 0.2.7
- _ZTVN5Qwt3D5LabelE at Base 0.2.7
- _ZTVN5Qwt3D5ScaleE at Base 0.2.7
- _ZTVN5Qwt3D6Plot3DE at Base 0.2.7
- _ZTVN5Qwt3D8CellDataE at Base 0.2.7
- _ZTVN5Qwt3D8DrawableE at Base 0.2.7
- _ZTVN5Qwt3D8FunctionE at Base 0.2.7
- _ZTVN5Qwt3D8GridDataE at Base 0.2.7
- _ZTVN5Qwt3D8LogScaleE at Base 0.2.7
- _ZTVN5Qwt3D9CrossHairE at Base 0.2.7
- gl2psBeginPage at Base 0.2.7
- gl2psBeginViewport at Base 0.2.7
- gl2psBlendFunc at Base 0.2.7
- gl2psDisable at Base 0.2.7
- gl2psDrawImageMap at Base 0.2.7
- gl2psDrawPixels at Base 0.2.7
- gl2psEnable at Base 0.2.7
- gl2psEndPage at Base 0.2.7
- gl2psEndViewport at Base 0.2.7
- gl2psGetFileExtension at Base 0.2.7
- gl2psGetFormatDescription at Base 0.2.7
- gl2psLineWidth at Base 0.2.7
- gl2psPointSize at Base 0.2.7
- gl2psSetOptions at Base 0.2.7
- gl2psSpecial at Base 0.2.7
- gl2psText at Base 0.2.7
- gl2psTextOpt at Base 0.2.7
- (c++)"non-virtual thunk to Qwt3D::Plot3D::~Plot3D()@Base" 0.2.7
- (c++)"non-virtual thunk to Qwt3D::SurfacePlot::~SurfacePlot()@Base" 0.2.7
diff --git a/debian/libqwtplot3d-qt5-dev.install b/debian/libqwtplot3d-qt5-dev.install
deleted file mode 100644
index 5049be0..0000000
--- a/debian/libqwtplot3d-qt5-dev.install
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/include/qwtplot3d
-usr/lib/libqwtplot3d-qt5.so
diff --git a/debian/patches/01_makefile.patch b/debian/patches/01_makefile.patch
deleted file mode 100644
index dea95ff..0000000
--- a/debian/patches/01_makefile.patch
+++ /dev/null
@@ -1,125 +0,0 @@
-Fixes the makefiles to install according to the Debian FHS
-Index: qwtplot3d-0.2.7+svn191/doc/Doxyfile.doxygen
-===================================================================
---- qwtplot3d-0.2.7+svn191.orig/doc/Doxyfile.doxygen
-+++ qwtplot3d-0.2.7+svn191/doc/Doxyfile.doxygen
-@@ -116,7 +116,7 @@ HTML_STYLESHEET        = web/navigation/
- HTML_ALIGN_MEMBERS     = YES
- GENERATE_HTMLHELP      = NO
- CHM_FILE               = qwtplot3d.chm
--HHC_LOCATION           = "c:\Programme\HTML Help Workshop\hhc.exe"
-+#HHC_LOCATION           = "c:\Programme\HTML Help Workshop\hhc.exe"
- GENERATE_CHI           = NO
- BINARY_TOC             = YES
- TOC_EXPAND             = YES
-@@ -181,7 +181,7 @@ ENABLE_PREPROCESSING   = YES
- MACRO_EXPANSION        = NO
- EXPAND_ONLY_PREDEF     = NO
- SEARCH_INCLUDES        = YES
--INCLUDE_PATH           = V:/cvs/qwtplot3d/include/
-+INCLUDE_PATH           = ../include/
- INCLUDE_FILE_PATTERNS  = *.h
- PREDEFINED             = QWT3D_NOT_FOR_DOXYGEN \
-                          QT_VERSION=0x040000
-@@ -212,7 +212,7 @@ CALL_GRAPH             = NO
- GRAPHICAL_HIERARCHY    = YES
- DIRECTORY_GRAPH        = YES
- DOT_IMAGE_FORMAT       = png
--DOT_PATH               = V:/graphviz/Graphviz/bin/
-+#DOT_PATH               = V:/graphviz/Graphviz/bin/
- DOTFILE_DIRS           = 
- MAX_DOT_GRAPH_WIDTH    = 974
- MAX_DOT_GRAPH_HEIGHT   = 10000
-Index: qwtplot3d-0.2.7+svn191/examples/common.pro
-===================================================================
---- qwtplot3d-0.2.7+svn191.orig/examples/common.pro
-+++ qwtplot3d-0.2.7+svn191/examples/common.pro
-@@ -3,13 +3,18 @@ CONFIG      += qt warn_on thread debug
- UI_DIR = tmp
- MOC_DIR      = tmp
- OBJECTS_DIR  = tmp
--INCLUDEPATH    += ../../include 
--DEPENDPATH	= $$INCLUDEPATH
- DESTDIR = ../bin
-+QT += widgets
- 
--unix:LIBS += -lqwtplot3d -L../../lib
- linux-g++:QMAKE_CXXFLAGS += -fno-exceptions
- 
-+unix{
-+  unix:LIBS += -lqwtplot3d-qt4
-+  INCLUDEPATH    += /usr/include/qwtplot3d-qt4
-+}
-+
-+DEPENDPATH	= $$INCLUDEPATH
-+
- win32{
-   LIBS += ../../lib/qwtplot3d.lib
-   TEMPLATE  = vcapp
-@@ -28,7 +33,7 @@ MYVERSION = $$[QMAKE_VERSION]
- ISQT4 = $$find(MYVERSION, ^[2-9])
- 
- !isEmpty( ISQT4 ) {
--RESOURCES     = ../images.qrc
-+#RESOURCES     = ../images.qrc
- QT += opengl
- }
- 
-Index: qwtplot3d-0.2.7+svn191/qwtplot3d.pro
-===================================================================
---- qwtplot3d-0.2.7+svn191.orig/qwtplot3d.pro
-+++ qwtplot3d-0.2.7+svn191/qwtplot3d.pro
-@@ -1,7 +1,13 @@
- # pro file for building the makefile for qwtplot3d
- #
- 
--TARGET            = qwtplot3d
-+TARGET            = qwtplot3d-qt$$QT_VERSION
-+# Install directives
-+INSTALLBASE	  = /usr
-+headers.path      = $$INSTALLBASE/include/qwtplot3d-qt$$QT_VERSION
-+headers.files     = $$HEADERS
-+target.path       = $$INSTALLBASE/lib
-+INSTALLS          = doc headers target
- TEMPLATE          = lib
- CONFIG           += qt warn_on opengl thread zlib debug
- MOC_DIR           = tmp
-@@ -87,9 +98,11 @@ HEADERS+=3rdparty/gl2ps/gl2ps.h \
- SOURCES+=src/qwt3d_io_gl2ps.cpp \
-          3rdparty/gl2ps/gl2ps.c
- 
-+unix:LIBS  += -lGLU
-+
- # zlib support for gl2ps
- zlib {
-   DEFINES += GL2PS_HAVE_ZLIB
-   win32:LIBS += zlib.lib
- 	unix:LIBS  += -lz
--}
-\ No newline at end of file
-+}
-Index: qwtplot3d-0.2.7+svn191/examples/mesh2/src/designerworkaround.h
-===================================================================
---- qwtplot3d-0.2.7+svn191.orig/examples/mesh2/src/designerworkaround.h
-+++ qwtplot3d-0.2.7+svn191/examples/mesh2/src/designerworkaround.h
-@@ -1,13 +1,13 @@
- #ifndef designerworkaround_h__2005_07_10_10_46_begin_guarded_code
- #define designerworkaround_h__2005_07_10_10_46_begin_guarded_code
- 
--#include <QtGui/QMenu>
--#include <QtGui/QToolBar>
--#include <QtGui/QAction>
--#include <QtGui/QActionGroup>
--#include <QtGui/QMainWindow>
--#include <QtGui/QComboBox>
--#include <QtGui/QMenuBar>
-+#include <QMenu>
-+#include <QToolBar>
-+#include <QAction>
-+#include <QActionGroup>
-+#include <QMainWindow>
-+#include <QComboBox>
-+#include <QMenuBar>
- 
- 
- class DesignerWorkaround
diff --git a/debian/patches/02_examples_include.patch b/debian/patches/02_examples_include.patch
deleted file mode 100644
index 2bc2dc8..0000000
--- a/debian/patches/02_examples_include.patch
+++ /dev/null
@@ -1,132 +0,0 @@
-Change include directory from local to system wide
---- a/examples/axes/src/axesmainwindow.cpp
-+++ b/examples/axes/src/axesmainwindow.cpp
-@@ -9,7 +9,7 @@
- 
- #include "axes.h"
- #include "axesmainwindow.h"
--#include "../../../include/qwt3d_function.h"
-+#include <qwt3d_function.h>
- 
- using namespace std;
- using namespace Qwt3D;
---- a/examples/mesh2/src/colormapreader.h
-+++ b/examples/mesh2/src/colormapreader.h
-@@ -5,7 +5,7 @@
- #include <qframe.h>
- #include <qpixmap.h>
- 
--#include "../../../include/qwt3d_types.h"
-+#include <qwt3d_types.h>
- 
- #if QT_VERSION < 0x040000
- 
---- a/examples/mesh2/src/functions.h
-+++ b/examples/mesh2/src/functions.h
-@@ -2,8 +2,8 @@
- #define __EXAMPLE_H__
- 
- #include <math.h>
--#include "../../../include/qwt3d_parametricsurface.h"
--#include "../../../include/qwt3d_function.h"
-+#include <qwt3d_parametricsurface.h>
-+#include <qwt3d_function.h>
- 
- using namespace Qwt3D;
- 
---- a/examples/mesh2/src/lightingdlg.h
-+++ b/examples/mesh2/src/lightingdlg.h
-@@ -3,10 +3,10 @@
- 
- #include <math.h>
- #include <qapplication.h>
--#include "../../../include/qwt3d_parametricsurface.h"
--#include "../../../include/qwt3d_surfaceplot.h"
--#include "../../../include/qwt3d_enrichment.h"
--#include "../../../include/qwt3d_color.h"
-+#include <qwt3d_parametricsurface.h>
-+#include <qwt3d_surfaceplot.h>
-+#include <qwt3d_enrichment.h>
-+#include <qwt3d_color.h>
- 
- #if QT_VERSION < 0x040000
- #include "lightingdlgbase.h"
---- a/examples/mesh2/src/mesh2mainwindow.cpp
-+++ b/examples/mesh2/src/mesh2mainwindow.cpp
-@@ -16,7 +16,7 @@
- #include <qtoolbar.h>
- #include <qimage.h>
- #include <qpixmap.h>
--#include <qfiledialog.h>       
-+#include <qfiledialog.h>
- #include <qstatusbar.h>
- #include <qfileinfo.h>
- #include <qslider.h>
-@@ -33,9 +33,9 @@
- #include "colormapreader.h"
- #include "lightingdlg.h"
- #include "femreader.h"
--#include "../../../include/qwt3d_io.h"
--#include "../../../include/qwt3d_io_gl2ps.h"
--#include "../../../include/qwt3d_io_reader.h"
-+#include <qwt3d_io.h>
-+#include <qwt3d_io_gl2ps.h>
-+#include <qwt3d_io_reader.h>
- 
- using namespace Qwt3D;
- using namespace std;
---- a/examples/mesh2/src/mesh2mainwindow.h
-+++ b/examples/mesh2/src/mesh2mainwindow.h
-@@ -1,7 +1,7 @@
- #ifndef mesh2mainwindow_h__2004_03_07_13_38_begin_guarded_code
- #define mesh2mainwindow_h__2004_03_07_13_38_begin_guarded_code
- 
--#include "../../../include/qwt3d_surfaceplot.h"
-+#include <qwt3d_surfaceplot.h>
- 
- 
- #if QT_VERSION < 0x040000
---- a/examples/enrichments/src/enrichmentmainwindow.cpp
-+++ b/examples/enrichments/src/enrichmentmainwindow.cpp
-@@ -6,7 +6,7 @@
- 
- #include "enrichmentmainwindow.h"
- #include "enrichments.h"
--#include "../../../include/qwt3d_function.h"
-+#include <qwt3d_function.h>
- 
- using namespace Qwt3D;
- 
---- a/examples/common.pro
-+++ b/examples/common.pro
-@@ -9,8 +9,13 @@
- linux-g++:QMAKE_CXXFLAGS += -fno-exceptions
- 
- unix{
--  unix:LIBS += -lqwtplot3d-qt4
--  INCLUDEPATH    += /usr/include/qwtplot3d-qt4
-+  unix:LIBS += -lqwtplot3d-qt$$QT_MAJOR_VERSION
-+  greaterThan(QT_MAJOR_VERSION, 4) {
-+    INCLUDEPATH    += /usr/include/qwtplot3d
-+  }
-+  else {
-+    INCLUDEPATH    += /usr/include/qwtplot3d-qt4
-+  }
- }
- 
- DEPENDPATH	= $$INCLUDEPATH
---- a/qwtplot3d.pro
-+++ b/qwtplot3d.pro
-@@ -1,10 +1,10 @@
- # pro file for building the makefile for qwtplot3d
- #
- 
--TARGET            = qwtplot3d-qt$$QT_VERSION
-+TARGET            = qwtplot3d-qt$$QT_MAJOR_VERSION
- # Install directives
- INSTALLBASE	  = /usr
--headers.path      = $$INSTALLBASE/include/qwtplot3d-qt$$QT_VERSION
-+headers.path      = $$INSTALLBASE/include/qwtplot3d-qt$$QT_MAJOR_VERSION
- headers.files     = $$HEADERS
- target.path       = $$INSTALLBASE/lib
- INSTALLS          = doc headers target
diff --git a/debian/patches/03_fix_ftbs.patch b/debian/patches/03_fix_ftbs.patch
deleted file mode 100644
index 4bc0e9a..0000000
--- a/debian/patches/03_fix_ftbs.patch
+++ /dev/null
@@ -1,18 +0,0 @@
-Add cstdio include
---- a/src/qwt3d_function.cpp
-+++ b/src/qwt3d_function.cpp
-@@ -1,3 +1,4 @@
-+#include <cstdio>
- #include "qwt3d_surfaceplot.h"
- #include "qwt3d_function.h"
- 
---- a/include/qwt3d_openglhelper.h
-+++ b/include/qwt3d_openglhelper.h
-@@ -7,6 +7,7 @@
- #else
- #include <QtOpenGL/qgl.h>
- #endif
-+#include <GL/glu.h>
- 
- namespace Qwt3D
- {
diff --git a/debian/patches/04_hardening.patch b/debian/patches/04_hardening.patch
deleted file mode 100644
index 62b5456..0000000
--- a/debian/patches/04_hardening.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-Adds hardening to makefile
---- a/qwtplot3d.pro
-+++ b/qwtplot3d.pro
-@@ -1,6 +1,11 @@
- # pro file for building the makefile for qwtplot3d
- #
- 
-+QMAKE_CPPFLAGS *= $(shell dpkg-buildflags --get CPPFLAGS)
-+QMAKE_CFLAGS   *= $(shell dpkg-buildflags --get CFLAGS) -D_FORTIFY_SOURCE=2
-+QMAKE_CXXFLAGS *= $(shell dpkg-buildflags --get CXXFLAGS)  -D_FORTIFY_SOURCE=2
-+QMAKE_LFLAGS   *= $(shell dpkg-buildflags --get LDFLAGS)
-+
- TARGET            = qwtplot3d-qt$$QT_MAJOR_VERSION
- # Install directives
- INSTALLBASE	  = /usr
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index 6479118..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1,4 +0,0 @@
-01_makefile.patch
-02_examples_include.patch
-03_fix_ftbs.patch
-04_hardening.patch
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index a4f5995..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/make -f
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-export DEB_BUILD_MAINT_OPTIONS=hardening=+all
-
-export CFLAGS := $(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS)
-export CXXFLAGS := $(shell dpkg-buildflags --get CXXFLAGS) $(shell dpkg-buildflags --get CPPFLAGS)
-export CPPFLAGS := $(shell dpkg-buildflags --get CXXFLAGS) $(shell dpkg-buildflags --get CPPFLAGS)
-export LDFLAGS := $(shell dpkg-buildflags --get LDFLAGS) -Wl,--as-needed
-
-%:
-	dh $@ --parallel --list-missing --with pkgkde_symbolshelper
-
-override_dh_auto_configure:
-	mkdir -p build-qt5
-	cp -a doc build-qt5/
-	QT_SELECT=qt5 dh_auto_configure --builddirectory=build-qt5 -- ../qwtplot3d.pro
-
-override_dh_auto_build:
-	dh_auto_build --builddirectory=build-qt5
-	cd build-qt5/doc && doxygen Doxyfile.doxygen
-
-override_dh_auto_clean:
-	rm -rf build-qt5
-
-override_dh_auto_install:
-	mkdir -p debian/tmp/usr/include/qwtplot3d
-	cp -a include/* debian/tmp/usr/include/qwtplot3d
-	dh_auto_install --builddirectory=build-qt5
-	mkdir -p debian/tmp/usr/include/qwtplot3d
-	cp -a include/* debian/tmp/usr/include/qwtplot3d
-	find debian/tmp/usr -type f -name '*.md5' -exec rm -vf {} \;
-	find debian/tmp/usr -type f -name '*.js' -exec rm -vf {} \;
-	mkdir -p debian/tmp/usr/share/doc/libqwtplot3d-doc/html
-	cp -a build-qt5/doc/web/doxygen/* debian/tmp/usr/share/doc/libqwtplot3d-doc/html
-
-override_dh_compress-indep:
-	dh_compress --exclude=.cpp --exclude=.pri --exclude=.xpm --exclude=.ui
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index 6153543..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,4 +0,0 @@
-version=3
-#http://sf.net/ngspice/ng-spice-rework-(.*)\.tar\.gz debian uupdate
-#http://sf.net/projects/qwtplot3d/files/qwtplot3d/(.*)/qwtplot3d-(.*)\.tgz/download debian uupdate
-http://sf.net/qwtplot3d/qwtplot3d-([0-9].*)\.tgz debian uupdate
diff --git a/doc/Doxyfile.doxygen b/doc/Doxyfile.doxygen
new file mode 100644
index 0000000..2a34e8e
--- /dev/null
+++ b/doc/Doxyfile.doxygen
@@ -0,0 +1,227 @@
+# Doxyfile 1.4.3
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = "QwtPlot3D API"
+PROJECT_NUMBER         = 0.2.7
+OUTPUT_DIRECTORY       = 
+CREATE_SUBDIRS         = NO
+OUTPUT_LANGUAGE        = English
+USE_WINDOWS_ENCODING   = YES
+BRIEF_MEMBER_DESC      = NO
+REPEAT_BRIEF           = NO
+ABBREVIATE_BRIEF       = 
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = NO
+DISTRIBUTE_GROUP_DOC   = NO
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 2
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = NO
+OPTIMIZE_OUTPUT_JAVA   = NO
+SUBGROUPING            = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = YES
+EXTRACT_LOCAL_CLASSES  = NO
+EXTRACT_LOCAL_METHODS  = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = YES
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = NO
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = YES
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = NO
+SORT_BRIEF_DOCS        = NO
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = NO
+GENERATE_TESTLIST      = NO
+GENERATE_BUGLIST       = NO
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+SHOW_DIRECTORIES       = YES
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = YES
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = NO
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = ../src \
+                         . \
+                         ../include
+FILE_PATTERNS          = *.cpp \
+                         *.h \
+                         *.dox
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = moc_*
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = doxygenimages
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 4
+IGNORE_PREFIX          = Qwt3D
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = web/doxygen
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = web/navigation/doxygen.css
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+CHM_FILE               = qwtplot3d.chm
+HHC_LOCATION           = "c:\Programme\HTML Help Workshop\hhc.exe"
+GENERATE_CHI           = NO
+BINARY_TOC             = YES
+TOC_EXPAND             = YES
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = YES
+PAPER_TYPE             = a4
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = YES
+USE_PDFLATEX           = YES
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = V:/cvs/qwtplot3d/include/
+INCLUDE_FILE_PATTERNS  = *.h
+PREDEFINED             = QWT3D_NOT_FOR_DOXYGEN \
+                         QT_VERSION=0x040000
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = NO
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = V:/graphviz/Graphviz/bin/
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 974
+MAX_DOT_GRAPH_HEIGHT   = 10000
+MAX_DOT_GRAPH_DEPTH    = 0
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
diff --git a/doc/footer.html b/doc/footer.html
new file mode 100644
index 0000000..d85179d
--- /dev/null
+++ b/doc/footer.html
@@ -0,0 +1,7 @@
+<hr><address style="align: right;"><small>
+The documentation for the QwtPlot3D API  has been created by <a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border=0 width=110 height=53>
+</a> $doxygenversion and is hosted at </small> <a href="http://sourceforge.net">
+<img src="http://sourceforge.net/sflogo.php?group_id=78209&type=1" width="88" height="31" border="0" alt="SourceForge.net Logo" /></a></address>
+</body>
+</html>
diff --git a/doc/web/navigation/doxygen.css b/doc/web/navigation/doxygen.css
new file mode 100644
index 0000000..ab2ec51
--- /dev/null
+++ b/doc/web/navigation/doxygen.css
@@ -0,0 +1,176 @@
+BODY {
+  background-color: #FAF8E8;
+	background: white;
+  font-family:sans-serif;
+  color:black;
+  font-size: 13px;  
+}
+
+h1, h2, h3, h4 {
+  font-family:sans-serif;
+	color: #005A9C;
+	background: transparent;
+}
+
+H1 {
+	text-align: center;
+  font-size: 18px;  
+}
+H2 {
+  font-size: 16px;  
+}
+CAPTION { font-weight: bold }
+DIV.qindex { width: 100%;
+             background-color: #eeeeff;
+             border: 4px solid #eeeeff;
+             text-align: center;
+             margin-bottom: 2px
+}
+
+a:link {  font-family: Arial, Helvetica, sans-serif; font-size: 13px; line-height: 13px; color: #3366ff}
+a:visited {  font-family: Arial, Helvetica, sans-serif; font-size: 13px; line-height: 13px; color: #3366ff}
+a:hover {  font-family: Arial, Helvetica, sans-serif; font-size: 13px; line-height: 13px; color: #3366ff}
+
+
+A.qindex:hover { background-color: #ddddff }
+A.qindexHL { background-color: #6666cc;
+             color: #ffffff
+           }
+A.qindexHL:hover { background-color: #6666cc }
+A.qindexRef:hover { background-color: #ddddff }
+A.qindexRefHL { background-color: #6666cc;
+             color: #ffffff
+           }
+A.qindexRefHL:hover { background-color: #6666cc }
+
+A.el { text-decoration: none }
+A.code { text-decoration: none; font-weight: normal; color: #4444ee }
+A.codeRef { font-weight: normal; color: #4444ee }
+A:hover { text-decoration: none; background-color: #f2f2ff }
+
+DL.el { margin-left: -1cm }
+DIV.fragment {
+	width: 98%;
+	border: 1px solid #CCCCCC;
+	background-color: #f5f5f5;
+	padding-left: 4px;
+	margin: 4px;
+}
+DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
+TD{  font-size: 13px;}
+TD.md { background-color: #f2f2ff; font-weight: bold}
+TD.mdname1 { background-color: #f2f2ff; font-weight: bold; color: #602020}
+TD.mdname { background-color: #f2f2ff; font-weight: bold; color: #602020; width: 600px}
+DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold }
+DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller }
+BODY {
+	background: white;
+	color: black;
+	margin-right: 20px;
+	margin-left: 20px;
+}
+TD.indexkey { 
+   background-color: #eeeeff; 
+   padding-right  : 10px; 
+   padding-top    : 2px; 
+   padding-left   : 10px; 
+   padding-bottom : 2px; 
+   margin-left    : 0px; 
+   margin-right   : 0px; 
+   margin-top     : 2px; 
+   margin-bottom  : 2px  
+}
+TD.indexvalue { 
+   background-color: #eeeeff; 
+   padding-right  : 10px; 
+   padding-top    : 2px; 
+   padding-left   : 10px; 
+   padding-bottom : 2px; 
+   margin-left    : 0px; 
+   margin-right   : 0px; 
+   margin-top     : 2px; 
+   margin-bottom  : 2px  
+}
+TR.memlist {
+   background-color: #f0f0f0; 
+}
+P.formulaDsp { text-align: center; }
+IMG.formulaDsp { }
+IMG.formulaInl { vertical-align: middle; }
+SPAN.keyword       { color: #008000 }
+SPAN.keywordtype   { color: #604020 }
+SPAN.keywordflow   { color: #e08000 }
+SPAN.comment       { color: #800000 }
+SPAN.preprocessor  { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral   { color: #008080 }
+.mdTable {
+	border: 1px solid #868686;
+	background-color: #f2f2ff;
+}
+.mdRow {
+	padding: 8px 20px;
+}
+.mdescLeft {
+	font-size: smaller;
+	font-family: Arial, Helvetica, sans-serif;
+	background-color: #FAFAFA;
+	padding-left: 8px;
+	border-top: 1px none #E0E0E0;
+	border-right: 1px none #E0E0E0;
+	border-bottom: 1px none #E0E0E0;
+	border-left: 1px none #E0E0E0;
+	margin: 0px;
+}
+.mdescRight {
+	font-size: smaller;
+	font-family: Arial, Helvetica, sans-serif;
+	font-style: italic;
+	background-color: #FAFAFA;
+	padding-left: 4px;
+	border-top: 1px none #E0E0E0;
+	border-right: 1px none #E0E0E0;
+	border-bottom: 1px none #E0E0E0;
+	border-left: 1px none #E0E0E0;
+	margin: 0px;
+	padding-bottom: 0px;
+	padding-right: 8px;
+}
+.memItemLeft {
+	padding: 1px 0px 0px 8px;
+	margin: 4px;
+	border-top-width: 1px;
+	border-right-width: 1px;
+	border-bottom-width: 1px;
+	border-left-width: 1px;
+	border-top-style: solid;
+	border-top-color: #E0E0E0;
+	border-right-color: #E0E0E0;
+	border-bottom-color: #E0E0E0;
+	border-left-color: #E0E0E0;
+	border-right-style: none;
+	border-bottom-style: none;
+	border-left-style: none;
+	background-color: #FAFAFA;
+	font-family: Geneva, Arial, Helvetica, sans-serif;
+	font-size: 13px;
+}
+.memItemRight {
+	padding: 1px 0px 0px 8px;
+	margin: 4px;
+	border-top-width: 1px;
+	border-right-width: 1px;
+	border-bottom-width: 1px;
+	border-left-width: 1px;
+	border-top-style: solid;
+	border-top-color: #E0E0E0;
+	border-right-color: #E0E0E0;
+	border-bottom-color: #E0E0E0;
+	border-left-color: #E0E0E0;
+	border-right-style: none;
+	border-bottom-style: none;
+	border-left-style: none;
+	background-color: #FAFAFA;
+	font-family: Geneva, Arial, Helvetica, sans-serif;
+	font-size: 13px;
+}
diff --git a/doc/web/navigation/doxygen.png b/doc/web/navigation/doxygen.png
new file mode 100644
index 0000000..96ae72c
Binary files /dev/null and b/doc/web/navigation/doxygen.png differ
diff --git a/doc/web/navigation/menu.css b/doc/web/navigation/menu.css
new file mode 100644
index 0000000..f8f92e9
--- /dev/null
+++ b/doc/web/navigation/menu.css
@@ -0,0 +1,12 @@
+BODY{ background: url(bg1.gif) }
+
+A:link {text-decoration:none; color: #004080}
+A:visited {text-decoration:none; color: #003060}
+A:active {text-decoration:none; color:#6F6F00}
+
+
+TD { font-family:Arial,sans-serif }
+TD.outside{background-color: #D0A000} 
+TD.inside{background-color: #FAF8D0; text-align: center; font-size:14px;} 
+TD.selected_outside{background-color: #0000E0}
+TD.alt_outside{background-color:#88BBAA}
diff --git a/doc/web/navigation/sflogo.png b/doc/web/navigation/sflogo.png
new file mode 100644
index 0000000..b2a9e99
Binary files /dev/null and b/doc/web/navigation/sflogo.png differ
diff --git a/dsp.bat b/dsp.bat
new file mode 100644
index 0000000..bc1cdc5
--- /dev/null
+++ b/dsp.bat
@@ -0,0 +1,2 @@
+REM set QMAKESPEC=win32-msvc.net
+qmake qwtplot3d.pro 
\ No newline at end of file
diff --git a/examples/autoswitch/autoswitch.cpp b/examples/autoswitch/autoswitch.cpp
new file mode 100644
index 0000000..92014fc
--- /dev/null
+++ b/examples/autoswitch/autoswitch.cpp
@@ -0,0 +1,102 @@
+#include <qapplication.h>
+#include <qsplitter.h>
+#include <qtimer.h>
+
+#include "autoswitch.h"
+
+using namespace Qwt3D;
+
+//--------------------------------------------------------------------
+//              autoswitch.cpp
+//
+//      Demonstrates autoswitching axes with a cutted saddle as data
+//--------------------------------------------------------------------
+
+Plot::Plot(QWidget* pw, int updateinterval)
+:SurfacePlot(pw)
+{
+	setRotation(30,0,15);
+	setShift(0.1,0,0);
+	setZoom(0.8);
+	coordinates()->setNumberFont("Courier",8);
+
+	for (unsigned i=0; i!=coordinates()->axes.size(); ++i)
+	{
+		coordinates()->axes[i].setMajors(7);
+		coordinates()->axes[i].setMinors(4);
+	}
+	
+	
+	coordinates()->axes[Qwt3D::X1].setLabelString("x");
+	coordinates()->axes[Y1].setLabelString("y");
+	coordinates()->axes[Z1].setLabelString("z"); 
+	coordinates()->axes[X2].setLabelString("x");
+	coordinates()->axes[Y2].setLabelString("y");
+	coordinates()->axes[Z2].setLabelString("z"); 
+	coordinates()->axes[X3].setLabelString("x");
+	coordinates()->axes[Y3].setLabelString("y");
+	coordinates()->axes[Z3].setLabelString("z"); 
+	coordinates()->axes[X4].setLabelString("x");
+	coordinates()->axes[Y4].setLabelString("y");
+	coordinates()->axes[Z4].setLabelString("z"); 
+
+
+  QTimer* timer = new QTimer( this );
+	connect( timer, SIGNAL(timeout()), this, SLOT(rotate()) );
+
+	timer->start(updateinterval);
+
+}
+
+void Plot::rotate()
+{
+	int prec = 3;
+		
+	setRotation(
+			(int(prec*xRotation() + 2) % (360*prec))/double(prec),
+			(int(prec*yRotation() + 2) % (360*prec))/double(prec),
+			(int(prec*zRotation() + 2) % (360*prec))/double(prec)
+			);
+}
+
+
+int main(int argc, char **argv)
+{
+    QApplication a(argc, argv);
+#if QT_VERSION < 0x040000
+		QSplitter* spl = new QSplitter(QSplitter::Horizontal);
+#else
+    QSplitter* spl = new QSplitter(Qt::Horizontal);
+#endif
+		Plot* plot1 = new Plot(spl,30);
+		plot1->setFloorStyle(FLOORISO);
+		plot1->setCoordinateStyle(BOX);
+		Saddle saddle(*plot1);
+		saddle.create();
+		plot1->setTitle("Autoswitching axes");
+		plot1->setBackgroundColor(RGBA(1,1, 157./255));
+		plot1->makeCurrent();
+		plot1->updateData();
+		plot1->updateGL();
+
+
+		Plot* plot2 = new Plot(spl,80);
+		plot2->setZoom(0.8);
+		Hat hat(*plot2);
+		hat.create();
+		plot2->setPlotStyle(HIDDENLINE);
+		plot2->setFloorStyle(FLOORDATA);
+		plot2->setCoordinateStyle(FRAME);
+		plot2->setBackgroundColor(RGBA(1,1, 157./255));
+		plot2->makeCurrent();
+		plot2->updateData();
+		plot2->updateGL();
+
+
+#if QT_VERSION < 0x040000
+    a.setMainWidget(spl);
+#endif
+		spl->resize(800,400);
+    spl->show();
+    return a.exec(); 
+}
diff --git a/examples/autoswitch/autoswitch.h b/examples/autoswitch/autoswitch.h
new file mode 100644
index 0000000..a46bc67
--- /dev/null
+++ b/examples/autoswitch/autoswitch.h
@@ -0,0 +1,58 @@
+#ifndef AUTOSWITCH_H__
+#define AUTOSWITCH_H__
+
+#include <qtimer.h>
+#include "qwt3d_surfaceplot.h"
+#include "qwt3d_function.h"
+
+typedef Qwt3D::SurfacePlot SurfacePlot; // VC6/moc issue
+typedef Qwt3D::Function Function; // VC6/moc issue
+
+class Saddle : public Function
+{
+public:
+	Saddle(SurfacePlot& pw)
+	:Function(pw)
+	{
+		setDomain(-2.5,2.5,-2.5,2.5);
+		setMaxZ(1.5);
+		setMinZ(-1.5);
+		setMesh(31,31);
+	}
+
+	double operator()(double x, double y)
+	{
+		return x*y;
+	}
+};
+
+class Hat : public Function
+{
+public:
+
+	Hat(SurfacePlot& pw)
+	:Function(pw)
+	{
+		setDomain(-1.5,1.5,-1.5,1.5);
+		setMesh(41,41);
+	}
+
+	double operator()(double x, double y)
+	{
+		return 1.0 / (x*x+y*y+0.3);
+	}
+};
+
+class Plot : public SurfacePlot
+{
+	Q_OBJECT
+
+public:
+    Plot(QWidget* pw, int updateinterval);
+
+public slots:
+	void rotate();
+
+};
+
+#endif
diff --git a/examples/autoswitch/autoswitch.pro b/examples/autoswitch/autoswitch.pro
new file mode 100644
index 0000000..5a48ce2
--- /dev/null
+++ b/examples/autoswitch/autoswitch.pro
@@ -0,0 +1,4 @@
+include( ../common.pro )
+
+SOURCES = autoswitch.cpp
+HEADERS = autoswitch.h
diff --git a/examples/axes/axes.pro b/examples/axes/axes.pro
new file mode 100644
index 0000000..d3c0e5c
--- /dev/null
+++ b/examples/axes/axes.pro
@@ -0,0 +1,15 @@
+include( ../common.pro )
+
+SOURCES =  src/main.cpp \
+		       src/axesmainwindow.cpp 
+
+HEADERS =  src/axesmainwindow.h \
+           src/axes.h
+
+!isEmpty( ISQT4 ) {
+  FORMS =  src/axesmainwindowbase4.ui
+}
+isEmpty( ISQT4 ) {
+  FORMS =  src/axesmainwindowbase.ui
+}
+
diff --git a/examples/axes/src/axes.h b/examples/axes/src/axes.h
new file mode 100644
index 0000000..1dc70a5
--- /dev/null
+++ b/examples/axes/src/axes.h
@@ -0,0 +1,75 @@
+#ifndef axes_h__2004_06_07_10_38_begin_guarded_code
+#define axes_h__2004_06_07_10_38_begin_guarded_code
+
+#include "qwt3d_plot.h"
+using namespace Qwt3D;
+
+/*****************************
+*
+*  Examples for user defined 
+*  tic labels
+*
+******************************/
+
+class Letter : public LinearScale
+{
+public:
+  explicit Letter(bool uppercase = true) : uc_(uppercase) {}
+  Scale* clone() const {return new Letter(*this);}
+  QString ticLabel(unsigned int idx) const
+  {
+    if (idx<majors_p.size() && idx < 26)
+      return (uc_) ? QString(QChar('A'+idx)) : QString(QChar('a'+idx));
+    return QString("-");
+  }
+private:
+  bool uc_;
+};
+
+class Imaginary : public LinearScale
+{
+public:
+  Scale* clone() const {return new Imaginary;}
+  QString ticLabel(unsigned int idx) const
+  {
+    if (idx<majors_p.size())
+    {
+      double val = majors_p[idx];
+      if (val)
+        return QString::number(val) + "*i";
+      return QString::number(val);
+    }
+    return QString("");
+  }
+};
+
+class TimeItems : public LinearScale
+{
+public:
+  Scale* clone() const {return new TimeItems;}
+  QString ticLabel(unsigned int idx) const
+  {
+    if (idx<majors_p.size())
+    {
+      QTime t = QTime::currentTime();
+      int h = t.hour();
+      int m = t.minute();
+      if (m+idx > 59)
+      {
+        if (h==23)
+          h=0;
+        else
+          h+=1;
+        m = (m+idx) % 60; 
+      }
+      else
+        m += idx;
+
+      return QTime(h,m).toString("hh:mm")+"h";
+    }
+    return QString("");
+  }
+};
+
+
+#endif /* include guarded */
diff --git a/examples/axes/src/axesmainwindow.cpp b/examples/axes/src/axesmainwindow.cpp
new file mode 100644
index 0000000..47b6219
--- /dev/null
+++ b/examples/axes/src/axesmainwindow.cpp
@@ -0,0 +1,245 @@
+#include <qsplitter.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qaction.h>
+#include <qslider.h>
+#include <qcheckbox.h>
+#include <qmenubar.h>
+#include <qdatetime.h>
+
+#include "axes.h"
+#include "axesmainwindow.h"
+#include "../../../include/qwt3d_function.h"
+
+using namespace std;
+using namespace Qwt3D;
+
+
+// Example function
+class Rosenbrock : public Function
+{
+public:
+
+	Rosenbrock(SurfacePlot& pw)
+	:Function(pw)
+	{
+	}
+
+	double operator()(double x, double y)
+	{
+		return log10((1-x)*(1-x) + 1 * (y - x*x)*(y - x*x));
+	}
+};
+
+
+// Main widget
+
+AxesMainWindow::AxesMainWindow( QWidget* parent)
+	: DummyBase(parent)
+{
+#if QT_VERSION < 0x040000
+	setCaption("axes");
+  QGridLayout *grid = new QGridLayout( frame, 0, 0 );
+#else
+  setupUi(this);
+  QGridLayout *grid = new QGridLayout( frame);
+#endif
+
+  plot = new SurfacePlot(frame);
+  grid->addWidget( plot, 0, 0 );
+
+  plot->setZoom(0.8);
+	plot->setRotation(30,0,15);
+
+	plot->coordinates()->setGridLines(true,true);
+	plot->setCoordinateStyle(BOX);
+	//plot->setCoordinateStyle(NOCOORD);
+	//plot->setPlotStyle(FILLED);
+
+
+	rosenbrock = new Rosenbrock(*plot);
+	
+	rosenbrock->setMesh(31,33);
+	rosenbrock->setDomain(-1.73,1.8,-1.9,1.8);
+	rosenbrock->setMinZ(-100);
+	
+	rosenbrock->create();
+
+	for (unsigned i=0; i!=plot->coordinates()->axes.size(); ++i)
+  {
+    plot->coordinates()->axes[i].setMajors(5);
+    plot->coordinates()->axes[i].setMinors(4);
+    plot->coordinates()->axes[i].setLabelColor(RGBA(0,0,0.4));
+  }
+
+	//plot->setTitle("Rosenbrock");
+	plot->setMeshLineWidth(1);
+	plot->coordinates()->setGridLinesColor(RGBA(0,0,0.5));
+	plot->coordinates()->setLineWidth(1);
+	plot->coordinates()->setNumberColor(RGBA(0,0.5,0));
+	plot->coordinates()->setNumberFont("Courier",10);
+	plot->setTitleFont("Courier",11);
+	plot->coordinates()->setLabelFont("Courier",12, QFont::Bold);
+	plot->coordinates()->axes[X1].setLabelString("X1");
+	plot->coordinates()->axes[Y1].setLabelString("Y1");
+	plot->coordinates()->axes[Z1].setLabelString("Z1");
+	plot->coordinates()->axes[X2].setLabelString("X2");
+	plot->coordinates()->axes[Y2].setLabelString("Y2");
+	plot->coordinates()->axes[Z2].setLabelString("Z2");
+	plot->coordinates()->axes[X3].setLabelString("X3");
+	plot->coordinates()->axes[Y3].setLabelString("Y3");
+	plot->coordinates()->axes[Z3].setLabelString("Z3");
+	plot->coordinates()->axes[X4].setLabelString("X4");
+	plot->coordinates()->axes[Y4].setLabelString("Y4");
+	plot->coordinates()->axes[Z4].setLabelString("Z4");
+  
+  
+  plot->coordinates()->setLineSmooth(true);
+  smoothBox->setDown(true);
+
+#if QT_VERSION < 0x040000
+  Items->insertItem( "&Standard",  this, SLOT(standardItems()), ALT+Key_S );
+  Items->insertItem( "&Imaginary", this, SLOT(complexItems()),    ALT+Key_I );
+  Items->insertItem( "&Letter", this, SLOT(letterItems()),    ALT+Key_L );
+  Items->insertItem( "&Time", this, SLOT(timeItems()),    ALT+Key_T );
+  Items->insertItem( "&Log", this, SLOT(customScale()),    ALT+Key_C );
+#else
+  QMenu* Items = menuBar()->addMenu("Item");
+  Items->addAction( "&Standard",  this, SLOT(standardItems()), QKeySequence("ALT+S") );
+  Items->addAction( "&Imaginary", this, SLOT(complexItems()), QKeySequence("ALT+I") );
+  Items->addAction( "&Letter", this, SLOT(letterItems()), QKeySequence("ALT+L") );
+  Items->addAction( "&Time", this, SLOT(timeItems()), QKeySequence("ALT+T") );
+  Items->addAction( "&Log", this, SLOT(customScale()), QKeySequence("ALT+C") );
+#endif
+  
+  plot->makeCurrent();
+	plot->updateData();
+  plot->updateGL();
+
+	connect(smoothBox, SIGNAL(toggled(bool)), this, SLOT(setSmoothLines(bool)) );	
+	connect(numbergapslider, SIGNAL(valueChanged(int)), this, SLOT(setNumberGap(int)) );
+	connect(labelgapslider, SIGNAL(valueChanged(int)), this, SLOT(setLabelGap(int)) );
+	connect(ticLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(setTicLength(int)) );
+	connect(ticNumberSlider, SIGNAL(valueChanged(int)), this, SLOT(setTicNumber(int)) );
+
+  tics = plot->coordinates()->axes[X1].majors();
+
+  //resetTics();
+
+  customScale();
+
+  plot->setPolygonOffset(10);
+}
+
+AxesMainWindow::~AxesMainWindow()
+{
+	delete rosenbrock;
+}
+
+void AxesMainWindow::setNumberGap(int gap)
+{
+	plot->coordinates()->adjustNumbers(gap);
+  plot->makeCurrent();
+  plot->updateGL();
+}
+
+void AxesMainWindow::setLabelGap(int gap)
+{
+	plot->coordinates()->adjustLabels(gap);
+  plot->makeCurrent();
+  plot->updateGL();
+}
+
+void AxesMainWindow::setSmoothLines(bool val)
+{
+  plot->coordinates()->setLineSmooth(val);
+  plot->updateGL();
+}
+
+void AxesMainWindow::setTicLength(int val)
+{
+  double majl =  (plot->coordinates()->second()-plot->coordinates()->first()).length() / 1000.;
+	majl = majl * val;
+	plot->coordinates()->setTicLength(majl,0.6*majl);
+  plot->updateGL();
+}
+
+void AxesMainWindow::setTicNumber(int degree)
+{
+  plot->coordinates()->axes[X1].setMajors(tics + degree);
+  plot->updateGL();
+}
+
+void AxesMainWindow::resetTics()
+{
+  ticNumberSlider->setEnabled(false);
+	plot->setTitle("");
+  plot->coordinates()->axes[X1].setMajors(5);
+  plot->coordinates()->setAutoScale(true);
+  plot->coordinates()->setStandardScale();
+	plot->coordinates()->axes[Z2].setLabelString("Z4");
+  plot->coordinates()->setGridLines(false,false,Qwt3D::BACK);
+}
+
+void AxesMainWindow::standardItems()
+{  
+  resetTics();
+  plot->updateGL();
+}
+
+void AxesMainWindow::letterItems()
+{  
+  resetTics();
+  ticNumberSlider->setEnabled(true);
+  plot->coordinates()->axes[X1].setAutoScale(false);
+  plot->coordinates()->setStandardScale();
+  plot->coordinates()->axes[X1].setScale(new Letter);
+  plot->coordinates()->axes[X2].setScale(new Letter);
+  plot->coordinates()->axes[X3].setScale(new Letter);
+  plot->coordinates()->axes[X4].setScale(new Letter);
+  plot->coordinates()->axes[Y1].setScale(new Letter(false));
+  plot->coordinates()->axes[Y2].setScale(new Letter(false));
+  plot->coordinates()->axes[Y3].setScale(new Letter(false));
+  plot->coordinates()->axes[Y4].setScale(new Letter(false));
+	plot->setTitle("Use the tics slider for this example!");
+  plot->updateGL();
+}
+
+void AxesMainWindow::complexItems()
+{  
+  resetTics();
+  plot->coordinates()->axes[Y1].setScale(new Imaginary);
+  plot->coordinates()->axes[Y2].setScale(new Imaginary);
+  plot->coordinates()->axes[Y3].setScale(new Imaginary);
+  plot->coordinates()->axes[Y4].setScale(new Imaginary);
+  plot->updateGL();
+}
+
+void AxesMainWindow::timeItems()
+{  
+  resetTics();
+  plot->coordinates()->axes[Z1].setScale(new TimeItems);
+  plot->coordinates()->axes[Z2].setScale(new TimeItems);
+  plot->coordinates()->axes[Z3].setScale(new TimeItems);
+  plot->coordinates()->axes[Z4].setScale(new TimeItems);
+  plot->updateGL();
+}
+
+void AxesMainWindow::customScale()
+{  
+  resetTics();
+  plot->coordinates()->axes[Z1].setScale(LOG10SCALE);
+  plot->coordinates()->axes[Z3].setScale(LOG10SCALE);
+  plot->coordinates()->axes[Z4].setScale(LOG10SCALE);
+	plot->coordinates()->axes[Z2].setLabelString("log10(z)");
+//  plot->coordinates()->axes[Z4].setScale(new LogScale);
+//  plot->coordinates()->axes[Z1].setAutoScale(false);
+//  plot->coordinates()->axes[Z2].setAutoScale(false);
+//  plot->coordinates()->axes[Z3].setAutoScale(false);
+//  plot->coordinates()->axes[Z4].setAutoScale(false);
+  
+  plot->coordinates()->setGridLines(true,true,Qwt3D::BACK);
+
+  plot->updateGL();
+}
+
diff --git a/examples/axes/src/axesmainwindow.h b/examples/axes/src/axesmainwindow.h
new file mode 100644
index 0000000..049dfcb
--- /dev/null
+++ b/examples/axes/src/axesmainwindow.h
@@ -0,0 +1,64 @@
+#include <qmainwindow.h>
+
+#include "qwt3d_surfaceplot.h"
+#include "qwt3d_function.h"
+#include "qwt3d_plot.h"
+
+#if QT_VERSION < 0x040000
+#include "axesmainwindowbase.h"
+#else
+#include "ui_axesmainwindowbase4.h"
+#endif
+
+//MOC_SKIP_BEGIN
+#if QT_VERSION < 0x040000
+  class DummyBase : public AxesMainWindowBase
+  {
+  public:
+    DummyBase(QWidget* parent = 0) 
+      : AxesMainWindowBase(parent) 
+    {
+    } 
+  };
+#else
+  class DummyBase : public QMainWindow, protected Ui::MainWindow
+  {
+  public:
+    DummyBase(QWidget* parent = 0) 
+      : QMainWindow(parent) 
+    {
+    } 
+  };
+#endif
+//MOC_SKIP_END
+
+
+class AxesMainWindow : public DummyBase
+{
+	Q_OBJECT
+
+public:
+	AxesMainWindow( QWidget* parent = 0);
+	~AxesMainWindow();
+	Qwt3D::SurfacePlot* plot;
+	Qwt3D::Function *rosenbrock;
+  void resetTics();
+
+public slots:
+	void setNumberGap(int gap);
+	void setLabelGap(int gap);
+
+  void setSmoothLines(bool);
+  void setTicLength(int val);
+  void setTicNumber(int degree);
+
+  void standardItems();
+  void complexItems();
+  void letterItems();
+  void timeItems();
+  void customScale();
+
+private:
+
+  int tics;
+};
diff --git a/examples/axes/src/axesmainwindowbase.ui b/examples/axes/src/axesmainwindowbase.ui
new file mode 100644
index 0000000..0fd51b5
--- /dev/null
+++ b/examples/axes/src/axesmainwindowbase.ui
@@ -0,0 +1,243 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>AxesMainWindowBase</class>
+<widget class="QMainWindow">
+    <property name="name">
+        <cstring>AxesMainWindowBase</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>826</width>
+            <height>608</height>
+        </rect>
+    </property>
+    <property name="caption">
+        <string>print</string>
+    </property>
+    <grid>
+        <property name="name">
+            <cstring>unnamed</cstring>
+        </property>
+        <property name="margin">
+            <number>11</number>
+        </property>
+        <property name="spacing">
+            <number>6</number>
+        </property>
+        <widget class="QFrame" row="0" column="0">
+            <property name="name">
+                <cstring>frame</cstring>
+            </property>
+            <property name="sizePolicy">
+                <sizepolicy>
+                    <hsizetype>7</hsizetype>
+                    <vsizetype>7</vsizetype>
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                </sizepolicy>
+            </property>
+            <property name="frameShape">
+                <enum>StyledPanel</enum>
+            </property>
+            <property name="frameShadow">
+                <enum>Sunken</enum>
+            </property>
+        </widget>
+        <widget class="QLayoutWidget" row="1" column="0">
+            <property name="name">
+                <cstring>layout11</cstring>
+            </property>
+            <vbox>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>layout9</cstring>
+                    </property>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>TextLabel1_2</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Number gap</string>
+                            </property>
+                        </widget>
+                        <widget class="QSlider">
+                            <property name="name">
+                                <cstring>numbergapslider</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>7</hsizetype>
+                                    <vsizetype>0</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="maxValue">
+                                <number>10</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                            <property name="tickmarks">
+                                <enum>Above</enum>
+                            </property>
+                            <property name="tickInterval">
+                                <number>1</number>
+                            </property>
+                        </widget>
+                    </vbox>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>layout10</cstring>
+                    </property>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>TextLabel1_2_2</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Label gap</string>
+                            </property>
+                        </widget>
+                        <widget class="QSlider">
+                            <property name="name">
+                                <cstring>labelgapslider</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>7</hsizetype>
+                                    <vsizetype>0</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="maxValue">
+                                <number>10</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                            <property name="tickmarks">
+                                <enum>Above</enum>
+                            </property>
+                            <property name="tickInterval">
+                                <number>1</number>
+                            </property>
+                        </widget>
+                    </vbox>
+                </widget>
+            </vbox>
+        </widget>
+        <widget class="QCheckBox" row="1" column="1" rowspan="1" colspan="2">
+            <property name="name">
+                <cstring>smoothBox</cstring>
+            </property>
+            <property name="text">
+                <string>Smooth Lines</string>
+            </property>
+            <property name="checked">
+                <bool>true</bool>
+            </property>
+        </widget>
+        <widget class="QLayoutWidget" row="0" column="1">
+            <property name="name">
+                <cstring>layout11</cstring>
+            </property>
+            <grid>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+                <widget class="QLayoutWidget" row="0" column="2" rowspan="2" colspan="1">
+                    <property name="name">
+                        <cstring>layout9</cstring>
+                    </property>
+                    <grid>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <widget class="QLabel" row="0" column="0" rowspan="1" colspan="3">
+                            <property name="name">
+                                <cstring>ticNumeberLabel</cstring>
+                            </property>
+                            <property name="enabled">
+                                <bool>true</bool>
+                            </property>
+                            <property name="text">
+                                <string>Tics</string>
+                            </property>
+                            <property name="alignment">
+                                <set>AlignCenter</set>
+                            </property>
+                        </widget>
+                        <widget class="QSlider" row="1" column="0">
+                            <property name="name">
+                                <cstring>ticLengthSlider</cstring>
+                            </property>
+                            <property name="maxValue">
+                                <number>100</number>
+                            </property>
+                            <property name="value">
+                                <number>10</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Vertical</enum>
+                            </property>
+                            <property name="tickmarks">
+                                <enum>Below</enum>
+                            </property>
+                            <property name="toolTip" stdset="0">
+                                <string>Tic Length (rel.)</string>
+                            </property>
+                        </widget>
+                        <widget class="QSlider" row="1" column="1">
+                            <property name="name">
+                                <cstring>ticNumberSlider</cstring>
+                            </property>
+                            <property name="enabled">
+                                <bool>false</bool>
+                            </property>
+                            <property name="maxValue">
+                                <number>25</number>
+                            </property>
+                            <property name="value">
+                                <number>0</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Vertical</enum>
+                            </property>
+                            <property name="tickmarks">
+                                <enum>Below</enum>
+                            </property>
+                            <property name="toolTip" stdset="0">
+                                <string>Change Tic Number (available only  for letter example)</string>
+                            </property>
+                        </widget>
+                    </grid>
+                </widget>
+            </grid>
+        </widget>
+    </grid>
+</widget>
+<menubar>
+    <property name="name">
+        <cstring>menubar</cstring>
+    </property>
+    <item text="Items" name="Items">
+    </item>
+</menubar>
+<toolbars>
+</toolbars>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/axes/src/axesmainwindowbase4.ui b/examples/axes/src/axesmainwindowbase4.ui
new file mode 100644
index 0000000..89930bb
--- /dev/null
+++ b/examples/axes/src/axesmainwindowbase4.ui
@@ -0,0 +1,295 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>694</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralWidget" >
+   <layout class="QVBoxLayout" >
+    <property name="margin" >
+     <number>8</number>
+    </property>
+    <property name="spacing" >
+     <number>6</number>
+    </property>
+    <item>
+     <layout class="QHBoxLayout" >
+      <property name="margin" >
+       <number>0</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <widget class="QFrame" name="frame" >
+        <property name="sizePolicy" >
+         <sizepolicy>
+          <hsizetype>7</hsizetype>
+          <vsizetype>7</vsizetype>
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="frameShape" >
+         <enum>QFrame::StyledPanel</enum>
+        </property>
+        <property name="frameShadow" >
+         <enum>QFrame::Sunken</enum>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" >
+        <property name="margin" >
+         <number>0</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="label_4" >
+            <property name="sizePolicy" >
+             <sizepolicy>
+              <hsizetype>0</hsizetype>
+              <vsizetype>0</vsizetype>
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text" >
+             <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Tics</p></body></html></string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeType" >
+             <enum>QSizePolicy::Preferred</enum>
+            </property>
+            <property name="sizeHint" >
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QSlider" name="ticLengthSlider" >
+            <property name="sizePolicy" >
+             <sizepolicy>
+              <hsizetype>0</hsizetype>
+              <vsizetype>7</vsizetype>
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="value" >
+             <number>10</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="invertedAppearance" >
+             <bool>true</bool>
+            </property>
+            <property name="tickPosition" >
+             <enum>QSlider::TicksBelow</enum>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QSlider" name="ticNumberSlider" >
+            <property name="sizePolicy" >
+             <sizepolicy>
+              <hsizetype>0</hsizetype>
+              <vsizetype>7</vsizetype>
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximum" >
+             <number>25</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="invertedAppearance" >
+             <bool>true</bool>
+            </property>
+            <property name="tickPosition" >
+             <enum>QSlider::TicksBelow</enum>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </item>
+    <item>
+     <layout class="QHBoxLayout" >
+      <property name="margin" >
+       <number>0</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <widget class="QWidget" name="widget_2" >
+        <layout class="QVBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <layout class="QVBoxLayout" >
+           <property name="margin" >
+            <number>0</number>
+           </property>
+           <property name="spacing" >
+            <number>6</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="label_2" >
+             <property name="text" >
+              <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Number gap</p></body></html></string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QSlider" name="numbergapslider" >
+             <property name="sizePolicy" >
+              <sizepolicy>
+               <hsizetype>7</hsizetype>
+               <vsizetype>5</vsizetype>
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="maximum" >
+              <number>10</number>
+             </property>
+             <property name="orientation" >
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="tickPosition" >
+              <enum>QSlider::TicksAbove</enum>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item>
+          <layout class="QVBoxLayout" >
+           <property name="margin" >
+            <number>0</number>
+           </property>
+           <property name="spacing" >
+            <number>6</number>
+           </property>
+           <item>
+            <widget class="QLabel" name="label" >
+             <property name="text" >
+              <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Label gap</p></body></html></string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <widget class="QSlider" name="labelgapslider" >
+             <property name="sizePolicy" >
+              <sizepolicy>
+               <hsizetype>7</hsizetype>
+               <vsizetype>5</vsizetype>
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="maximum" >
+              <number>10</number>
+             </property>
+             <property name="orientation" >
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="tickPosition" >
+              <enum>QSlider::TicksAbove</enum>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QCheckBox" name="smoothBox" >
+        <property name="sizePolicy" >
+         <sizepolicy>
+          <hsizetype>1</hsizetype>
+          <vsizetype>5</vsizetype>
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text" >
+         <string>Smooth Lines</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </item>
+   </layout>
+   <widget class="QWidget" name="widget" >
+    <property name="geometry" >
+     <rect>
+      <x>590</x>
+      <y>10</y>
+      <width>61</width>
+      <height>421</height>
+     </rect>
+    </property>
+   </widget>
+  </widget>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/axes/src/main.cpp b/examples/axes/src/main.cpp
new file mode 100644
index 0000000..f9d16c4
--- /dev/null
+++ b/examples/axes/src/main.cpp
@@ -0,0 +1,31 @@
+/********************************************************************
+    created:   2003/09/10
+    filename:  main.cpp
+	
+    author:    Micha Bieber	
+*********************************************************************/
+
+#include <qapplication.h>
+#include "axesmainwindow.h"
+
+
+int main( int argc, char** argv )
+{
+	QApplication app( argc, argv );
+	
+  if ( !QGLFormat::hasOpenGL() ) 
+	{
+		qWarning( "This system has no OpenGL support. Exiting." );     
+		return -1;
+  }
+
+	AxesMainWindow mainwindow;
+	
+#if QT_VERSION < 0x040000
+  app.setMainWidget(&mainwindow);
+#endif
+
+	mainwindow.show();
+
+	return app.exec();
+}
diff --git a/examples/box.png b/examples/box.png
new file mode 100644
index 0000000..1aa8c08
Binary files /dev/null and b/examples/box.png differ
diff --git a/examples/common.pro b/examples/common.pro
new file mode 100644
index 0000000..1f93321
--- /dev/null
+++ b/examples/common.pro
@@ -0,0 +1,37 @@
+TEMPLATE     = app
+CONFIG      += qt warn_on thread debug
+UI_DIR = tmp
+MOC_DIR      = tmp
+OBJECTS_DIR  = tmp
+INCLUDEPATH    += ../../include 
+DEPENDPATH	= $$INCLUDEPATH
+DESTDIR = ../bin
+
+unix:LIBS += -lqwtplot3d -L../../lib
+linux-g++:QMAKE_CXXFLAGS += -fno-exceptions
+
+win32{
+  LIBS += ../../lib/qwtplot3d.lib
+  TEMPLATE  = vcapp
+  DEFINES  += QT_DLL QWT3D_DLL
+  RC_FILE = ../icon.rc
+  contains (CONFIG, debug)  {
+    QMAKE_LFLAGS += /NODEFAULTLIB:msvcrt
+    DESTDIR = ../bin/debug
+  }
+  !contains (CONFIG, release)  {
+    DESTDIR = ../bin/release
+  }
+}
+
+MYVERSION = $$[QMAKE_VERSION] 
+ISQT4 = $$find(MYVERSION, ^[2-9])
+
+!isEmpty( ISQT4 ) {
+RESOURCES     = ../images.qrc
+QT += opengl
+}
+
+isEmpty( ISQT4 ) {
+CONFIG += opengl
+}
diff --git a/examples/dsp.bat b/examples/dsp.bat
new file mode 100644
index 0000000..20b1e1f
--- /dev/null
+++ b/examples/dsp.bat
@@ -0,0 +1,12 @@
+REM set QMAKESPEC=win32-msvc.net
+cd mesh2
+qmake mesh2.pro
+cd ../simpleplot
+qmake simpleplot.pro
+cd ../autoswitch
+qmake autoswitch.pro
+cd ../enrichments
+qmake enrichments.pro
+cd ../axes
+qmake axes.pro
+cd ..
\ No newline at end of file
diff --git a/examples/enrichments/enrichments.pro b/examples/enrichments/enrichments.pro
new file mode 100644
index 0000000..b25b8ae
--- /dev/null
+++ b/examples/enrichments/enrichments.pro
@@ -0,0 +1,16 @@
+include( ../common.pro )
+
+SOURCES =  src/main.cpp \
+		       src/enrichmentmainwindow.cpp \
+		       src/enrichments.cpp 
+
+HEADERS =  src/enrichmentmainwindow.h \
+					 src/enrichments.h 
+	 
+!isEmpty( ISQT4 ) {
+  FORMS =  src/enrichmentmainwindowbase4.ui
+}
+isEmpty( ISQT4 ) {
+  FORMS =  src/enrichmentmainwindowbase.ui
+}
+
diff --git a/examples/enrichments/src/enrichmentmainwindow.cpp b/examples/enrichments/src/enrichmentmainwindow.cpp
new file mode 100644
index 0000000..3c74edc
--- /dev/null
+++ b/examples/enrichments/src/enrichmentmainwindow.cpp
@@ -0,0 +1,147 @@
+#include <qlayout.h>
+#include <qslider.h>
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+
+
+#include "enrichmentmainwindow.h"
+#include "enrichments.h"
+#include "../../../include/qwt3d_function.h"
+
+using namespace Qwt3D;
+
+
+class Hat : public Function
+{
+public:
+
+	Hat(SurfacePlot& pw)
+	:Function(pw)
+	{
+	}
+	
+	double operator()(double x, double y)
+	{
+    double ret = 1.0 / (x*x+y*y+0.5);
+    return ret;
+	}
+	QString name() const {return "$\\frac{1}{x^2+y^2+\\frac{1}{2}}$";}
+};
+
+Hat* hat;
+
+EnrichmentMainWindow::EnrichmentMainWindow( QWidget* parent )
+	: DummyBase( parent )
+{
+#if QT_VERSION < 0x040000
+	setCaption("enrichment");
+  QGridLayout *grid = new QGridLayout( frame, 0, 0 );
+#else
+  setupUi(this);
+  QGridLayout *grid = new QGridLayout( frame);
+#endif
+
+  plot = new SurfacePlot(frame);
+  grid->addWidget( plot, 0, 0 );
+
+  plot->setTitle("Bar Style (Vertex Enrichment)");
+  plot->setTitleFont("Arial",12);
+
+	plot->setZoom(0.8);
+	plot->setRotation(30,0,15);
+
+	plot->setCoordinateStyle(BOX);
+  bar = (Bar*)plot->setPlotStyle(Bar(0.007,0.5));
+
+  hat = new Hat(*plot);
+	
+	hat->setMesh(23,21);
+	hat->setDomain(-1.8,1.7,-1.6,1.7);	
+
+	hat->create();
+
+	for (unsigned i=0; i!=plot->coordinates()->axes.size(); ++i)
+  {
+    plot->coordinates()->axes[i].setMajors(5);
+    plot->coordinates()->axes[i].setMinors(4);
+  }
+
+
+	//plot->setMeshLineWidth(1);
+	plot->coordinates()->setGridLinesColor(RGBA(0,0,0.5));
+	plot->coordinates()->setLineWidth(1);
+	plot->coordinates()->setNumberFont("Courier",8);
+  plot->coordinates()->adjustNumbers(5);
+ 
+	setColor();
+  plot->updateData();
+  plot->updateGL();
+
+
+  levelSlider->setValue(50);
+	level_ = 0.5;
+  width_ = 0.007;
+  connect( levelSlider, SIGNAL(valueChanged(int)), this, SLOT(setLevel(int)) );
+
+  //connect( barBtn, SIGNAL(clicked()), this, SLOT(barSlot()) );
+  //connect( sliceBtn, SIGNAL(clicked()), this, SLOT(sliceSlot()) );
+
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glDisable(GL_LINE_SMOOTH);
+}
+
+EnrichmentMainWindow::~EnrichmentMainWindow()
+{
+	delete hat;
+}
+
+
+void EnrichmentMainWindow::setColor()
+{	
+  Qwt3D::ColorVector cv;
+	
+	RGBA rgb;
+	int i = 252;
+	int step = 4;
+
+  while (i>=0)
+  {    
+    rgb.r = i/255.; rgb.g=(i-60>0) ? (i-60)/255.:0;rgb.b=0;
+  //  rgb.a = 0.2;
+    cv.push_back(rgb);	
+    if (!--step) 
+    {
+      i-=4;
+      step=4;
+    }
+  }
+	StandardColor* col = new StandardColor(plot);
+	col->setColorVector(cv);
+	
+	plot->setDataColor(col);
+}
+
+
+void EnrichmentMainWindow::setLevel(int i)
+{
+  level_ = 1 - i / 100.;
+  bar->configure(width_,level_);
+  plot->updateData();
+  plot->updateGL();
+}
+
+void EnrichmentMainWindow::setWidth(int i)
+{
+  width_ = i / 20000.;
+  bar->configure(width_,level_);
+  plot->updateData();
+  plot->updateGL();
+}
+
+void EnrichmentMainWindow::barSlot()
+{  
+  Bar b(width_,level_); 
+  bar = (Bar*)plot->setPlotStyle(b);
+  plot->updateData();
+  plot->updateGL();
+}
diff --git a/examples/enrichments/src/enrichmentmainwindow.h b/examples/enrichments/src/enrichmentmainwindow.h
new file mode 100644
index 0000000..218df93
--- /dev/null
+++ b/examples/enrichments/src/enrichmentmainwindow.h
@@ -0,0 +1,57 @@
+#include "qwt3d_surfaceplot.h"
+#include "qwt3d_function.h"
+#include "qwt3d_plot.h"
+#include "enrichments.h"
+
+
+#if QT_VERSION < 0x040000
+#include "enrichmentmainwindowbase.h"
+#else
+#include "ui_enrichmentmainwindowbase4.h"
+#endif
+
+//MOC_SKIP_BEGIN
+#if QT_VERSION < 0x040000
+  class DummyBase : public EnrichmentMainWindowBase
+  {
+  public:
+    DummyBase(QWidget* parent = 0) 
+      : EnrichmentMainWindowBase(parent) 
+    {
+    } 
+  };
+#else
+  class DummyBase : public QMainWindow, protected Ui::MainWindow
+  {
+  public:
+    DummyBase(QWidget* parent = 0) 
+      : QMainWindow(parent) 
+    {
+    } 
+  };
+#endif
+//MOC_SKIP_END
+
+
+class EnrichmentMainWindow : public DummyBase
+{
+	Q_OBJECT
+
+public:
+	EnrichmentMainWindow( QWidget* parent = 0 );
+	~EnrichmentMainWindow();
+  void setColor();
+  Bar *bar;
+  Qwt3D::SurfacePlot* plot;
+
+public slots:
+  void setLevel(int);
+  void setWidth(int);
+  void barSlot();
+ 
+private:
+  double level_, width_;
+  
+};
+
+
diff --git a/examples/enrichments/src/enrichmentmainwindowbase.ui b/examples/enrichments/src/enrichmentmainwindowbase.ui
new file mode 100644
index 0000000..f8f1037
--- /dev/null
+++ b/examples/enrichments/src/enrichmentmainwindowbase.ui
@@ -0,0 +1,215 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>EnrichmentMainWindowBase</class>
+<widget class="QMainWindow">
+    <property name="name">
+        <cstring>EnrichmentMainWindowBase</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>843</width>
+            <height>702</height>
+        </rect>
+    </property>
+    <property name="caption">
+        <string>print</string>
+    </property>
+    <grid>
+        <property name="name">
+            <cstring>unnamed</cstring>
+        </property>
+        <property name="margin">
+            <number>11</number>
+        </property>
+        <property name="spacing">
+            <number>6</number>
+        </property>
+        <widget class="QLayoutWidget" row="1" column="0">
+            <property name="name">
+                <cstring>Layout11</cstring>
+            </property>
+            <grid>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+                <property name="margin">
+                    <number>0</number>
+                </property>
+                <property name="spacing">
+                    <number>6</number>
+                </property>
+                <widget class="QLayoutWidget" row="0" column="0">
+                    <property name="name">
+                        <cstring>Layout10</cstring>
+                    </property>
+                    <grid>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <property name="margin">
+                            <number>0</number>
+                        </property>
+                        <property name="spacing">
+                            <number>6</number>
+                        </property>
+                        <widget class="QLabel" row="0" column="0">
+                            <property name="name">
+                                <cstring>TextLabel1_2</cstring>
+                            </property>
+                            <property name="enabled">
+                                <bool>false</bool>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>5</hsizetype>
+                                    <vsizetype>0</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="text">
+                                <string>Width</string>
+                            </property>
+                        </widget>
+                        <widget class="QSlider" row="0" column="1">
+                            <property name="name">
+                                <cstring>widthSlider</cstring>
+                            </property>
+                            <property name="enabled">
+                                <bool>false</bool>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>7</hsizetype>
+                                    <vsizetype>0</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="minimumSize">
+                                <size>
+                                    <width>0</width>
+                                    <height>40</height>
+                                </size>
+                            </property>
+                            <property name="minValue">
+                                <number>10</number>
+                            </property>
+                            <property name="maxValue">
+                                <number>200</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                            <property name="tickmarks">
+                                <enum>Below</enum>
+                            </property>
+                            <property name="tickInterval">
+                                <number>10</number>
+                            </property>
+                            <property name="toolTip" stdset="0">
+                                <string>Relative psition of slicing plane</string>
+                            </property>
+                        </widget>
+                    </grid>
+                </widget>
+                <widget class="QLayoutWidget" row="0" column="1">
+                    <property name="name">
+                        <cstring>Layout9</cstring>
+                    </property>
+                    <grid>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <property name="margin">
+                            <number>0</number>
+                        </property>
+                        <property name="spacing">
+                            <number>6</number>
+                        </property>
+                    </grid>
+                </widget>
+            </grid>
+        </widget>
+        <widget class="QLayoutWidget" row="0" column="1" rowspan="2" colspan="1">
+            <property name="name">
+                <cstring>Layout8</cstring>
+            </property>
+            <grid>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+                <property name="margin">
+                    <number>0</number>
+                </property>
+                <property name="spacing">
+                    <number>6</number>
+                </property>
+                <widget class="QSlider" row="1" column="0">
+                    <property name="name">
+                        <cstring>levelSlider</cstring>
+                    </property>
+                    <property name="enabled">
+                        <bool>true</bool>
+                    </property>
+                    <property name="minimumSize">
+                        <size>
+                            <width>40</width>
+                            <height>0</height>
+                        </size>
+                    </property>
+                    <property name="maxValue">
+                        <number>100</number>
+                    </property>
+                    <property name="value">
+                        <number>10</number>
+                    </property>
+                    <property name="orientation">
+                        <enum>Vertical</enum>
+                    </property>
+                    <property name="tickmarks">
+                        <enum>Below</enum>
+                    </property>
+                    <property name="tickInterval">
+                        <number>10</number>
+                    </property>
+                    <property name="toolTip" stdset="0">
+                        <string>Changes the level, where marker are shown</string>
+                    </property>
+                </widget>
+                <widget class="QLabel" row="0" column="0">
+                    <property name="name">
+                        <cstring>TextLabel1</cstring>
+                    </property>
+                    <property name="text">
+                        <string>Level</string>
+                    </property>
+                    <property name="alignment">
+                        <set>AlignCenter</set>
+                    </property>
+                </widget>
+            </grid>
+        </widget>
+        <widget class="QFrame" row="0" column="0">
+            <property name="name">
+                <cstring>frame</cstring>
+            </property>
+            <property name="frameShape">
+                <enum>StyledPanel</enum>
+            </property>
+            <property name="frameShadow">
+                <enum>Sunken</enum>
+            </property>
+        </widget>
+    </grid>
+</widget>
+<menubar>
+    <property name="name">
+        <cstring>menubar</cstring>
+    </property>
+</menubar>
+<toolbars>
+</toolbars>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/enrichments/src/enrichmentmainwindowbase4.ui b/examples/enrichments/src/enrichmentmainwindowbase4.ui
new file mode 100644
index 0000000..e5f4c80
--- /dev/null
+++ b/examples/enrichments/src/enrichmentmainwindowbase4.ui
@@ -0,0 +1,167 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>800</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralWidget" >
+   <layout class="QGridLayout" >
+    <property name="margin" >
+     <number>8</number>
+    </property>
+    <property name="spacing" >
+     <number>6</number>
+    </property>
+    <item row="0" column="0" >
+     <layout class="QVBoxLayout" >
+      <property name="margin" >
+       <number>0</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <layout class="QHBoxLayout" >
+        <property name="margin" >
+         <number>0</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <widget class="QFrame" name="frame" >
+          <property name="frameShape" >
+           <enum>QFrame::StyledPanel</enum>
+          </property>
+          <property name="frameShadow" >
+           <enum>QFrame::Sunken</enum>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <layout class="QVBoxLayout" >
+          <property name="margin" >
+           <number>0</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="label" >
+            <property name="sizePolicy" >
+             <sizepolicy>
+              <hsizetype>5</hsizetype>
+              <vsizetype>0</vsizetype>
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text" >
+             <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Level</p></body></html></string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QSlider" name="levelSlider" >
+            <property name="sizePolicy" >
+             <sizepolicy>
+              <hsizetype>0</hsizetype>
+              <vsizetype>7</vsizetype>
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="value" >
+             <number>10</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="invertedAppearance" >
+             <bool>true</bool>
+            </property>
+            <property name="tickPosition" >
+             <enum>QSlider::TicksBelow</enum>
+            </property>
+            <property name="tickInterval" >
+             <number>10</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" >
+        <property name="margin" >
+         <number>0</number>
+        </property>
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <item>
+         <widget class="QLabel" name="label_2" >
+          <property name="enabled" >
+           <bool>false</bool>
+          </property>
+          <property name="sizePolicy" >
+           <sizepolicy>
+            <hsizetype>0</hsizetype>
+            <vsizetype>0</vsizetype>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="text" >
+           <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Width</p></body></html></string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSlider" name="widthSlider" >
+          <property name="enabled" >
+           <bool>false</bool>
+          </property>
+          <property name="minimum" >
+           <number>2</number>
+          </property>
+          <property name="maximum" >
+           <number>200</number>
+          </property>
+          <property name="value" >
+           <number>20</number>
+          </property>
+          <property name="orientation" >
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="tickPosition" >
+           <enum>QSlider::TicksBelow</enum>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/enrichments/src/enrichments.cpp b/examples/enrichments/src/enrichments.cpp
new file mode 100644
index 0000000..f013e70
--- /dev/null
+++ b/examples/enrichments/src/enrichments.cpp
@@ -0,0 +1,150 @@
+#include "qbitmap.h"
+
+#include "qwt3d_color.h"
+#include "qwt3d_plot.h"
+#include "enrichments.h"
+
+using namespace Qwt3D;
+
+
+/////////////////////////////////////////////////////////////////
+//
+//   Bar
+//
+/////////////////////////////////////////////////////////////////
+
+Bar::Bar()
+{
+  configure(0, 1);
+}
+
+Bar::Bar(double rad, double level)
+{
+  configure(rad, level);
+}
+
+void Bar::configure(double rad, double level)
+{
+  plot = 0;
+  radius_ = rad;
+  level_ = level;
+}
+
+void Bar::drawBegin()
+{  
+  diag_ = (plot->hull().maxVertex-plot->hull().minVertex).length() * radius_;
+  glLineWidth( 0 );
+  glEnable(GL_POLYGON_OFFSET_FILL);
+  glPolygonOffset(1,1);
+}
+
+void Bar::drawEnd()
+{
+}
+
+void Bar::draw(Qwt3D::Triple const& pos)
+{
+  
+//	GLStateBewarer sb(GL_LINE_SMOOTH, true);
+//  sb.turnOn();
+
+  double interval = plot->hull().maxVertex.z-plot->hull().minVertex.z;
+  double numlevel = plot->hull().minVertex.z + level_ * interval;
+  interval /=100;
+  if (pos.z > numlevel - interval && pos.z < numlevel + interval )
+  {
+    Label3D lb;
+    lb.draw(pos, diag_, diag_ * 2);
+  }
+  
+  GLdouble minz = plot->hull().minVertex.z;
+
+  RGBA rgbat = (*plot->dataColor())(pos);
+	RGBA rgbab = (*plot->dataColor())(pos.x, pos.y, minz);
+	
+  glBegin(GL_QUADS);
+    glColor4d(rgbab.r,rgbab.g,rgbab.b,rgbab.a);
+    glVertex3d(pos.x-diag_,pos.y-diag_,minz);
+    glVertex3d(pos.x+diag_,pos.y-diag_,minz);
+    glVertex3d(pos.x+diag_,pos.y+diag_,minz);
+    glVertex3d(pos.x-diag_,pos.y+diag_,minz);
+
+    if (pos.z > numlevel - interval && pos.z < numlevel + interval )
+      glColor3d(0.7,0,0);
+    else
+      glColor4d(rgbat.r,rgbat.g,rgbat.b,rgbat.a);
+    glVertex3d(pos.x-diag_,pos.y-diag_,pos.z);
+    glVertex3d(pos.x+diag_,pos.y-diag_,pos.z);
+    glVertex3d(pos.x+diag_,pos.y+diag_,pos.z);
+    glVertex3d(pos.x-diag_,pos.y+diag_,pos.z);
+
+    glColor4d(rgbab.r,rgbab.g,rgbat.b,rgbab.a);
+    glVertex3d(pos.x-diag_,pos.y-diag_,minz);
+    glVertex3d(pos.x+diag_,pos.y-diag_,minz);
+    glColor4d(rgbat.r,rgbat.g,rgbat.b,rgbat.a);
+    glVertex3d(pos.x+diag_,pos.y-diag_,pos.z);
+    glVertex3d(pos.x-diag_,pos.y-diag_,pos.z);
+
+    glColor4d(rgbab.r,rgbab.g,rgbat.b,rgbab.a);
+    glVertex3d(pos.x-diag_,pos.y+diag_,minz);
+    glVertex3d(pos.x+diag_,pos.y+diag_,minz);
+    glColor4d(rgbat.r,rgbat.g,rgbat.b,rgbat.a);
+    glVertex3d(pos.x+diag_,pos.y+diag_,pos.z);
+    glVertex3d(pos.x-diag_,pos.y+diag_,pos.z);
+
+    glColor4d(rgbab.r,rgbab.g,rgbat.b,rgbab.a);
+    glVertex3d(pos.x-diag_,pos.y-diag_,minz);
+    glVertex3d(pos.x-diag_,pos.y+diag_,minz);
+    glColor4d(rgbat.r,rgbat.g,rgbat.b,rgbat.a);
+    glVertex3d(pos.x-diag_,pos.y+diag_,pos.z);
+    glVertex3d(pos.x-diag_,pos.y-diag_,pos.z);
+
+    glColor4d(rgbab.r,rgbab.g,rgbat.b,rgbab.a);
+    glVertex3d(pos.x+diag_,pos.y-diag_,minz);
+    glVertex3d(pos.x+diag_,pos.y+diag_,minz);
+    glColor4d(rgbat.r,rgbat.g,rgbat.b,rgbat.a);
+    glVertex3d(pos.x+diag_,pos.y+diag_,pos.z);
+    glVertex3d(pos.x+diag_,pos.y-diag_,pos.z);
+  glEnd();
+
+    glColor3d(0,0,0);
+  glBegin(GL_LINES);
+    glVertex3d(pos.x-diag_,pos.y-diag_,minz); glVertex3d(pos.x+diag_,pos.y-diag_,minz);
+    glVertex3d(pos.x-diag_,pos.y-diag_,pos.z); glVertex3d(pos.x+diag_,pos.y-diag_,pos.z);
+    glVertex3d(pos.x-diag_,pos.y+diag_,pos.z); glVertex3d(pos.x+diag_,pos.y+diag_,pos.z);
+    glVertex3d(pos.x-diag_,pos.y+diag_,minz); glVertex3d(pos.x+diag_,pos.y+diag_,minz);
+
+    glVertex3d(pos.x-diag_,pos.y-diag_,minz); glVertex3d(pos.x-diag_,pos.y+diag_,minz);
+    glVertex3d(pos.x+diag_,pos.y-diag_,minz); glVertex3d(pos.x+diag_,pos.y+diag_,minz);
+    glVertex3d(pos.x+diag_,pos.y-diag_,pos.z); glVertex3d(pos.x+diag_,pos.y+diag_,pos.z);
+    glVertex3d(pos.x-diag_,pos.y-diag_,pos.z); glVertex3d(pos.x-diag_,pos.y+diag_,pos.z);
+
+    glVertex3d(pos.x-diag_,pos.y-diag_,minz); glVertex3d(pos.x-diag_,pos.y-diag_,pos.z);
+    glVertex3d(pos.x+diag_,pos.y-diag_,minz); glVertex3d(pos.x+diag_,pos.y-diag_,pos.z);
+    glVertex3d(pos.x+diag_,pos.y+diag_,minz); glVertex3d(pos.x+diag_,pos.y+diag_,pos.z);
+    glVertex3d(pos.x-diag_,pos.y+diag_,minz); glVertex3d(pos.x-diag_,pos.y+diag_,pos.z);
+  glEnd();
+}
+
+void Label3D::draw(Qwt3D::Triple const& pos, double w, double h)
+{
+  double gap = 0.3;
+  glColor3d(1,1,1);
+  glBegin(GL_QUADS);
+    glVertex3d(pos.x-w,pos.y,pos.z + gap);
+    glVertex3d(pos.x+w,pos.y,pos.z + gap);
+    glVertex3d(pos.x+w,pos.y,pos.z + gap + h);
+    glVertex3d(pos.x-w,pos.y,pos.z + gap + h);
+  glEnd();
+  glColor3d(0.4,0,0);
+  glBegin(GL_LINE_LOOP);
+    glVertex3d(pos.x-w,pos.y,pos.z + gap);
+    glVertex3d(pos.x+w,pos.y,pos.z + gap);
+    glVertex3d(pos.x+w,pos.y,pos.z + gap + h);
+    glVertex3d(pos.x-w,pos.y,pos.z + gap + h);
+  glEnd();
+  glBegin(GL_LINES);
+    glVertex3d(pos.x,pos.y,pos.z);
+    glVertex3d(pos.x,pos.y,pos.z + gap);
+  glEnd();
+}
diff --git a/examples/enrichments/src/enrichments.h b/examples/enrichments/src/enrichments.h
new file mode 100644
index 0000000..36bed76
--- /dev/null
+++ b/examples/enrichments/src/enrichments.h
@@ -0,0 +1,31 @@
+#ifndef enrichments_h__2004_02_25_13_58_begin_guarded_code
+#define enrichments_h__2004_02_25_13_58_begin_guarded_code
+
+#include "qwt3d_plot.h"
+
+
+class Bar : public Qwt3D::VertexEnrichment
+{
+public:
+  Bar();
+  Bar(double rad, double level);
+
+  Qwt3D::Enrichment* clone() const {return new Bar(*this);}
+  
+  void configure(double rad, double level);
+  void drawBegin();
+  void drawEnd();
+  void draw(Qwt3D::Triple const&);
+
+private:
+  double level_, radius_;
+  double diag_;
+};
+
+class  Label3D
+{
+public:
+  void draw(Qwt3D::Triple const&, double w, double h);
+};
+
+#endif
diff --git a/examples/enrichments/src/main.cpp b/examples/enrichments/src/main.cpp
new file mode 100644
index 0000000..4ed08b6
--- /dev/null
+++ b/examples/enrichments/src/main.cpp
@@ -0,0 +1,30 @@
+/********************************************************************
+    created:   2003/09/10
+    filename:  main.cpp
+	
+    author:    Micha Bieber	
+*********************************************************************/
+
+#include <qapplication.h>
+#include "enrichmentmainwindow.h"
+
+int main( int argc, char** argv )
+{
+	QApplication app( argc, argv );
+	
+  if ( !QGLFormat::hasOpenGL() ) 
+	{
+		qWarning( "This system has no OpenGL support. Exiting." );     
+		return -1;
+  }
+
+	EnrichmentMainWindow mainwindow;
+	
+#if QT_VERSION < 0x040000
+  app.setMainWidget(&mainwindow);
+#endif
+
+	mainwindow.show();
+
+	return app.exec();
+}
diff --git a/examples/examples.pro b/examples/examples.pro
new file mode 100644
index 0000000..d5957da
--- /dev/null
+++ b/examples/examples.pro
@@ -0,0 +1,10 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+	simpleplot \
+	autoswitch \
+	enrichments \
+	axes \
+	mesh2
+	
+
+	
diff --git a/examples/examples.sln b/examples/examples.sln
new file mode 100644
index 0000000..68980b6
--- /dev/null
+++ b/examples/examples.sln
@@ -0,0 +1,43 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "autoswitch", "autoswitch\autoswitch.vcproj", "{C925FD16-FB8D-3C0C-A955-78E37532F05B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "axes", "axes\axes.vcproj", "{9DBB316E-B662-37E5-81FA-F07D1AD5DBF3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "enrichments", "enrichments\enrichments.vcproj", "{DE9FA224-88EA-3A55-B709-A679DE8B943D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mesh2", "mesh2\mesh2.vcproj", "{8001AE3F-B159-3472-A7B5-E866065C22AE}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qwtplot3d", "..\qwtplot3d.vcproj", "{FCF9D3F3-79A6-3A08-92BE-6DAE29ADC6A5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simpleplot", "simpleplot\simpleplot.vcproj", "{A81FCC17-CCAB-3CEC-9A30-C8F9EDD6F0D3}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{C925FD16-FB8D-3C0C-A955-78E37532F05B}.Debug|Win32.ActiveCfg = Debug|Win32
+		{C925FD16-FB8D-3C0C-A955-78E37532F05B}.Debug|Win32.Build.0 = Debug|Win32
+		{C925FD16-FB8D-3C0C-A955-78E37532F05B}.Release|Win32.ActiveCfg = Release|Win32
+		{9DBB316E-B662-37E5-81FA-F07D1AD5DBF3}.Debug|Win32.ActiveCfg = Debug|Win32
+		{9DBB316E-B662-37E5-81FA-F07D1AD5DBF3}.Debug|Win32.Build.0 = Debug|Win32
+		{9DBB316E-B662-37E5-81FA-F07D1AD5DBF3}.Release|Win32.ActiveCfg = Release|Win32
+		{DE9FA224-88EA-3A55-B709-A679DE8B943D}.Debug|Win32.ActiveCfg = Debug|Win32
+		{DE9FA224-88EA-3A55-B709-A679DE8B943D}.Debug|Win32.Build.0 = Debug|Win32
+		{DE9FA224-88EA-3A55-B709-A679DE8B943D}.Release|Win32.ActiveCfg = Release|Win32
+		{8001AE3F-B159-3472-A7B5-E866065C22AE}.Debug|Win32.ActiveCfg = Debug|Win32
+		{8001AE3F-B159-3472-A7B5-E866065C22AE}.Debug|Win32.Build.0 = Debug|Win32
+		{8001AE3F-B159-3472-A7B5-E866065C22AE}.Release|Win32.ActiveCfg = Release|Win32
+		{FCF9D3F3-79A6-3A08-92BE-6DAE29ADC6A5}.Debug|Win32.ActiveCfg = Debug|Win32
+		{FCF9D3F3-79A6-3A08-92BE-6DAE29ADC6A5}.Debug|Win32.Build.0 = Debug|Win32
+		{FCF9D3F3-79A6-3A08-92BE-6DAE29ADC6A5}.Release|Win32.ActiveCfg = Release|Win32
+		{A81FCC17-CCAB-3CEC-9A30-C8F9EDD6F0D3}.Debug|Win32.ActiveCfg = Debug|Win32
+		{A81FCC17-CCAB-3CEC-9A30-C8F9EDD6F0D3}.Debug|Win32.Build.0 = Debug|Win32
+		{A81FCC17-CCAB-3CEC-9A30-C8F9EDD6F0D3}.Release|Win32.ActiveCfg = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/examples/filecell.png b/examples/filecell.png
new file mode 100644
index 0000000..c2da1fe
Binary files /dev/null and b/examples/filecell.png differ
diff --git a/examples/fileopen.png b/examples/fileopen.png
new file mode 100644
index 0000000..85dab43
Binary files /dev/null and b/examples/fileopen.png differ
diff --git a/examples/filledmesh.png b/examples/filledmesh.png
new file mode 100644
index 0000000..45f0ebd
Binary files /dev/null and b/examples/filledmesh.png differ
diff --git a/examples/floordata.png b/examples/floordata.png
new file mode 100644
index 0000000..e577276
Binary files /dev/null and b/examples/floordata.png differ
diff --git a/examples/floorempty.png b/examples/floorempty.png
new file mode 100644
index 0000000..83d5fd7
Binary files /dev/null and b/examples/floorempty.png differ
diff --git a/examples/flooriso.png b/examples/flooriso.png
new file mode 100644
index 0000000..b3b03fd
Binary files /dev/null and b/examples/flooriso.png differ
diff --git a/examples/floormesh.png b/examples/floormesh.png
new file mode 100644
index 0000000..51e7125
Binary files /dev/null and b/examples/floormesh.png differ
diff --git a/examples/frame.png b/examples/frame.png
new file mode 100644
index 0000000..9d1a388
Binary files /dev/null and b/examples/frame.png differ
diff --git a/examples/grid.png b/examples/grid.png
new file mode 100644
index 0000000..0745d21
Binary files /dev/null and b/examples/grid.png differ
diff --git a/examples/gridb.png b/examples/gridb.png
new file mode 100644
index 0000000..658df52
Binary files /dev/null and b/examples/gridb.png differ
diff --git a/examples/gridc.png b/examples/gridc.png
new file mode 100644
index 0000000..37330a3
Binary files /dev/null and b/examples/gridc.png differ
diff --git a/examples/gridf.png b/examples/gridf.png
new file mode 100644
index 0000000..f4066e0
Binary files /dev/null and b/examples/gridf.png differ
diff --git a/examples/gridfr.png b/examples/gridfr.png
new file mode 100644
index 0000000..c8e8e47
Binary files /dev/null and b/examples/gridfr.png differ
diff --git a/examples/gridl.png b/examples/gridl.png
new file mode 100644
index 0000000..02a6a01
Binary files /dev/null and b/examples/gridl.png differ
diff --git a/examples/gridr.png b/examples/gridr.png
new file mode 100644
index 0000000..addaebc
Binary files /dev/null and b/examples/gridr.png differ
diff --git a/examples/hiddenline.png b/examples/hiddenline.png
new file mode 100644
index 0000000..cb9ea63
Binary files /dev/null and b/examples/hiddenline.png differ
diff --git a/examples/icon.gif b/examples/icon.gif
new file mode 100644
index 0000000..f59b1ab
Binary files /dev/null and b/examples/icon.gif differ
diff --git a/examples/icon.ico b/examples/icon.ico
new file mode 100644
index 0000000..f9f5da1
Binary files /dev/null and b/examples/icon.ico differ
diff --git a/examples/icon.png b/examples/icon.png
new file mode 100644
index 0000000..c30a5d7
Binary files /dev/null and b/examples/icon.png differ
diff --git a/examples/icon.rc b/examples/icon.rc
new file mode 100644
index 0000000..bb10963
--- /dev/null
+++ b/examples/icon.rc
@@ -0,0 +1 @@
+IDI_ICON1               ICON    DISCARDABLE     "icon.ico"
\ No newline at end of file
diff --git a/examples/images.qrc b/examples/images.qrc
new file mode 100644
index 0000000..d7e24d9
--- /dev/null
+++ b/examples/images.qrc
@@ -0,0 +1,31 @@
+<RCC>
+    <qresource prefix="/images" >
+        <file>box.png</file>
+        <file>filecell.png</file>
+        <file>fileopen.png</file>
+        <file>filledmesh.png</file>
+        <file>floordata.png</file>
+        <file>floorempty.png</file>
+        <file>flooriso.png</file>
+        <file>floormesh.png</file>
+        <file>frame.png</file>
+        <file>grid.png</file>
+        <file>gridb.png</file>
+        <file>gridc.png</file>
+        <file>gridf.png</file>
+        <file>gridfr.png</file>
+        <file>gridl.png</file>
+        <file>gridr.png</file>
+        <file>hiddenline.png</file>
+        <file>icon.png</file>
+        <file>movie.png</file>
+        <file>nodata.png</file>
+        <file>none.png</file>
+        <file>normals.png</file>
+        <file>polygon.png</file>
+        <file>qwtplot.png</file>
+        <file>savecontent.png</file>
+        <file>scattered.png</file>
+        <file>wireframe.png</file>
+    </qresource>
+</RCC>
diff --git a/examples/mesh2/mesh2.pro b/examples/mesh2/mesh2.pro
new file mode 100644
index 0000000..9cbffc3
--- /dev/null
+++ b/examples/mesh2/mesh2.pro
@@ -0,0 +1,25 @@
+include( ../common.pro )
+
+SOURCES = src/main.cpp \
+		src/mesh2mainwindow.cpp \
+		src/colormapreader.cpp \
+		src/lightingdlg.cpp \
+		src/mesh.cpp
+
+HEADERS =  src/mesh2mainwindow.h \
+		src/functions.h \
+		src/colormapreader.h \
+		src/lightingdlg.h \
+		src/femreader.h
+
+!isEmpty( ISQT4 ) {
+SOURCES += src/designerworkaround.cpp
+HEADERS += src/designerworkaround.h 
+FORMS =  src/mesh2mainwindowbase4.ui \
+         src/lightingdlgbase4.ui
+}
+isEmpty( ISQT4 ) {
+FORMS =  src/mesh2mainwindowbase.ui \
+         src/lightingdlgbase.ui
+}
+
diff --git a/examples/mesh2/src/colormapreader.cpp b/examples/mesh2/src/colormapreader.cpp
new file mode 100644
index 0000000..eedf78b
--- /dev/null
+++ b/examples/mesh2/src/colormapreader.cpp
@@ -0,0 +1,81 @@
+#include <fstream>
+
+#include <qfileinfo.h>
+#include <qfiledialog.h>
+#include <qlayout.h>
+#include <qpainter.h>
+
+#include "colormapreader.h"
+
+using namespace Qwt3D;
+using namespace std;
+
+#if QT_VERSION < 0x040000
+
+ColorMapPreview::ColorMapPreview( QWidget *parent ) 
+: QFrame( parent ) 
+{
+	label_ = new QLabel(this);
+	setFrameShape( QFrame::StyledPanel );
+	setFrameShadow( QFrame::Sunken );
+	QGridLayout* layout = new QGridLayout( this, 1, 1, 10); 
+
+	layout->addWidget( label_, 0, 0, Qt::AlignJustify );
+}
+
+void ColorMapPreview::previewUrl( const QUrl &u )
+{
+		QString path = u.path();
+    QFileInfo fi( path );
+		if (fi.extension() != "map" && fi.extension() != "MAP")
+      label_->setText( "No color map" );
+		else
+		{
+			if ( open(path) )
+				label_->setPixmap( pix_ );
+		}
+}
+
+bool ColorMapPreview::open(QString fname)
+{	
+  if (fname.isEmpty())
+    return false;
+
+  ifstream file(QWT3DLOCAL8BIT(fname));
+	
+	RGBA rgb;
+	cv.clear();
+	
+	while ( file ) 
+	{		
+		file >> rgb.r >> rgb.g >> rgb.b;
+		file.ignore(10000,'\n');
+		if (!file.good())
+			break;
+		else
+		{
+			rgb.a = 1;
+			rgb.r /= 255;
+			rgb.g /= 255;
+			rgb.b /= 255;
+			cv.push_back(rgb);	
+		}
+	}
+
+	pix_.resize(80, cv.size());
+	QPainter p( &pix_ );
+  p.translate( 0, cv.size()-1 );
+	for (unsigned i=0; i!=cv.size(); ++i)
+	{
+		rgb = cv[i];
+		p.setPen(GL2Qt(rgb.r,rgb.g,rgb.b));
+		p.drawLine(QPoint(0,0),QPoint(pix_.width(),0));	
+    p.translate( 0, -1 );
+	}
+  p.end();
+
+	return true;
+}
+
+#else
+#endif
diff --git a/examples/mesh2/src/colormapreader.h b/examples/mesh2/src/colormapreader.h
new file mode 100644
index 0000000..359cb4c
--- /dev/null
+++ b/examples/mesh2/src/colormapreader.h
@@ -0,0 +1,28 @@
+#ifndef __colormapreader_2003_06_08_13_23__
+#define __colormapreader_2003_06_08_13_23__
+
+#include <qlabel.h>
+#include <qframe.h>
+#include <qpixmap.h>
+
+#include "../../../include/qwt3d_types.h"
+
+#if QT_VERSION < 0x040000
+
+class ColorMapPreview : public QFrame, public QFilePreview
+{
+public:
+  ColorMapPreview( QWidget *parent=0 );
+  void previewUrl( const QUrl &u );
+
+private:
+	Qwt3D::ColorVector cv;
+	QLabel* label_;
+	QPixmap pix_;
+	bool open(QString);
+};
+
+#else // if present in Qt4  
+#endif
+
+#endif
diff --git a/examples/mesh2/src/designerworkaround.cpp b/examples/mesh2/src/designerworkaround.cpp
new file mode 100644
index 0000000..e8fdab9
--- /dev/null
+++ b/examples/mesh2/src/designerworkaround.cpp
@@ -0,0 +1,146 @@
+#include "designerworkaround.h"
+
+namespace{
+  QString tr(const char* val)
+  {
+    return QObject::tr(val);
+  }
+
+  void setCheckable(QActionGroup* ag) 
+  {
+    QList<QAction*> tmplist = ag->actions();
+    for (QList<QAction*>::iterator it=tmplist.begin(); it!=tmplist.end(); ++it)
+      (*it)->setCheckable(true);
+  }
+
+}
+
+
+void DesignerWorkaround::setupWorkaround(QMainWindow* mw)
+{
+    // actions
+
+  openFile = new QAction(QIcon(":/images/fileopen.png"), tr("&Open File"), mw);
+  openFile->setShortcut( QKeySequence(tr("CTRL+O")));
+  openMeshFile = new QAction(QIcon(":/images/filecell.png"), tr("Open FEM File"), mw);
+  
+  Exit = new QAction(tr("&Exit"), mw);
+  Exit->setShortcut( QKeySequence(tr("CTRL+Q")));
+
+  animation = new QAction(QIcon(":/images/movie.png"), tr("Animation"), mw);
+  animation->setCheckable(true);
+  dump = new QAction(QIcon(":/images/savecontent.png"), "", mw);
+
+  coord = new QActionGroup(mw);
+    Box = new QAction(QIcon(":/images/box.png"), "", coord);
+    Frame = new QAction(QIcon(":/images/frame.png"), "", coord);
+    None = new QAction(QIcon(":/images/grid.png"), "", coord);
+  setCheckable(coord);
+
+  grids = new QActionGroup(mw);
+    front = new QAction(QIcon(":/images/gridfr.png"), "", grids);
+    back = new QAction(QIcon(":/images/gridb.png"), "", grids);
+    right = new QAction(QIcon(":/images/gridr.png"), "", grids);
+    left = new QAction(QIcon(":/images/gridl.png"), "", grids);
+    ceil = new QAction(QIcon(":/images/gridc.png"), "", grids);
+    floor = new QAction(QIcon(":/images/gridf.png"), "", grids);
+  grids->setExclusive(false);
+  setCheckable(grids);
+
+  plotstyle = new QActionGroup(mw);
+    pointstyle = new QAction(QIcon(":/images/scattered.png"), "", plotstyle);
+    wireframe = new QAction(QIcon(":/images/wireframe.png"), "", plotstyle);
+    hiddenline = new QAction(QIcon(":/images/hiddenline.png"), "", plotstyle);
+    polygon = new QAction(QIcon(":/images/polygon.png"), "", plotstyle);
+    filledmesh = new QAction(QIcon(":/images/filledmesh.png"), "", plotstyle);
+    nodata = new QAction(QIcon(":/images/nodata.png"), "", plotstyle);
+  setCheckable(plotstyle);
+  
+  floorstyle = new QActionGroup(mw);
+    floordata = new QAction(QIcon(":/images/floordata.png"), "", floorstyle);
+    flooriso = new QAction(QIcon(":/images/flooriso.png"), "", floorstyle);
+    floornone = new QAction(QIcon(":/images/floorempty.png"), "", floorstyle);
+  setCheckable(floorstyle);  
+
+  normals = new QAction(QIcon(":/images/normals.png"), "", mw);
+  normals->setCheckable(true);
+
+  color = new QActionGroup(mw);
+    axescolor = new QAction(tr("&Axes"), color);
+    backgroundcolor = new QAction(tr("&Background"), color);
+    meshcolor = new QAction(tr("&Mesh"), color);
+    numbercolor = new QAction(tr("&Numbers"), color);
+    labelcolor = new QAction(tr("&Label"), color);
+    titlecolor = new QAction(tr("Caption"), color);
+    datacolor = new QAction(tr("Data color"), color);
+    resetcolor = new QAction(tr("&Reset"), color);
+
+  font = new QActionGroup(mw);
+    numberfont = new QAction(tr("&Scale numbering"), font);
+    labelfont = new QAction(tr("&Axes label"), font);
+    titlefont = new QAction(tr("&Caption"), font);
+    resetfont = new QAction(tr("&Reset"), font);
+
+
+  // toolbars
+  mainToolbar = new QToolBar( QString(""), mw ); 
+  mainToolbar->setMovable( false );
+  
+  mainToolbar->addAction(openFile);
+  mainToolbar->addAction(openMeshFile);
+  mainToolbar->addAction(dump);
+
+  filetypeCB = new QComboBox;
+  functionCB = new QComboBox;
+  psurfaceCB = new QComboBox;
+
+  mainToolbar->addWidget(filetypeCB);
+  mainToolbar->addWidget(functionCB);
+  mainToolbar->addWidget(psurfaceCB);
+
+  mainToolbar->addAction(animation);
+
+  csToolbar = new QToolBar( QString(""), mw ); 
+  csToolbar->setMovable( false );
+
+  csToolbar->addActions(coord->actions());
+  csToolbar->addActions(grids->actions());
+  csToolbar->addActions(plotstyle->actions());
+  csToolbar->addActions(floorstyle->actions());
+  csToolbar->addAction(normals);
+  
+  // menubar
+  menubar = mw->menuBar();//new QMenuBar();
+    filemenu = menubar->addMenu("&File");
+      filemenu->addAction(openFile);
+      filemenu->addAction(openMeshFile);
+      filemenu->addAction(animation);
+      filemenu->addAction(Exit);
+    colormenu = menubar->addMenu(tr("&Color"));    
+      colormenu->addActions(color->actions());
+    fontmenu = menubar->addMenu(tr("&Fonts"));    
+      fontmenu->addActions(font->actions());
+  
+  mw->addToolBar(mainToolbar);
+  mw->addToolBar(csToolbar);
+  
+
+  functionCB->clear();
+  functionCB->addItem( tr( "---" ) );
+  functionCB->addItem( tr( "Hat" ) );
+  functionCB->addItem( tr( "Rosenbrock" ) );
+  functionCB->addItem( tr( "Saddle" ) );
+  functionCB->addItem( tr( "Sombrero" ) );
+  functionCB->addItem( tr( "Ripple" ) );
+  functionCB->setToolTip(tr( "Display function" ) );
+  psurfaceCB->clear();
+  psurfaceCB->addItem( tr( "---" ) );
+  psurfaceCB->addItem( tr( "Torus" ) );
+  psurfaceCB->addItem( tr( "Seashell" ) );
+  psurfaceCB->addItem( tr( "Boy" ) );
+  psurfaceCB->addItem( tr( "Dini" ) );
+  psurfaceCB->addItem( tr( "Cone" ) );
+  psurfaceCB->setToolTip(tr( "Display parametric surface. Turn Lighting on for better quality."));
+    
+  QObject::connect(Exit, SIGNAL(triggered()), mw, SLOT(close()));
+}
diff --git a/examples/mesh2/src/designerworkaround.h b/examples/mesh2/src/designerworkaround.h
new file mode 100644
index 0000000..32a9161
--- /dev/null
+++ b/examples/mesh2/src/designerworkaround.h
@@ -0,0 +1,76 @@
+#ifndef designerworkaround_h__2005_07_10_10_46_begin_guarded_code
+#define designerworkaround_h__2005_07_10_10_46_begin_guarded_code
+
+#include <QtGui/QMenu>
+#include <QtGui/QToolBar>
+#include <QtGui/QAction>
+#include <QtGui/QActionGroup>
+#include <QtGui/QMainWindow>
+#include <QtGui/QComboBox>
+#include <QtGui/QMenuBar>
+
+
+class DesignerWorkaround
+{
+public:
+  QMenuBar *menubar;
+  QMenu *filemenu;
+  QMenu *colormenu;
+  QMenu *fontmenu;
+  QToolBar *mainToolbar;
+  QToolBar *csToolbar;
+  QAction* openFile;
+  QAction* openMeshFile;
+  QAction* animation;
+  QAction* dump;
+  QAction* normals;
+  QAction* Exit;
+  
+  QActionGroup* coord;
+  QAction* Box;
+  QAction* Frame;
+  QAction* None;
+  
+  QActionGroup* plotstyle;
+  QAction* wireframe;
+  QAction* hiddenline;
+  QAction* polygon;
+  QAction* filledmesh;
+  QAction* nodata;
+  QAction* pointstyle;
+  
+  QActionGroup* color;
+  QAction* axescolor;
+  QAction* backgroundcolor;
+  QAction* meshcolor;
+  QAction* numbercolor;
+  QAction* labelcolor;
+  QAction* titlecolor;
+  QAction* datacolor;
+  QAction* resetcolor;
+  
+  QActionGroup* font;
+  QAction* numberfont;
+  QAction* labelfont;
+  QAction* titlefont;
+  QAction* resetfont;
+  
+  QActionGroup* floorstyle;
+  QAction* floordata;
+  QAction* flooriso;
+  QAction* floornone;
+  
+  QActionGroup* grids;
+  QAction* front;
+  QAction* back;
+  QAction* right;
+  QAction* left;
+  QAction* ceil;
+  QAction* floor;
+
+  QComboBox* filetypeCB, *functionCB, *psurfaceCB;
+
+  void setupWorkaround(QMainWindow* mw);
+};
+
+#endif
diff --git a/examples/mesh2/src/femreader.h b/examples/mesh2/src/femreader.h
new file mode 100644
index 0000000..e662765
--- /dev/null
+++ b/examples/mesh2/src/femreader.h
@@ -0,0 +1,83 @@
+#ifndef femreader_h__2004_03_07_14_03_begin_guarded_code
+#define femreader_h__2004_03_07_14_03_begin_guarded_code
+
+#include <math.h>
+#include <fstream>
+#include "qwt3d_global.h"
+#include "qwt3d_types.h"
+
+class NodeFilter
+{
+	public:
+		explicit NodeFilter()
+		{
+			values = std::vector<double>(6);
+		}
+		
+		Qwt3D::Triple readLine(std::ifstream& str)
+		{
+			for (unsigned i = 0; i!=values.size(); ++i)
+				str >> values[i];
+
+      return Qwt3D::Triple(values[1], values[2], values[5] / 1000);
+		}
+	
+	private:				
+		std::vector<double> values;
+};
+
+class CellFilter
+{
+	public:
+		
+		Qwt3D::Cell readLine(std::ifstream& str)
+		{
+			Qwt3D::Cell cell(4);
+			str >> cell[0]; // dummy (cell number) - overridden in next step
+			for (unsigned i = 0; i<cell.size(); ++i)
+			{
+				str >> cell[i];
+				cell[i] = cell[i] - 1;
+			}
+			return cell;
+		}
+};
+
+
+template <typename FILTER>
+bool readNodes(Qwt3D::TripleField& v, const char* fname, FILTER fil)
+{
+	std::ifstream file(fname);
+	
+	v.clear();
+
+	Qwt3D::Triple t;
+	while ( file ) 
+	{
+		t = fil.readLine( file );			
+		if (!file.good())
+			break;
+		v.push_back( t );
+	}
+	return true;
+}
+
+template <typename FILTER>
+bool readConnections(Qwt3D::CellField& v, const char* fname, FILTER fil)
+{
+	std::ifstream file(fname);
+
+	v.clear();
+
+	Qwt3D::Cell cell;
+	while ( file ) 
+	{
+		cell = fil.readLine( file );
+		if (!file.good())
+			break;
+		v.push_back(cell);	
+	}
+	return true;
+}
+
+#endif /* include guarded */
diff --git a/examples/mesh2/src/functions.h b/examples/mesh2/src/functions.h
new file mode 100644
index 0000000..4778aa0
--- /dev/null
+++ b/examples/mesh2/src/functions.h
@@ -0,0 +1,214 @@
+#ifndef __EXAMPLE_H__
+#define __EXAMPLE_H__
+
+#include <math.h>
+#include "../../../include/qwt3d_parametricsurface.h"
+#include "../../../include/qwt3d_function.h"
+
+using namespace Qwt3D;
+
+
+class Rosenbrock : public Function
+{
+public:
+
+	Rosenbrock(SurfacePlot& pw)
+	:Function(pw)
+	{
+	}
+
+	double operator()(double x, double y)
+	{
+    return 0.7 * log10((1-x)*(1-x) + 10 * (y - x*x)*(y - x*x));
+	}
+//	QString name() const {return "Almost {\\it Rosenbrock}\\,:\\quad$\\frac{\\ln((1-x)^2 + 100(y-x^2)^2)}{8}$";}
+};
+
+class Hat : public Function
+{
+public:
+
+	Hat(SurfacePlot& pw)
+	:Function(pw)
+	{
+		//setMinZ(0.3);     
+    setDomain(0,10,0,10);
+	}
+	
+	double operator()(double x, double y)
+	{
+    return 1.0 / (x*x+y*y+0.5);
+    //return x*x*y/(x*x*x*x+y*y);
+	}
+};
+
+
+class Ripple : public Function
+{
+public:
+
+	Ripple(SurfacePlot& pw)
+	:Function(pw)
+	{
+		double l = 12; 
+    setDomain(-l,l,-l,l);
+	}
+	
+	double operator()(double x, double y)
+	{
+    return (cos(sqrt(x*x+y*y) + cos(sqrt(((x+.913*2*Qwt3D::PI)*(x+.913*2*Qwt3D::PI))+y*y)) 
+      + cos(sqrt(((x-.913*2*Qwt3D::PI)*(x-.913*2*Qwt3D::PI))+(y*y))))*4);
+	}
+};
+
+class Saddle : public Function
+{
+public:
+
+	Saddle()
+	:Function()
+	{
+	//	setMaxZ(0.8);     
+	}
+	
+	double operator()(double x, double y)
+	{
+		return x*x - y*y;
+	}
+//	QString name() const {return "$x^2-y^2$";}
+};
+
+class Mex : public Function
+{
+public:
+
+	Mex()
+	:Function()
+	{
+	//	setMaxZ(0.8);     
+	}
+	
+	double operator()(double x, double y)
+	{
+		double n = sqrt(x*x+y*y); 
+
+		if (n < DBL_MIN)
+			return 20;
+		
+		return 20 * sin(sqrt(x*x+y*y)) / n;
+	}
+//	QString name() const {return "$\\frac{20\\sin\\sqrt{x^2+y^2}}{\\sqrt{x^2+y^2}}$";}
+};
+
+class Torus : public ParametricSurface
+{
+public:
+
+  Torus(SurfacePlot& pw)
+  :ParametricSurface(pw)
+  {
+    setMesh(41,31);
+    setDomain(-2*Qwt3D::PI, 0,-2*Qwt3D::PI,0);
+    setPeriodic(true,true);
+  }
+
+
+  Triple operator()(double u, double v)
+  {
+    double x,y,z;
+    double c = 1.9;
+    x = (c + cos(v)) * cos(u);
+    y = (c + cos(v)) * sin(u);
+    z = sin(v) + cos(v);
+    return Triple(x,y,z);
+  }
+};
+
+class Seashell : public ParametricSurface
+{
+public:
+
+  Seashell(SurfacePlot& pw)
+  :ParametricSurface(pw)
+  {
+    setMesh(41,131);
+    setDomain(0,2*Qwt3D::PI,0,2*Qwt3D::PI);
+    setPeriodic(true,true);
+  }
+
+
+  Triple operator()(double u, double v)
+  {
+    double x,y,z;
+    double a = 1;
+    double b = 6;
+    double c = 0.5;
+    int n = 3;
+
+    double f = v/(2*Qwt3D::PI);
+
+    x = a*(1-f)*cos(n*v)*(1+cos(u)) + c*cos(n*v) ;
+    y = a*(1-f)*sin(n*v)*(1+cos(u)) + c*sin(n*v) ;
+    z = b*f + a*(1-f)*sin(u);
+    return Triple(x,y,z);
+  }
+};
+
+class Boy : public ParametricSurface
+{
+public:
+
+  Boy(SurfacePlot& pw)
+  :ParametricSurface(pw)
+  {
+    setMesh(141,131);
+    setDomain(0,Qwt3D::PI,0,Qwt3D::PI);
+    setPeriodic(true,true);
+  }
+
+
+  Triple operator()(double u, double v)
+  {
+    double x,y,z;
+    double a = 2/3.;
+    double b = sqrt(2.);
+    
+    x = a*(cos(u)*cos(2*v)+b*sin(u)*cos(v))*cos(u) / (b-sin(2*u)*sin(3*v));
+    y = a*(cos(u)*sin(2*v)-b*sin(u)*sin(v))*cos(u) / (b-sin(2*u)*sin(3*v));
+    z = b*cos(u)*cos(u) / (b-sin(2*u)*sin(2*v));
+    
+    return Triple(x,y,z);
+  }
+};
+
+class Dini : public ParametricSurface
+{
+public:
+
+  Dini(SurfacePlot& pw)
+  :ParametricSurface(pw)
+  {
+    setMesh(141,35);
+    setDomain(0,5*Qwt3D::PI,0.001, 2);
+    setPeriodic(true,true);
+  }
+
+
+  Triple operator()(double u, double v)
+  {
+    double x,y,z;
+    double a = 5;
+    double b = 1;
+
+    
+    x=a*cos(u)*sin(v);
+    y=a*sin(u)*sin(v); 
+    z=a*(cos(v)+log(tan(v/2)))+b*u;
+
+    return Triple(x,y,z);
+  }
+};
+
+void createCone(Qwt3D::TripleField& conepos, Qwt3D::CellField& conecell);
+
+#endif
diff --git a/examples/mesh2/src/lightingdlg.cpp b/examples/mesh2/src/lightingdlg.cpp
new file mode 100644
index 0000000..f26ae4e
--- /dev/null
+++ b/examples/mesh2/src/lightingdlg.cpp
@@ -0,0 +1,220 @@
+#include <qlayout.h>
+#include <qframe.h>
+#include <qslider.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+
+#include "lightingdlg.h"
+
+using namespace Qwt3D;
+
+class Sphere : public ParametricSurface
+{
+public:
+
+  Sphere(SurfacePlot& pw)
+  :ParametricSurface(pw)
+  {
+    setMesh(41,31);
+    setDomain(0,2*Qwt3D::PI,0,Qwt3D::PI);
+    setPeriodic(false,false);
+  }
+
+
+  Triple operator()(double u, double v)
+  {
+    double x,y,z;
+    double r = 1;
+    x = r*cos(u)*sin(v);
+    y = r*sin(u)*sin(v);
+    z = r*cos(v);
+    return Triple(x,y,z);
+  }
+};
+
+
+/////////////////////////////////////////////////////////////////
+//
+//   Plot
+//
+/////////////////////////////////////////////////////////////////
+
+Plot::Plot(QWidget *parent)
+: SurfacePlot(parent)
+{
+  setTitle("A Simple SurfacePlot Demonstration");
+  
+  Sphere sphere(*this);
+  sphere.create();
+
+  reset();  
+  assignMouse(Qt::LeftButton,
+    Qt::RightButton,
+    Qt::LeftButton,
+    Qt::NoButton,
+    Qt::NoButton,
+    Qt::NoButton,
+    Qt::NoButton,
+    Qt::NoButton,
+    Qt::NoButton
+    );
+
+  stick = (Pointer*)addEnrichment(Pointer(0.05));
+  stick->setPos(0,0,1);
+}
+
+void Plot::reset()
+{
+  makeCurrent();
+  setRotation(0,0,0);
+  setTitle("Use your mouse buttons and keyboard");
+  setTitleFont("Arial", 8, QFont::Bold);
+  setTitleColor(RGBA(0.9,0.9,0.9));
+  setSmoothMesh(true);
+  setZoom(0.9);
+  setCoordinateStyle(NOCOORD);
+  setMeshColor(RGBA(0.6,0.6,0.6,0.3));
+  setPlotStyle(FILLEDMESH);
+  setBackgroundColor(RGBA(0,0,0));
+
+  updateData();
+}
+
+/////////////////////////////////////////////////////////////////
+//
+//   Pointer
+//
+/////////////////////////////////////////////////////////////////
+
+
+Pointer::Pointer(double rad)
+{
+  configure(rad);
+}
+
+Pointer::~Pointer()
+{
+}
+
+void Pointer::configure(double rad)
+{
+  plot = 0;
+  
+  radius_ = rad;
+}
+
+void Pointer::drawBegin()
+{
+  GLint mode;
+	glGetIntegerv(GL_MATRIX_MODE, &mode);
+	glMatrixMode( GL_MODELVIEW );
+  glPushMatrix();
+  
+  glColor3d(1,0,0);
+  glBegin(GL_LINES);
+    glVertex3d(pos_.x, pos_.y, pos_.z);
+    glVertex3d(0, 0, 0);
+  glEnd();
+
+  glPopMatrix();
+	glMatrixMode(mode);
+}
+
+
+LightingDlg::LightingDlg(QWidget *parent)
+:LightingBase(parent)
+{
+#if QT_VERSION < 0x040000
+  QGridLayout *grid = new QGridLayout( frame, 0, 0 );
+#else
+  setupUi(this);
+  QGridLayout *grid = new QGridLayout( frame);
+#endif
+
+  dataPlot = 0;
+  
+  plot = new Plot(frame);
+  plot->updateData();
+
+  grid->addWidget( plot, 0, 0 );
+
+	connect( stdlight, SIGNAL( clicked() ), this, SLOT( reset() ) );
+	connect( distSL, SIGNAL(valueChanged(int)), this, SLOT(setDistance(int)) );
+	connect( emissSL, SIGNAL(valueChanged(int)), this, SLOT(setEmission(int)) );
+	connect( ambdiffSL, SIGNAL(valueChanged(int)), this, SLOT(setDiff(int)) );
+	connect( specSL, SIGNAL(valueChanged(int)), this, SLOT(setSpec(int)) );
+	connect( shinSL, SIGNAL(valueChanged(int)), this, SLOT(setShin(int)) );
+  connect( plot, SIGNAL(rotationChanged(double, double, double)), this, SLOT(setRotation(double, double, double)) );
+}
+
+LightingDlg::~LightingDlg()
+{
+  delete plot;
+}
+
+void LightingDlg::setEmission(int val)
+{
+  if (!dataPlot)
+    return;
+  dataPlot->setMaterialComponent(GL_EMISSION, val / 100.);
+  dataPlot->updateGL();
+}
+void LightingDlg::setDiff(int val)
+{
+  if (!dataPlot)
+    return;
+  dataPlot->setLightComponent(GL_DIFFUSE, val / 100.);
+  dataPlot->updateGL();
+}
+void LightingDlg::setSpec(int val)
+{
+  if (!dataPlot)
+    return;
+  dataPlot->setMaterialComponent(GL_SPECULAR, val / 100.);
+  dataPlot->updateGL();
+}
+void LightingDlg::setShin(int val)
+{
+  if (!dataPlot)
+    return;
+  dataPlot->setShininess( val / 100.);
+  dataPlot->updateGL();
+}
+
+void LightingDlg::reset()
+{
+  plot->reset();
+  if (dataPlot)
+    dataPlot->updateGL();
+}
+
+void LightingDlg::setDistance(int val)
+{
+  
+  plot->stick->setPos(0,0,val/100.);
+  plot->updateData();
+  plot->updateGL();
+  
+  double drad = (dataPlot->hull().maxVertex-dataPlot->hull().minVertex).length();
+  drad *= val/20.;
+
+  dataPlot->setLightShift(drad,drad,drad);
+  dataPlot->updateGL();
+}
+
+void LightingDlg::assign(Qwt3D::Plot3D* pl) 
+{
+  if (!pl) 
+    return;
+  dataPlot = pl;
+}
+
+void LightingDlg::setRotation(double x, double y, double z)
+{
+  if (!dataPlot)
+    return;
+  
+  setDistance(distSL->value());
+  dataPlot->setLightRotation(x,y,z);
+  dataPlot->updateGL();
+}
diff --git a/examples/mesh2/src/lightingdlg.h b/examples/mesh2/src/lightingdlg.h
new file mode 100644
index 0000000..5df3c04
--- /dev/null
+++ b/examples/mesh2/src/lightingdlg.h
@@ -0,0 +1,100 @@
+#ifndef lightingdlg_h__2004_03_07_13_35_begin_guarded_code
+#define lightingdlg_h__2004_03_07_13_35_begin_guarded_code
+
+#include <math.h>
+#include <qapplication.h>
+#include "../../../include/qwt3d_parametricsurface.h"
+#include "../../../include/qwt3d_surfaceplot.h"
+#include "../../../include/qwt3d_enrichment.h"
+#include "../../../include/qwt3d_color.h"
+
+#if QT_VERSION < 0x040000
+#include "lightingdlgbase.h"
+#else
+#include "ui_lightingdlgbase4.h"
+#endif
+
+class Pointer : public Qwt3D::VertexEnrichment
+{
+public:
+  Pointer(double rad);
+  ~Pointer();
+
+  Qwt3D::Enrichment* clone() const {return new Pointer(*this);}
+  
+  void configure(double rad);
+  void drawBegin();
+  void draw(Qwt3D::Triple const&){}
+  void setPos(double x, double y, double z) {pos_ = Qwt3D::Triple(x,y,z);}
+
+private:
+  double radius_;
+  Qwt3D::Triple pos_;
+};
+
+struct SColor : public Qwt3D::Color
+{
+  Qwt3D::RGBA operator()(double, double, double) const {return Qwt3D::RGBA(0.8,0,0,0.5);}
+};
+
+typedef Qwt3D::SurfacePlot SPlot; // moc/VC6 issue in Qt 4.0.0
+
+class Plot : public SPlot
+{
+  Q_OBJECT
+    
+public:
+  Plot(QWidget* parent);
+  Pointer* stick;
+  void reset();
+};
+
+//MOC_SKIP_BEGIN
+#if QT_VERSION < 0x040000
+  class LightingBase : public LightingDlgBase
+  {
+  public:
+    LightingBase(QWidget* parent = 0) 
+      : LightingDlgBase(parent) 
+    {
+    } 
+  };
+#else
+  class LightingBase : public QDialog, protected Ui::Dialog
+  {
+  public:
+    LightingBase(QWidget* parent = 0) 
+      : QDialog(parent) 
+    {
+    } 
+  };
+#endif
+//MOC_SKIP_END
+
+
+
+class LightingDlg : public LightingBase
+{
+	Q_OBJECT
+    
+public:
+  LightingDlg(QWidget *parent=0);
+  ~LightingDlg();
+
+  void assign(Qwt3D::Plot3D* pl);
+  
+  Plot* plot;
+  Qwt3D::Plot3D* dataPlot;
+
+public slots:
+	void setDistance(int);
+	void setEmission(int);
+	void setDiff(int);
+	void setSpec(int);
+	void setShin(int);
+  void reset();
+  void setRotation(double x, double y, double z);
+};
+
+    
+#endif /* include guarded */
diff --git a/examples/mesh2/src/lightingdlgbase.ui b/examples/mesh2/src/lightingdlgbase.ui
new file mode 100644
index 0000000..0d60f1c
--- /dev/null
+++ b/examples/mesh2/src/lightingdlgbase.ui
@@ -0,0 +1,361 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>LightingDlgBase</class>
+<widget class="QDialog">
+    <property name="name">
+        <cstring>LightingDlgBase</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>450</width>
+            <height>345</height>
+        </rect>
+    </property>
+    <property name="sizePolicy">
+        <sizepolicy>
+            <hsizetype>5</hsizetype>
+            <vsizetype>5</vsizetype>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+        </sizepolicy>
+    </property>
+    <property name="minimumSize">
+        <size>
+            <width>450</width>
+            <height>345</height>
+        </size>
+    </property>
+    <property name="maximumSize">
+        <size>
+            <width>450</width>
+            <height>345</height>
+        </size>
+    </property>
+    <property name="baseSize">
+        <size>
+            <width>0</width>
+            <height>0</height>
+        </size>
+    </property>
+    <property name="caption">
+        <string>Lighting Configuration</string>
+    </property>
+    <property name="sizeGripEnabled">
+        <bool>false</bool>
+    </property>
+    <grid>
+        <property name="name">
+            <cstring>unnamed</cstring>
+        </property>
+        <property name="margin">
+            <number>11</number>
+        </property>
+        <property name="spacing">
+            <number>6</number>
+        </property>
+        <widget class="QFrame" row="0" column="0">
+            <property name="name">
+                <cstring>frame</cstring>
+            </property>
+            <property name="minimumSize">
+                <size>
+                    <width>290</width>
+                    <height>290</height>
+                </size>
+            </property>
+            <property name="maximumSize">
+                <size>
+                    <width>290</width>
+                    <height>290</height>
+                </size>
+            </property>
+            <property name="frameShape">
+                <enum>StyledPanel</enum>
+            </property>
+            <property name="frameShadow">
+                <enum>Sunken</enum>
+            </property>
+        </widget>
+        <widget class="QLayoutWidget" row="1" column="0">
+            <property name="name">
+                <cstring>Layout11</cstring>
+            </property>
+            <hbox>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+                <property name="margin">
+                    <number>0</number>
+                </property>
+                <property name="spacing">
+                    <number>6</number>
+                </property>
+                <widget class="QPushButton">
+                    <property name="name">
+                        <cstring>stdlight</cstring>
+                    </property>
+                    <property name="caption">
+                        <string></string>
+                    </property>
+                    <property name="text">
+                        <string>Std</string>
+                    </property>
+                    <property name="autoDefault">
+                        <bool>true</bool>
+                    </property>
+                    <property name="default">
+                        <bool>true</bool>
+                    </property>
+                </widget>
+                <spacer>
+                    <property name="name">
+                        <cstring>Horizontal Spacing2</cstring>
+                    </property>
+                    <property name="orientation">
+                        <enum>Horizontal</enum>
+                    </property>
+                    <property name="sizeType">
+                        <enum>Expanding</enum>
+                    </property>
+                    <property name="sizeHint">
+                        <size>
+                            <width>16</width>
+                            <height>0</height>
+                        </size>
+                    </property>
+                </spacer>
+                <widget class="QPushButton">
+                    <property name="name">
+                        <cstring>buttonOk</cstring>
+                    </property>
+                    <property name="caption">
+                        <string></string>
+                    </property>
+                    <property name="text">
+                        <string>&OK</string>
+                    </property>
+                    <property name="autoDefault">
+                        <bool>true</bool>
+                    </property>
+                    <property name="default">
+                        <bool>true</bool>
+                    </property>
+                </widget>
+            </hbox>
+        </widget>
+        <widget class="QLayoutWidget" row="0" column="1">
+            <property name="name">
+                <cstring>Layout8</cstring>
+            </property>
+            <vbox>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+                <property name="margin">
+                    <number>0</number>
+                </property>
+                <property name="spacing">
+                    <number>6</number>
+                </property>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>Layout2</cstring>
+                    </property>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <property name="margin">
+                            <number>0</number>
+                        </property>
+                        <property name="spacing">
+                            <number>6</number>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>ambdiff</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Ambient & Diffuse Part</string>
+                            </property>
+                        </widget>
+                        <widget class="QSlider">
+                            <property name="name">
+                                <cstring>ambdiffSL</cstring>
+                            </property>
+                            <property name="maxValue">
+                                <number>100</number>
+                            </property>
+                            <property name="value">
+                                <number>80</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                        </widget>
+                    </vbox>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>Layout2_2</cstring>
+                    </property>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <property name="margin">
+                            <number>0</number>
+                        </property>
+                        <property name="spacing">
+                            <number>6</number>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>spec</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Specular Part</string>
+                            </property>
+                        </widget>
+                        <widget class="QSlider">
+                            <property name="name">
+                                <cstring>specSL</cstring>
+                            </property>
+                            <property name="maxValue">
+                                <number>100</number>
+                            </property>
+                            <property name="value">
+                                <number>30</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                        </widget>
+                    </vbox>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>Layout2_3</cstring>
+                    </property>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <property name="margin">
+                            <number>0</number>
+                        </property>
+                        <property name="spacing">
+                            <number>6</number>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>shin</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Shininess</string>
+                            </property>
+                        </widget>
+                        <widget class="QSlider">
+                            <property name="name">
+                                <cstring>shinSL</cstring>
+                            </property>
+                            <property name="maxValue">
+                                <number>1000</number>
+                            </property>
+                            <property name="value">
+                                <number>500</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                        </widget>
+                    </vbox>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>Layout2_4</cstring>
+                    </property>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <property name="margin">
+                            <number>0</number>
+                        </property>
+                        <property name="spacing">
+                            <number>6</number>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>emiss</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Emission</string>
+                            </property>
+                        </widget>
+                        <widget class="QSlider">
+                            <property name="name">
+                                <cstring>emissSL</cstring>
+                            </property>
+                            <property name="maxValue">
+                                <number>100</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                        </widget>
+                    </vbox>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>Layout2_4_2</cstring>
+                    </property>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <property name="margin">
+                            <number>0</number>
+                        </property>
+                        <property name="spacing">
+                            <number>6</number>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>dist</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Distance</string>
+                            </property>
+                        </widget>
+                        <widget class="QSlider">
+                            <property name="name">
+                                <cstring>distSL</cstring>
+                            </property>
+                            <property name="maxValue">
+                                <number>1000</number>
+                            </property>
+                            <property name="value">
+                                <number>100</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                        </widget>
+                    </vbox>
+                </widget>
+            </vbox>
+        </widget>
+    </grid>
+</widget>
+<connections>
+    <connection>
+        <sender>buttonOk</sender>
+        <signal>clicked()</signal>
+        <receiver>LightingDlgBase</receiver>
+        <slot>accept()</slot>
+    </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/mesh2/src/lightingdlgbase4.ui b/examples/mesh2/src/lightingdlgbase4.ui
new file mode 100644
index 0000000..60a200d
--- /dev/null
+++ b/examples/mesh2/src/lightingdlgbase4.ui
@@ -0,0 +1,293 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>428</width>
+    <height>330</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" >
+   <property name="margin" >
+    <number>8</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item row="0" column="0" >
+    <layout class="QGridLayout" >
+     <property name="margin" >
+      <number>0</number>
+     </property>
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <item row="0" column="0" >
+      <widget class="QFrame" name="frame" >
+       <property name="frameShape" >
+        <enum>QFrame::StyledPanel</enum>
+       </property>
+       <property name="frameShadow" >
+        <enum>QFrame::Sunken</enum>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0" >
+      <layout class="QHBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QPushButton" name="stdlight" >
+         <property name="text" >
+          <string>Std</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>91</width>
+           <height>31</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QPushButton" name="buttonOk" >
+         <property name="text" >
+          <string>&Ok</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item row="0" column="1" >
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>0</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <layout class="QVBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="label" >
+           <property name="text" >
+            <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ambient &amp; Diffuse Part</p></body></html></string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QSlider" name="ambdiffSL" >
+           <property name="maximum" >
+            <number>100</number>
+           </property>
+           <property name="value" >
+            <number>80</number>
+           </property>
+           <property name="orientation" >
+            <enum>Qt::Horizontal</enum>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QVBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="label_2" >
+           <property name="text" >
+            <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Specular Part</p></body></html></string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QSlider" name="specSL" >
+           <property name="maximum" >
+            <number>100</number>
+           </property>
+           <property name="value" >
+            <number>30</number>
+           </property>
+           <property name="sliderPosition" >
+            <number>30</number>
+           </property>
+           <property name="orientation" >
+            <enum>Qt::Horizontal</enum>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QVBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="label_3" >
+           <property name="text" >
+            <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Shininess</p></body></html></string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QSlider" name="shinSL" >
+           <property name="maximum" >
+            <number>1000</number>
+           </property>
+           <property name="value" >
+            <number>500</number>
+           </property>
+           <property name="orientation" >
+            <enum>Qt::Horizontal</enum>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QVBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="label_3_2" >
+           <property name="text" >
+            <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Emission</p></body></html></string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QSlider" name="emissSL" >
+           <property name="maximum" >
+            <number>100</number>
+           </property>
+           <property name="value" >
+            <number>0</number>
+           </property>
+           <property name="orientation" >
+            <enum>Qt::Horizontal</enum>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QVBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="label_3_2_2" >
+           <property name="text" >
+            <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Distance</p></body></html></string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QSlider" name="distSL" >
+           <property name="maximum" >
+            <number>1000</number>
+           </property>
+           <property name="value" >
+            <number>100</number>
+           </property>
+           <property name="orientation" >
+            <enum>Qt::Horizontal</enum>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+  <widget class="QWidget" name="layoutWidget" >
+   <property name="geometry" >
+    <rect>
+     <x>10</x>
+     <y>280</y>
+     <width>351</width>
+     <height>33</height>
+    </rect>
+   </property>
+  </widget>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>stdlight</sender>
+   <signal>clicked()</signal>
+   <receiver>Dialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>278</x>
+     <y>253</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>96</x>
+     <y>254</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonOk</sender>
+   <signal>clicked()</signal>
+   <receiver>Dialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>369</x>
+     <y>253</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>179</x>
+     <y>282</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/examples/mesh2/src/lightingdlgbaseimpl.cpp b/examples/mesh2/src/lightingdlgbaseimpl.cpp
new file mode 100644
index 0000000..13a73ef
--- /dev/null
+++ b/examples/mesh2/src/lightingdlgbaseimpl.cpp
@@ -0,0 +1,22 @@
+#include "lightingdlgbaseimpl.h"
+
+/* 
+ *  Constructs a lightingdlgbase which is a child of 'parent', with the 
+ *  name 'name' and widget flags set to 'f' 
+ *
+ *  The dialog will by default be modeless, unless you set 'modal' to
+ *  TRUE to construct a modal dialog.
+ */
+lightingdlgbase::lightingdlgbase( QWidget* parent,  const char* name, bool modal, WFlags fl )
+    : lightingdlgbaseBase( parent, name, modal, fl )
+{
+}
+
+/*  
+ *  Destroys the object and frees any allocated resources
+ */
+lightingdlgbase::~lightingdlgbase()
+{
+    // no need to delete child widgets, Qt does it all for us
+}
+
diff --git a/examples/mesh2/src/lightingdlgbaseimpl.h b/examples/mesh2/src/lightingdlgbaseimpl.h
new file mode 100644
index 0000000..48e7866
--- /dev/null
+++ b/examples/mesh2/src/lightingdlgbaseimpl.h
@@ -0,0 +1,15 @@
+#ifndef LIGHTINGDLGBASE_H
+#define LIGHTINGDLGBASE_H
+#include "lightingdlgbase.h"
+
+class lightingdlgbase : public lightingdlgbaseBase
+{ 
+    Q_OBJECT
+
+public:
+    lightingdlgbase( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 );
+    ~lightingdlgbase();
+
+};
+
+#endif // LIGHTINGDLGBASE_H
diff --git a/examples/mesh2/src/main.cpp b/examples/mesh2/src/main.cpp
new file mode 100644
index 0000000..fa138cb
--- /dev/null
+++ b/examples/mesh2/src/main.cpp
@@ -0,0 +1,32 @@
+/********************************************************************
+    created:   2003/09/09
+    filename:  main.cpp
+	
+    author:    Micha Bieber	
+*********************************************************************/
+
+#include <qapplication.h>
+#include "mesh2mainwindow.h"
+
+int main( int argc, char **argv )
+{
+  QApplication::setColorSpec( QApplication::CustomColor );
+  QApplication app(argc,argv);
+
+  if ( !QGLFormat::hasOpenGL() ) 
+	{
+		qWarning( "This system has no OpenGL support. Exiting." );     
+		return -1;
+  }
+    
+  Mesh2MainWindow mainwindow;
+
+#if QT_VERSION < 0x040000
+  app.setMainWidget(&mainwindow);
+#endif
+
+  mainwindow.resize(1024,768);
+	mainwindow.show();
+
+	return app.exec();
+}
diff --git a/examples/mesh2/src/mesh.cpp b/examples/mesh2/src/mesh.cpp
new file mode 100644
index 0000000..282de0a
--- /dev/null
+++ b/examples/mesh2/src/mesh.cpp
@@ -0,0 +1,57 @@
+#include "functions.h"
+
+using namespace std;
+using namespace Qwt3D;
+
+
+void createCone(Qwt3D::TripleField& conepos, Qwt3D::CellField& conecell)
+{
+  conepos.clear(); conecell.clear();
+  Cell cell;
+  
+  conepos.push_back(Triple(0,0,0));
+
+  const unsigned int count = 17;
+  double r1 = 0.7;
+  double r2 = 0.9 * r1;
+  
+  double h1 = 2;
+  double h2 = 1.03 * h1;
+
+  unsigned i;
+  
+  Cell c1;
+  // outer top border
+  for (i=0; i<count; ++i)
+  {
+    conepos.push_back(Triple(r1*cos(2*i*Qwt3D::PI/count), r1*sin(2*i*Qwt3D::PI/count),h1));
+  }
+  // inner top border
+  for (i=0; i<count; ++i)
+  {
+    conepos.push_back(Triple(r2*cos(2*i*Qwt3D::PI/count), r2*sin(2*i*Qwt3D::PI/count),h2));
+    c1.push_back(count+i+1);
+  }
+  // top polygon
+  conecell.push_back(c1);
+  
+  // triangles
+  Cell c2(3);
+  for (i=1; i<count+1; ++i)
+  {
+    c2[0] = 0;
+    c2[1] = i%count +1;
+    c2[2] = i;
+    conecell.push_back(c2);
+  }
+  // quadrangles
+  c2 = Cell(4);
+  for (i=1; i<count+1; ++i)
+  {
+    c2[0] = i;
+    c2[1] = i%count +1;
+    c2[2] = count+i%count +1;
+    c2[3] = count+i;
+    conecell.push_back(c2);
+  }
+}
diff --git a/examples/mesh2/src/mesh2mainwindow.cpp b/examples/mesh2/src/mesh2mainwindow.cpp
new file mode 100644
index 0000000..bddec94
--- /dev/null
+++ b/examples/mesh2/src/mesh2mainwindow.cpp
@@ -0,0 +1,956 @@
+#include <qmetaobject.h>
+
+#include <qframe.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+#include <qaction.h>
+#include <qmenubar.h>
+
+#if QT_VERSION < 0x040000
+#include <qpopupmenu.h>
+#endif
+
+#include <qtoolbar.h>
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qfiledialog.h>       
+#include <qstatusbar.h>
+#include <qfileinfo.h>
+#include <qslider.h>
+#include <qtimer.h>
+#include <qcombobox.h>
+#include <qstring.h>
+#include <qcheckbox.h>
+#include <qcolordialog.h>
+#include <qfontdialog.h>
+
+#include "mesh2mainwindow.h"
+
+#include "functions.h"
+#include "colormapreader.h"
+#include "lightingdlg.h"
+#include "femreader.h"
+#include "../../../include/qwt3d_io.h"
+#include "../../../include/qwt3d_io_gl2ps.h"
+#include "../../../include/qwt3d_io_reader.h"
+
+using namespace Qwt3D;
+using namespace std;
+
+
+bool Mesh2MainWindow::connectA (const QObject* sender, const char * slot)
+{
+#if QT_VERSION < 0x040000
+    return connect( sender, SIGNAL( activated() ), this, slot );
+#else
+    return connect( sender, SIGNAL( triggered() ), this, slot );
+#endif
+}
+
+bool Mesh2MainWindow::connectAG (const QObject* sender, const char * slot)
+{
+#if QT_VERSION < 0x040000
+    return connect( sender, SIGNAL( selected( QAction* ) ), this, slot ) ;
+#else
+    return connect( sender, SIGNAL( triggered( QAction* ) ), this, slot ) ;
+#endif
+}
+
+Mesh2MainWindow::~Mesh2MainWindow()      
+{
+	delete dataWidget;
+}
+
+Mesh2MainWindow::Mesh2MainWindow( QWidget* parent )       
+	: DummyBase( parent )
+{
+#if QT_VERSION < 0x040000
+	setCaption("Mesh2");      
+  QGridLayout *grid = new QGridLayout( frame, 0, 0 );
+#else
+  setupWorkaround(this);
+	setupUi(this);
+  QGridLayout *grid = new QGridLayout( frame );
+#endif   
+  
+  col_ = 0;
+	legend_ = false;
+	redrawWait = 50;
+	activeCoordSystem = None;
+
+  dataWidget = new SurfacePlot(frame);
+  grid->addWidget( dataWidget, 0, 0 );
+
+	connectAG( coord, SLOT( pickCoordSystem( QAction* ) ) );
+	connectAG( plotstyle, SLOT( pickPlotStyle( QAction* ) ) );
+	connectA( axescolor, SLOT( pickAxesColor() ) );
+	connectA( backgroundcolor, SLOT( pickBgColor() ) );
+	connectAG( floorstyle, SLOT( pickFloorStyle( QAction* ) ) );
+	connectA( meshcolor, SLOT( pickMeshColor() ) );
+	connectA( numbercolor, SLOT( pickNumberColor() ) );
+	connectA( labelcolor, SLOT( pickLabelColor() ) );
+	connectA( titlecolor, SLOT( pickTitleColor() ) );
+	connectA( datacolor, SLOT( pickDataColor() ) );
+	connect( lighting, SIGNAL( clicked() ), this, SLOT( pickLighting() ) );
+	connectA( resetcolor, SLOT( resetColors() ) );
+ 	connectA( numberfont, SLOT( pickNumberFont() ) );
+	connectA( labelfont, SLOT( pickLabelFont() ) );
+	connectA( titlefont, SLOT( pickTitleFont() ) );
+	connectA( resetfont, SLOT( resetFonts() ) );
+	connect( animation, SIGNAL( toggled(bool) ) , this, SLOT( toggleAnimation(bool) ) );
+    connectA( dump, SLOT( dumpImage() ) );
+	connectA( openFile, SLOT( open() ) );
+    //connect(openFile, SIGNAL(triggered()), this, SLOT(open()));
+	connectA( openMeshFile, SLOT( openMesh() ) );
+	
+  // only EXCLUSIVE groups emit selected :-/
+  connect( left, SIGNAL( toggled( bool ) ), this, SLOT( setLeftGrid( bool ) ) );
+	connect( right, SIGNAL( toggled( bool ) ), this, SLOT( setRightGrid( bool ) ) );
+	connect( ceil, SIGNAL( toggled( bool ) ), this, SLOT( setCeilGrid( bool ) ) );
+	connect( floor, SIGNAL( toggled( bool ) ), this, SLOT( setFloorGrid( bool ) ) );
+	connect( back, SIGNAL( toggled( bool ) ), this, SLOT( setBackGrid( bool ) ) );
+	connect( front, SIGNAL( toggled( bool ) ), this, SLOT( setFrontGrid( bool ) ) );
+
+	timer = new QTimer( this );
+	connect( timer, SIGNAL(timeout()), this, SLOT(rotate()) );
+
+	resSlider->setRange(1,70);
+	connect( resSlider, SIGNAL(valueChanged(int)), dataWidget, SLOT(setResolution(int)) );
+	connect( dataWidget, SIGNAL(resolutionChanged(int)), resSlider, SLOT(setValue(int)) );
+	resSlider->setValue(1);             
+	
+	connect( offsSlider, SIGNAL(valueChanged(int)), this, SLOT(setPolygonOffset(int)) );
+
+	connect(normButton, SIGNAL(clicked()), this, SLOT(setStandardView()));  
+	
+  QString qwtstr(" qwtplot3d ");
+  qwtstr += QString::number(QWT3D_MAJOR_VERSION) + ".";
+  qwtstr += QString::number(QWT3D_MINOR_VERSION) + ".";
+  qwtstr += QString::number(QWT3D_PATCH_VERSION) + " ";
+
+	QLabel* info = new QLabel(qwtstr, statusBar());       
+  statusBar()->addWidget(info, 0);
+	filenameWidget = new QLabel("                                  ", statusBar());
+	statusBar()->addWidget(filenameWidget,0);
+	dimWidget = new QLabel("", statusBar());
+	statusBar()->addWidget(dimWidget,0);
+	rotateLabel = new QLabel("", statusBar());
+	statusBar()->addWidget(rotateLabel,0);
+	shiftLabel = new QLabel("", statusBar());
+	statusBar()->addWidget(shiftLabel,0);
+	scaleLabel = new QLabel("", statusBar());
+	statusBar()->addWidget(scaleLabel,0);
+	zoomLabel = new QLabel("", statusBar());
+	statusBar()->addWidget(zoomLabel,0);
+	
+	connect(dataWidget, SIGNAL(rotationChanged(double,double,double)),this,SLOT(showRotate(double,double,double)));
+	connect(dataWidget, SIGNAL(vieportShiftChanged(double,double)),this,SLOT(showShift(double,double)));
+	connect(dataWidget, SIGNAL(scaleChanged(double,double,double)),this,SLOT(showScale(double,double,double)));
+	connect(dataWidget, SIGNAL(zoomChanged(double)),this,SLOT(showZoom(double)));
+
+	connect(functionCB, SIGNAL(activated(const QString&)), this, SLOT(createFunction(const QString&)));
+	connect(psurfaceCB, SIGNAL(activated(const QString&)), this, SLOT(createPSurface(const QString&)));
+	connect(projection, SIGNAL( toggled(bool) ), this, SLOT( toggleProjectionMode(bool)));
+	connect(colorlegend, SIGNAL( toggled(bool) ), this, SLOT( toggleColorLegend(bool)));
+	connect(autoscale, SIGNAL( toggled(bool) ), this, SLOT( toggleAutoScale(bool)));
+	connect(shader, SIGNAL( toggled(bool) ), this, SLOT( toggleShader(bool)));
+	connect(mouseinput, SIGNAL( toggled(bool) ), dataWidget, SLOT( enableMouse(bool)));
+	connect(lightingswitch, SIGNAL( toggled(bool) ), this, SLOT( enableLighting(bool)));
+	connect(normals, SIGNAL( toggled(bool) ), this, SLOT( showNormals(bool)));
+	connect(normalsquality,  SIGNAL(valueChanged(int)), this, SLOT(setNormalQuality(int)) );
+	connect(normalslength,  SIGNAL(valueChanged(int)), this, SLOT(setNormalLength(int)) );
+			
+	setStandardView();
+
+	dataWidget->coordinates()->setLineSmooth(true);
+  dataWidget->coordinates()->setGridLinesColor(RGBA(0.35,0.35,0.35,1));
+	dataWidget->enableMouse(true);
+  dataWidget->setKeySpeed(15,20,20);
+
+  lightingdlg_ = new LightingDlg( this );
+  lightingdlg_->assign( dataWidget);
+	
+#if QT_VERSION < 0x040000 //todo - restore, when Qt4 re-implements preview functionality
+	datacolordlg_ = new QFileDialog( this );
+	QDir dir("./../../data/colormaps");
+	if (dir.exists("./../../data/colormaps"))
+		datacolordlg_->setDir("./../../data/colormaps");
+	datacolordlg_->setFilter("Colormap files (*.map *.MAP)");
+	colormappv_ = new ColorMapPreview;
+  datacolordlg_->setContentsPreviewEnabled( TRUE );
+	datacolordlg_->setContentsPreview( colormappv_, colormappv_ );
+	datacolordlg_->setPreviewMode( QFileDialog::Contents );
+	connect(datacolordlg_, SIGNAL(fileHighlighted(const QString&)), this, SLOT(adaptDataColors(const QString&)));
+#else
+	//connect(datacolordlg_, SIGNAL(filesSelected(const QStringList&)), this, SLOT(adaptDataColors4(const QStringList&)));
+#endif  
+	connect(filetypeCB, SIGNAL(activated(const QString&)), this, SLOT(setFileType(const QString&)));
+
+  filetypeCB->clear();
+
+  QStringList list = IO::outputFormatList();
+#if QT_VERSION < 0x040000
+  filetypeCB->insertStringList(list);
+#else
+  filetypeCB->insertItems(0,list);
+#endif
+  
+
+
+	filetype_ = filetypeCB->currentText();
+  dataWidget->setTitleFont( "Arial", 14, QFont::Normal );
+
+  grids->setEnabled(false);
+
+  PixmapWriter* pmhandler = (PixmapWriter*)IO::outputHandler("JPEG");
+  if (!pmhandler)
+    pmhandler = (PixmapWriter*)IO::outputHandler("jpeg"); //Qt4 naming scheme change
+  if (pmhandler)
+    pmhandler->setQuality(70);
+  
+  VectorWriter* handler = (VectorWriter*)IO::outputHandler("PDF");
+  handler->setTextMode(VectorWriter::TEX);
+  handler = (VectorWriter*)IO::outputHandler("EPS");
+  handler->setTextMode(VectorWriter::TEX);
+  handler = (VectorWriter*)IO::outputHandler("EPS_GZ");
+  if (handler) // with zlib support only
+    handler->setTextMode(VectorWriter::TEX);
+}
+
+void Mesh2MainWindow::open()
+{
+#if QT_VERSION < 0x040000
+  QString s = QFileDialog::getOpenFileName( "../../data", "GridData Files (*.mes *.MES)", this );
+#else
+  QString s = QFileDialog::getOpenFileName( this, "", "../../data", "GridData Files (*.mes *.MES)");
+#endif
+
+	if ( s.isEmpty() || !dataWidget)
+      return;
+	
+  QFileInfo fi( s );
+
+#if QT_VERSION < 0x040000
+  QString ext = fi.extension();   // ext = "gz"
+	QToolTip::add(filenameWidget, s);
+#else
+	filenameWidget->setToolTip(s);
+  QString ext = fi.suffix();
+#endif
+	filenameWidget->setText(fi.fileName());
+    qApp->processEvents(); // enforces repaint;  
+
+  if (IO::load(dataWidget, s, ext))
+	{
+		double a = dataWidget->facets().first;
+		double b = dataWidget->facets().second;
+
+		dimWidget->setText(QString("Cells ") + QString::number(a*b) 
+			+ " (" + QString::number(a) + "x" + QString::number(b) +")" );
+		
+		dataWidget->setResolution(3);
+	}
+ 	
+	for (unsigned i=0; i!=dataWidget->coordinates()->axes.size(); ++i)
+	{
+		dataWidget->coordinates()->axes[i].setMajors(4);
+		dataWidget->coordinates()->axes[i].setMinors(5);
+		dataWidget->coordinates()->axes[i].setLabelString("");
+	}
+	
+	updateColorLegend(4,5);
+	pickCoordSystem(activeCoordSystem);
+	dataWidget->showColorLegend(legend_);
+}
+
+void Mesh2MainWindow::createFunction(QString const& name)
+{
+	dataWidget->makeCurrent();
+  
+  dataWidget->legend()->setScale(LINEARSCALE);
+	for (unsigned i=0; i!=dataWidget->coordinates()->axes.size(); ++i)
+	{
+		dataWidget->coordinates()->axes[i].setMajors(7);
+		dataWidget->coordinates()->axes[i].setMinors(5);
+	}
+
+  if (name == QString("Rosenbrock")) 
+	{
+		Rosenbrock rosenbrock(*dataWidget);
+		
+		rosenbrock.setMesh(50,51);
+		rosenbrock.setDomain(-1.73,1.55,-1.5,1.95);
+		rosenbrock.setMinZ(-100);
+		
+		rosenbrock.create();
+	  
+    dataWidget->coordinates()->axes[Z1].setScale(LOG10SCALE);
+    dataWidget->coordinates()->axes[Z2].setScale(LOG10SCALE);
+    dataWidget->coordinates()->axes[Z3].setScale(LOG10SCALE);
+    dataWidget->coordinates()->axes[Z4].setScale(LOG10SCALE);
+    dataWidget->legend()->setScale(LOG10SCALE);
+	}
+	else if (name == QString("Hat")) 
+	{
+		Hat hat(*dataWidget);
+		
+		hat.setMesh(51,72);
+		hat.setDomain(-1.5,1.5,-1.5,1.5);
+		hat.create();	
+	}
+	else if (name == QString("Ripple")) 
+	{
+		Ripple ripple(*dataWidget);
+    ripple.setMesh(120,120);
+		ripple.create();	
+	}
+	else if (name == QString("Saddle")) 
+	{
+		Saddle saddle;
+		
+		saddle.setMesh(71,71);
+		double dom = 2.5;
+		saddle.setDomain(-dom, dom, -dom, dom);
+		saddle.assign(*dataWidget);
+		saddle.create();
+	}
+	else if (name == QString("Sombrero")) 
+	{
+		Mex mex;
+		
+		mex.setMesh(91,91);
+		double dom = 15;
+		mex.setDomain(-dom, dom, -dom, dom);
+		mex.create(*dataWidget);
+	}
+
+	double a = dataWidget->facets().first;
+	double b = dataWidget->facets().second;
+
+	dimWidget->setText(QString("Cells ") + QString::number(a*b) 
+		+ " (" + QString::number(a) + "x" + QString::number(b) +")" );
+
+	updateColorLegend(7,5);
+
+	dataWidget->coordinates()->axes[X1].setLabelString(QString("X1"));
+  dataWidget->coordinates()->axes[X2].setLabelString(QString("X2"));
+	dataWidget->coordinates()->axes[X3].setLabelString(QString("X3"));
+	dataWidget->coordinates()->axes[X4].setLabelString(QString("X4"));
+
+	dataWidget->coordinates()->axes[Y1].setLabelString(QString("Y1"));
+	dataWidget->coordinates()->axes[Y2].setLabelString(QString("Y2"));
+	dataWidget->coordinates()->axes[Y3].setLabelString(QString("Y3"));
+	dataWidget->coordinates()->axes[Y4].setLabelString(QString("Y4"));
+
+	dataWidget->coordinates()->axes[Z1].setLabelString(QString("Z1"));
+	dataWidget->coordinates()->axes[Z2].setLabelString(QString("Z2"));
+	dataWidget->coordinates()->axes[Z3].setLabelString(QString("Z3"));
+	dataWidget->coordinates()->axes[Z4].setLabelString(QString("Z4"));
+
+	pickCoordSystem(activeCoordSystem);
+}
+
+void Mesh2MainWindow::createPSurface(QString const& name)
+{
+	dataWidget->makeCurrent();
+	if (name == QString("Torus")) 
+	{
+		Torus sf(*dataWidget);
+		sf.create();
+	}
+	else if (name == QString("Seashell")) 
+	{
+		Seashell ss(*dataWidget);
+		ss.create();
+	}
+	else if (name == QString("Boy")) 
+	{
+		Boy boy(*dataWidget);
+		boy.create();
+	}
+	else if (name == QString("Dini")) 
+	{
+		Dini dini(*dataWidget);
+		dini.create();
+	}
+	else if (name == QString("Cone")) 
+	{
+    TripleField conepos;
+    CellField conecell;
+    createCone(conepos,conecell);
+    dataWidget->loadFromData(conepos, conecell);
+	}
+	for (unsigned i=0; i!=dataWidget->coordinates()->axes.size(); ++i)
+	{
+		dataWidget->coordinates()->axes[i].setMajors(7);
+		dataWidget->coordinates()->axes[i].setMinors(5);
+	}
+
+	double a = dataWidget->facets().first;
+	double b = dataWidget->facets().second;
+
+	dimWidget->setText(QString("Cells ") + QString::number(a*b) 
+		+ " (" + QString::number(a) + "x" + QString::number(b) +")" );
+
+	updateColorLegend(7,5);
+
+	dataWidget->coordinates()->axes[X1].setLabelString(QString("X1"));
+  dataWidget->coordinates()->axes[X2].setLabelString(QString("X2"));
+	dataWidget->coordinates()->axes[X3].setLabelString(QString("X3"));
+	dataWidget->coordinates()->axes[X4].setLabelString(QString("X4"));
+
+	dataWidget->coordinates()->axes[Y1].setLabelString(QString("Y1"));
+	dataWidget->coordinates()->axes[Y2].setLabelString(QString("Y2"));
+	dataWidget->coordinates()->axes[Y3].setLabelString(QString("Y3"));
+	dataWidget->coordinates()->axes[Y4].setLabelString(QString("Y4"));
+
+	dataWidget->coordinates()->axes[Z1].setLabelString(QString("Z1"));
+	dataWidget->coordinates()->axes[Z2].setLabelString(QString("Z2"));
+	dataWidget->coordinates()->axes[Z3].setLabelString(QString("Z3"));
+	dataWidget->coordinates()->axes[Z4].setLabelString(QString("Z4"));
+
+	pickCoordSystem(activeCoordSystem);
+}
+
+
+void Mesh2MainWindow::pickCoordSystem( QAction* action)
+{
+	if (!action || !dataWidget)
+		return;
+
+	activeCoordSystem = action;
+	
+	dataWidget->setTitle("QwtPlot3D (Use Ctrl-Alt-Shift-LeftBtn-Wheel or keyboard)");
+
+	if (!dataWidget->hasData())
+	{
+		double l = 0.6;
+		dataWidget->createCoordinateSystem(Triple(-l,-l,-l), Triple(l,l,l));
+		for (unsigned i=0; i!=dataWidget->coordinates()->axes.size(); ++i)
+		{
+			dataWidget->coordinates()->axes[i].setMajors(4);
+			dataWidget->coordinates()->axes[i].setMinors(5);
+		}
+	}			
+
+	if (action == Box || action == Frame)
+	{
+		if (action == Box)
+			dataWidget->setCoordinateStyle(BOX);
+		if (action == Frame)
+			dataWidget->setCoordinateStyle(FRAME);
+		grids->setEnabled(true);
+	}
+	else if (action == None)
+	{
+	  dataWidget->setTitle("QwtPlot3D (Use Ctrl-Alt-Shift-LeftBtn-Wheel or keyboard)");
+		dataWidget->setCoordinateStyle(NOCOORD);
+		grids->setEnabled(false);
+	}
+}
+
+void Mesh2MainWindow::pickPlotStyle( QAction* action )
+{
+	if (!action || !dataWidget)
+		return;
+
+	if (action == polygon)
+	{
+		dataWidget->setPlotStyle(FILLED);
+	}
+	else if (action == filledmesh)
+	{
+		dataWidget->setPlotStyle(FILLEDMESH);
+	}
+	else if (action == wireframe)
+	{
+		dataWidget->setPlotStyle(WIREFRAME);
+	}
+	else if (action == hiddenline)
+	{
+		dataWidget->setPlotStyle(HIDDENLINE);
+	}
+	else if (action == pointstyle)
+	{
+
+    dataWidget->setPlotStyle(Qwt3D::POINTS);
+//    Cone d(len,32);
+//    CrossHair d(0.003,0,true,false);
+//    dataWidget->setPlotStyle(d);
+	}
+	else
+	{
+		dataWidget->setPlotStyle(NOPLOT);
+	}
+	dataWidget->updateData();
+	dataWidget->updateGL();
+}
+
+void
+Mesh2MainWindow::pickFloorStyle( QAction* action )
+{
+	if (!action || !dataWidget)
+		return;
+
+	if (action == floordata)
+	{
+		dataWidget->setFloorStyle(FLOORDATA);
+	}
+	else if (action == flooriso)
+	{
+		dataWidget->setFloorStyle(FLOORISO);
+	}
+	else
+	{
+		dataWidget->setFloorStyle(NOFLOOR);
+	}
+	
+	dataWidget->updateData();
+	dataWidget->updateGL();
+}	
+
+void Mesh2MainWindow::setLeftGrid(bool b)
+{
+  setGrid(Qwt3D::LEFT,b);
+}
+void Mesh2MainWindow::setRightGrid(bool b)
+{
+  setGrid(Qwt3D::RIGHT,b);
+}
+void Mesh2MainWindow::setCeilGrid(bool b)
+{
+  setGrid(Qwt3D::CEIL,b);
+}
+void Mesh2MainWindow::setFloorGrid(bool b)
+{
+  setGrid(Qwt3D::FLOOR,b);
+}
+void Mesh2MainWindow::setFrontGrid(bool b)
+{
+  setGrid(Qwt3D::FRONT,b);
+}
+void Mesh2MainWindow::setBackGrid(bool b)
+{
+  setGrid(Qwt3D::BACK,b);
+}
+
+void Mesh2MainWindow::setGrid(Qwt3D::SIDE s, bool b)
+{
+  if (!dataWidget)
+		return;
+  
+ int sum = dataWidget->coordinates()->grids();
+
+  if (b)
+    sum |= s;
+  else
+    sum &= ~s;
+
+  dataWidget->coordinates()->setGridLines(sum!=Qwt3D::NOSIDEGRID, sum!=Qwt3D::NOSIDEGRID, sum);
+  dataWidget->updateGL();
+}
+
+void Mesh2MainWindow::resetColors()
+{
+	if (!dataWidget)
+		return;
+
+	const RGBA axc = RGBA(0,0,0,1);
+	const RGBA bgc = RGBA(1.0,1.0,1.0,1.0);
+	const RGBA msc = RGBA(0,0,0,1);
+	const RGBA nuc = RGBA(0,0,0,1);
+	const RGBA lbc = RGBA(0,0,0,1);
+	const RGBA tc = RGBA(0,0,0,1);
+
+	dataWidget->coordinates()->setAxesColor(axc);
+	dataWidget->setBackgroundColor(bgc);
+	dataWidget->setMeshColor(msc);
+	dataWidget->updateData();
+	dataWidget->coordinates()->setNumberColor(nuc);
+	dataWidget->coordinates()->setLabelColor(lbc);
+  dataWidget->setTitleColor(tc);
+
+	col_ = new StandardColor(dataWidget);
+	dataWidget->setDataColor(col_);
+	dataWidget->updateData();	
+	dataWidget->updateNormals();
+	dataWidget->updateGL();
+}
+
+
+void Mesh2MainWindow::pickAxesColor()
+{
+  QColor c = QColorDialog::getColor( Qt::white, this );
+  if ( !c.isValid() )
+		return;
+	RGBA rgb = Qt2GL(c);
+	dataWidget->coordinates()->setAxesColor(rgb);
+	dataWidget->updateGL();
+}
+
+void Mesh2MainWindow::pickBgColor()
+{
+  
+	QColor c = QColorDialog::getColor( Qt::white, this );
+  if ( !c.isValid() )
+		return;
+	RGBA rgb = Qt2GL(c);
+	dataWidget->setBackgroundColor(rgb);
+	dataWidget->updateGL();
+}
+
+void Mesh2MainWindow::pickMeshColor()
+{
+  
+	QColor c = QColorDialog::getColor( Qt::white, this );
+  if ( !c.isValid() )
+		return;
+	RGBA rgb = Qt2GL(c);
+	dataWidget->setMeshColor(rgb);
+	dataWidget->updateData();
+	dataWidget->updateGL();
+}
+
+void Mesh2MainWindow::pickNumberColor()
+{
+  
+	QColor c = QColorDialog::getColor( Qt::white, this );
+  if ( !c.isValid() )
+		return;
+	RGBA rgb = Qt2GL(c);
+	dataWidget->coordinates()->setNumberColor(rgb);
+	dataWidget->updateGL();
+}
+
+void Mesh2MainWindow::pickLabelColor()
+{
+ 	QColor c = QColorDialog::getColor( Qt::white, this );
+  if ( !c.isValid() )
+		return;
+	RGBA rgb = Qt2GL(c);
+	dataWidget->coordinates()->setLabelColor(rgb);
+	dataWidget->updateGL();
+}
+void Mesh2MainWindow::pickTitleColor()
+{
+ 	QColor c = QColorDialog::getColor( Qt::white, this );
+  if ( !c.isValid() )
+		return;
+	RGBA rgb = Qt2GL(c);
+	dataWidget->setTitleColor(rgb);
+	dataWidget->updateGL();
+}
+
+void Mesh2MainWindow::pickLighting()
+{
+	lightingdlg_->show();
+}
+
+void Mesh2MainWindow::pickDataColor()
+{
+#if QT_VERSION < 0x040000
+	datacolordlg_->show();
+#else
+  QString s =  QFileDialog::getOpenFileName( this, "", "./../../data/colormaps", "Colormap files (*.map *.MAP)");
+  adaptDataColors(s);
+#endif
+}
+
+void Mesh2MainWindow::adaptDataColors(const QString& fileName)
+{
+  ColorVector cv;
+	
+	if (!openColorMap(cv, fileName))
+		return;
+	
+	col_ = new StandardColor(dataWidget);
+	col_->setColorVector(cv);
+	
+	dataWidget->setDataColor(col_);
+	dataWidget->updateData();
+	dataWidget->updateNormals();
+	dataWidget->showColorLegend(legend_);
+  dataWidget->updateGL();
+}
+
+void Mesh2MainWindow::pickNumberFont()
+{
+	bool ok;
+	QFont font = QFontDialog::getFont(&ok, this );
+	if ( !ok ) 
+	{
+		return;
+	} 
+	dataWidget->coordinates()->setNumberFont(font);
+	dataWidget->updateGL();
+}
+void Mesh2MainWindow::pickLabelFont()
+{
+	bool ok;
+	QFont font = QFontDialog::getFont(&ok, this );
+	if ( !ok ) 
+	{
+		return;
+	} 
+	dataWidget->coordinates()->setLabelFont(font);
+	dataWidget->updateGL();
+}
+void Mesh2MainWindow::pickTitleFont()
+{
+	bool ok;
+	QFont font = QFontDialog::getFont(&ok, this );
+	if ( !ok ) 
+	{
+		return;
+	} 
+	dataWidget->setTitleFont(font.family(), font.pointSize(), font.weight(), font.italic());
+}
+
+void Mesh2MainWindow::resetFonts()
+{
+	dataWidget->coordinates()->setNumberFont(QFont("Courier", 12));
+	dataWidget->coordinates()->setLabelFont(QFont("Courier", 14, QFont::Bold));
+  dataWidget->setTitleFont( "Arial", 14, QFont::Normal );
+	dataWidget->updateGL();
+}
+
+void Mesh2MainWindow::setStandardView()
+{
+	dataWidget->setRotation(30,0,15);
+	dataWidget->setViewportShift(0.05,0);
+	dataWidget->setScale(1,1,1);
+	dataWidget->setZoom(0.95);
+}
+
+void Mesh2MainWindow::dumpImage()
+{
+	static int counter = 0;
+	if (!dataWidget)
+		return;
+	QString name;
+	
+	name = QString("dump_") + QString::number(counter++) + ".";
+  
+  if (filetype_ == "PS_GZ")
+    name += "ps.gz";
+  else if (filetype_ == "EPS_GZ")
+    name += "eps.gz";
+  else
+	  name += filetype_;
+  
+#if QT_VERSION < 0x040000
+  IO::save(dataWidget, name.lower(), filetype_);
+#else
+  VectorWriter* vw = (VectorWriter*)IO::outputHandler("PDF");
+  if (vw)
+    vw->setSortMode(VectorWriter::BSPSORT);
+  IO::save(dataWidget, name.toLower(), filetype_);
+#endif
+}
+
+/*!
+  Turns animation on or off
+*/
+void Mesh2MainWindow::toggleAnimation(bool val)
+{
+	if ( val )
+	{
+		timer->start( redrawWait ); // Wait this many msecs before redraw
+	}
+	else
+	{
+		timer->stop();
+	}
+}
+
+void Mesh2MainWindow::rotate()
+{
+	if (!dataWidget)
+		return;
+
+	dataWidget->setRotation(
+		int(dataWidget->xRotation() + 1) % 360,
+		int(dataWidget->yRotation() + 1) % 360,
+		int(dataWidget->zRotation() + 1) % 360
+		);
+}
+
+void
+Mesh2MainWindow::toggleProjectionMode(bool val)
+{
+	dataWidget->setOrtho(val);
+}
+
+void
+Mesh2MainWindow::toggleColorLegend(bool val)
+{
+	legend_ = val;
+	dataWidget->showColorLegend(val);
+}
+
+void
+Mesh2MainWindow::toggleAutoScale(bool val)
+{
+	dataWidget->coordinates()->setAutoScale(val);
+	dataWidget->updateGL();
+}
+
+void
+Mesh2MainWindow::toggleShader(bool val)
+{
+	if (val)
+		dataWidget->setShading(GOURAUD);
+	else
+		dataWidget->setShading(FLAT);
+}
+
+void
+Mesh2MainWindow::setPolygonOffset(int val)
+{
+	dataWidget->setPolygonOffset(val / 10.0);
+	dataWidget->updateData();
+	dataWidget->updateGL();
+}
+
+void
+Mesh2MainWindow::showRotate(double x, double y, double z)		
+{
+	rotateLabel->setText(" Angles ("  + QString::number(x,'g',3) + " ," 
+																	+ QString::number(y,'g',3) + " ,"
+																	+ QString::number(z,'g',3) + ")");
+}
+void
+Mesh2MainWindow::showShift(double x, double y)		
+{
+	shiftLabel->setText(" Shifts (" + QString::number(x,'g',3) + " ," 
+																	+ QString::number(y,'g',3) + " )"
+																	);
+}
+void
+Mesh2MainWindow::showScale(double x, double y, double z)		
+{
+	scaleLabel->setText(" Scales (" + QString::number(x,'g',3) + " ," 
+																	+ QString::number(y,'g',3) + " ,"
+																	+ QString::number(z,'g',3) + ")");
+}
+void
+Mesh2MainWindow::showZoom(double z)		
+{
+	zoomLabel->setText(" Zoom "  + QString::number(z,'g',3)); 
+}
+
+void Mesh2MainWindow::openMesh()
+{
+#if QT_VERSION < 0x040000
+  QString data(QFileDialog::getOpenFileName( "../../data", "nodes (*.nod)", this ) );
+  QString edges( QFileDialog::getOpenFileName( "../../data", "connectivities (*.cel)", this ) );
+#else
+  QString data( QFileDialog::getOpenFileName( this, "", "../../data", "nodes (*.nod)") );
+  QString edges( QFileDialog::getOpenFileName( this, "", "../../data", "connectivities (*.cel)") );
+#endif
+ 
+	if ( data.isEmpty() || edges.isEmpty() || !dataWidget)
+      return;
+
+
+	TripleField vdata;
+	CellField vpoly;
+	
+  readNodes(vdata, QWT3DLOCAL8BIT(data), NodeFilter());
+	readConnections(vpoly, QWT3DLOCAL8BIT(edges), CellFilter());
+
+  dataWidget->loadFromData(vdata, vpoly);
+	dimWidget->setText(QString("Cells ") + QString::number(dataWidget->facets().first));
+
+ 	for (unsigned i=0; i!=dataWidget->coordinates()->axes.size(); ++i)
+	{
+		dataWidget->coordinates()->axes[i].setMajors(4);
+		dataWidget->coordinates()->axes[i].setMinors(5);
+		dataWidget->coordinates()->axes[i].setLabelString(QString(""));
+	}
+
+	updateColorLegend(4,5);
+	pickCoordSystem(activeCoordSystem);
+}
+
+void
+Mesh2MainWindow::showNormals(bool val)
+{
+	dataWidget->showNormals(val);
+	dataWidget->updateNormals();
+	dataWidget->updateGL();
+}
+
+void
+Mesh2MainWindow::setNormalLength(int val)
+{
+	dataWidget->setNormalLength(val / 400.);
+	dataWidget->updateNormals();
+	dataWidget->updateGL();
+}
+
+void
+Mesh2MainWindow::setNormalQuality(int val)
+{
+	dataWidget->setNormalQuality(val);
+	dataWidget->updateNormals();
+	dataWidget->updateGL();
+}
+
+bool
+Mesh2MainWindow::openColorMap(ColorVector& cv, QString fname)
+{	
+  if (fname.isEmpty())
+    return false;
+  
+  ifstream file(QWT3DLOCAL8BIT(fname));
+
+	if (!file)
+		return false;
+	
+	RGBA rgb;
+	cv.clear();
+	
+	while ( file ) 
+	{		
+		file >> rgb.r >> rgb.g >> rgb.b;
+		file.ignore(1000,'\n');
+		if (!file.good())
+			break;
+		else
+		{
+			rgb.a = 1;
+			rgb.r /= 255;
+			rgb.g /= 255;
+			rgb.b /= 255;
+			cv.push_back(rgb);	
+		}
+	}
+
+	return true;
+}
+
+void 
+Mesh2MainWindow::updateColorLegend(int majors, int minors)
+{
+	dataWidget->legend()->setMajors(majors);
+	dataWidget->legend()->setMinors(minors);
+	double start, stop;
+	dataWidget->coordinates()->axes[Z1].limits(start,stop);
+	dataWidget->legend()->setLimits(start, stop);
+}		
+
+void Mesh2MainWindow::setFileType(QString const& name)
+{
+	filetype_ = name;	
+}
+
+void Mesh2MainWindow::enableLighting(bool val)
+{
+  dataWidget->enableLighting(val);
+  dataWidget->illuminate(0);
+  dataWidget->updateGL();
+}
diff --git a/examples/mesh2/src/mesh2mainwindow.h b/examples/mesh2/src/mesh2mainwindow.h
new file mode 100644
index 0000000..36d7381
--- /dev/null
+++ b/examples/mesh2/src/mesh2mainwindow.h
@@ -0,0 +1,134 @@
+#ifndef mesh2mainwindow_h__2004_03_07_13_38_begin_guarded_code
+#define mesh2mainwindow_h__2004_03_07_13_38_begin_guarded_code
+
+#include "../../../include/qwt3d_surfaceplot.h"
+
+
+#if QT_VERSION < 0x040000
+#include "mesh2mainwindowbase.h"
+#else
+#include "ui_mesh2mainwindowbase4.h"
+#include "designerworkaround.h"
+#endif
+
+
+
+//MOC_SKIP_BEGIN
+#if QT_VERSION < 0x040000
+  class DummyBase : public Mesh2MainWindowBase
+  {
+  public:
+    DummyBase(QWidget* parent = 0) 
+      : Mesh2MainWindowBase(parent) 
+    {
+    } 
+  };
+#else
+  class DummyBase : public QMainWindow, protected Ui::MainWindow, protected DesignerWorkaround
+  {
+  public:
+    DummyBase(QWidget* parent = 0) 
+      : QMainWindow(parent) 
+    {
+    } 
+  };
+#endif
+//MOC_SKIP_END
+
+class QLabel;
+class QTimer;
+class QAction;
+class QFileDialog;
+class LightingDlg;
+class ColorMapPreview;
+
+class Mesh2MainWindow : public DummyBase
+{
+	Q_OBJECT
+public:
+	Mesh2MainWindow( QWidget* parent = 0 );
+	~Mesh2MainWindow();
+
+  Qwt3D::SurfacePlot* dataWidget;
+	
+public slots:
+	void open();
+	void openMesh();
+
+	void createFunction(QString const& name);
+	void createPSurface(QString const& name);
+	void setFileType(QString const& name);
+
+	void pickCoordSystem( QAction* );
+	void pickPlotStyle( QAction* );
+	void pickFloorStyle( QAction* );
+	void pickAxesColor();
+	void pickBgColor();
+	void pickMeshColor();
+	void pickNumberColor();
+	void pickLabelColor();
+	void pickTitleColor();
+	void pickDataColor();
+	void pickLighting();
+	void resetColors();
+	void pickNumberFont();
+	void pickLabelFont();
+	void pickTitleFont();
+	void resetFonts();
+ 	void setStandardView();
+	void dumpImage();
+	void toggleAnimation(bool);
+	void toggleProjectionMode(bool);
+	void toggleColorLegend(bool);
+	void toggleAutoScale(bool val);
+	void toggleShader(bool val);
+	void rotate();
+	void setPolygonOffset(int);
+
+	void showRotate(double x, double y, double z);
+	void showShift(double x, double y);
+	void showScale(double x, double y, double z);
+	void showZoom(double z);
+	void showNormals(bool val);
+	void setNormalQuality(int);
+	void setNormalLength(int);
+	bool openColorMap(Qwt3D::ColorVector& cv, QString fname);
+	void adaptDataColors(const QString&);
+	void updateColorLegend(int majors, int minors);
+
+	void setLeftGrid( bool b );
+	void setRightGrid( bool b );
+	void setCeilGrid( bool b );
+	void setFloorGrid( bool b );
+	void setFrontGrid( bool b );
+	void setBackGrid( bool b );
+  void setGrid( Qwt3D::SIDE, bool );
+
+  void enableLighting(bool val);
+
+private:
+	QLabel *filenameWidget, *dimWidget,
+		*rotateLabel, *shiftLabel, *scaleLabel, *zoomLabel;
+	
+	QTimer* timer;
+	int redrawWait;
+
+	QAction* activeCoordSystem;
+
+	bool legend_;
+	Qwt3D::StandardColor* col_;
+
+	QFileDialog* datacolordlg_;
+    LightingDlg* lightingdlg_;
+	QString filetype_;
+
+    // convenience compatib. code
+    bool connectA (const QObject* sender, const char * slot);
+    bool connectAG (const QObject* sender, const char * slot);
+
+#if QT_VERSION < 0x040000
+	ColorMapPreview* colormappv_;
+#endif
+};
+
+#endif /* include guarded */
diff --git a/examples/mesh2/src/mesh2mainwindowbase.ui b/examples/mesh2/src/mesh2mainwindowbase.ui
new file mode 100644
index 0000000..a6f03cb
--- /dev/null
+++ b/examples/mesh2/src/mesh2mainwindowbase.ui
@@ -0,0 +1,1728 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>Mesh2MainWindowBase</class>
+<widget class="QMainWindow">
+    <property name="name">
+        <cstring>Mesh2MainWindowBase</cstring>
+    </property>
+    <property name="geometry">
+        <rect>
+            <x>0</x>
+            <y>0</y>
+            <width>954</width>
+            <height>710</height>
+        </rect>
+    </property>
+    <property name="sizePolicy">
+        <sizepolicy>
+            <hsizetype>5</hsizetype>
+            <vsizetype>5</vsizetype>
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+        </sizepolicy>
+    </property>
+    <property name="minimumSize">
+        <size>
+            <width>381</width>
+            <height>328</height>
+        </size>
+    </property>
+    <property name="caption">
+        <string>Mesh2</string>
+    </property>
+    <property name="dockWindowsMovable">
+        <bool>false</bool>
+    </property>
+    <grid>
+        <property name="name">
+            <cstring>unnamed</cstring>
+        </property>
+        <property name="margin">
+            <number>11</number>
+        </property>
+        <property name="spacing">
+            <number>6</number>
+        </property>
+        <spacer row="1" column="1">
+            <property name="name">
+                <cstring>Spacer4</cstring>
+            </property>
+            <property name="orientation">
+                <enum>Vertical</enum>
+            </property>
+            <property name="sizeType">
+                <enum>Fixed</enum>
+            </property>
+            <property name="sizeHint">
+                <size>
+                    <width>16</width>
+                    <height>50</height>
+                </size>
+            </property>
+        </spacer>
+        <widget class="QLayoutWidget" row="0" column="1">
+            <property name="name">
+                <cstring>Layout11</cstring>
+            </property>
+            <vbox>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+                <property name="margin">
+                    <number>0</number>
+                </property>
+                <property name="spacing">
+                    <number>6</number>
+                </property>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>Layout9</cstring>
+                    </property>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <property name="margin">
+                            <number>0</number>
+                        </property>
+                        <property name="spacing">
+                            <number>6</number>
+                        </property>
+                        <widget class="QCheckBox">
+                            <property name="name">
+                                <cstring>projection</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>0</hsizetype>
+                                    <vsizetype>0</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="text">
+                                <string>Ortho</string>
+                            </property>
+                            <property name="checked">
+                                <bool>true</bool>
+                            </property>
+                        </widget>
+                        <widget class="QCheckBox">
+                            <property name="name">
+                                <cstring>colorlegend</cstring>
+                            </property>
+                            <property name="enabled">
+                                <bool>true</bool>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>0</hsizetype>
+                                    <vsizetype>0</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="text">
+                                <string>Legend</string>
+                            </property>
+                        </widget>
+                        <widget class="QCheckBox">
+                            <property name="name">
+                                <cstring>autoscale</cstring>
+                            </property>
+                            <property name="enabled">
+                                <bool>true</bool>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>0</hsizetype>
+                                    <vsizetype>0</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="text">
+                                <string>Autoscale</string>
+                            </property>
+                            <property name="checked">
+                                <bool>true</bool>
+                            </property>
+                            <property name="toolTip" stdset="0">
+                                <string>Autoscale axes</string>
+                            </property>
+                            <property name="whatsThis" stdset="0">
+                                <string>Autoscale axes</string>
+                            </property>
+                        </widget>
+                        <widget class="QCheckBox">
+                            <property name="name">
+                                <cstring>mouseinput</cstring>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>0</hsizetype>
+                                    <vsizetype>0</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="text">
+                                <string>Mouse</string>
+                            </property>
+                            <property name="checked">
+                                <bool>true</bool>
+                            </property>
+                            <property name="toolTip" stdset="0">
+                                <string>Enable mouse input</string>
+                            </property>
+                        </widget>
+                        <widget class="QCheckBox">
+                            <property name="name">
+                                <cstring>shader</cstring>
+                            </property>
+                            <property name="enabled">
+                                <bool>true</bool>
+                            </property>
+                            <property name="sizePolicy">
+                                <sizepolicy>
+                                    <hsizetype>0</hsizetype>
+                                    <vsizetype>0</vsizetype>
+                                    <horstretch>0</horstretch>
+                                    <verstretch>0</verstretch>
+                                </sizepolicy>
+                            </property>
+                            <property name="text">
+                                <string>Shading</string>
+                            </property>
+                            <property name="checked">
+                                <bool>true</bool>
+                            </property>
+                            <property name="toolTip" stdset="0">
+                                <string>Checked means Gouraud (smooth) shading, flat else</string>
+                            </property>
+                            <property name="whatsThis" stdset="0">
+                                <string>Checked means Gouraud (smooth) shading, flat else</string>
+                            </property>
+                        </widget>
+                    </vbox>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>Layout7</cstring>
+                    </property>
+                    <grid>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <property name="margin">
+                            <number>0</number>
+                        </property>
+                        <property name="spacing">
+                            <number>6</number>
+                        </property>
+                        <widget class="QLayoutWidget" row="1" column="0">
+                            <property name="name">
+                                <cstring>Layout6</cstring>
+                            </property>
+                            <hbox>
+                                <property name="name">
+                                    <cstring>unnamed</cstring>
+                                </property>
+                                <property name="margin">
+                                    <number>0</number>
+                                </property>
+                                <property name="spacing">
+                                    <number>6</number>
+                                </property>
+                                <widget class="QSlider">
+                                    <property name="name">
+                                        <cstring>normalsquality</cstring>
+                                    </property>
+                                    <property name="minValue">
+                                        <number>3</number>
+                                    </property>
+                                    <property name="maxValue">
+                                        <number>32</number>
+                                    </property>
+                                    <property name="pageStep">
+                                        <number>4</number>
+                                    </property>
+                                    <property name="tracking">
+                                        <bool>true</bool>
+                                    </property>
+                                    <property name="orientation">
+                                        <enum>Vertical</enum>
+                                    </property>
+                                    <property name="tickmarks">
+                                        <enum>Above</enum>
+                                    </property>
+                                    <property name="tickInterval">
+                                        <number>1</number>
+                                    </property>
+                                    <property name="toolTip" stdset="0">
+                                        <string>Quality (Roundness)</string>
+                                    </property>
+                                </widget>
+                                <widget class="QSlider">
+                                    <property name="name">
+                                        <cstring>normalslength</cstring>
+                                    </property>
+                                    <property name="minValue">
+                                        <number>1</number>
+                                    </property>
+                                    <property name="maxValue">
+                                        <number>100</number>
+                                    </property>
+                                    <property name="pageStep">
+                                        <number>5</number>
+                                    </property>
+                                    <property name="value">
+                                        <number>8</number>
+                                    </property>
+                                    <property name="tracking">
+                                        <bool>true</bool>
+                                    </property>
+                                    <property name="orientation">
+                                        <enum>Vertical</enum>
+                                    </property>
+                                    <property name="tickmarks">
+                                        <enum>Above</enum>
+                                    </property>
+                                    <property name="tickInterval">
+                                        <number>5</number>
+                                    </property>
+                                    <property name="toolTip" stdset="0">
+                                        <string>Length</string>
+                                    </property>
+                                </widget>
+                            </hbox>
+                        </widget>
+                        <widget class="QLabel" row="0" column="0">
+                            <property name="name">
+                                <cstring>TextLabel1</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Normals</string>
+                            </property>
+                        </widget>
+                    </grid>
+                </widget>
+            </vbox>
+        </widget>
+        <widget class="QFrame" row="0" column="0">
+            <property name="name">
+                <cstring>frame</cstring>
+            </property>
+            <property name="frameShape">
+                <enum>StyledPanel</enum>
+            </property>
+            <property name="frameShadow">
+                <enum>Sunken</enum>
+            </property>
+        </widget>
+        <widget class="QLayoutWidget" row="1" column="0">
+            <property name="name">
+                <cstring>Layout8</cstring>
+            </property>
+            <hbox>
+                <property name="name">
+                    <cstring>unnamed</cstring>
+                </property>
+                <property name="margin">
+                    <number>0</number>
+                </property>
+                <property name="spacing">
+                    <number>6</number>
+                </property>
+                <widget class="QPushButton">
+                    <property name="name">
+                        <cstring>normButton</cstring>
+                    </property>
+                    <property name="sizePolicy">
+                        <sizepolicy>
+                            <hsizetype>0</hsizetype>
+                            <vsizetype>0</vsizetype>
+                            <horstretch>0</horstretch>
+                            <verstretch>0</verstretch>
+                        </sizepolicy>
+                    </property>
+                    <property name="minimumSize">
+                        <size>
+                            <width>50</width>
+                            <height>35</height>
+                        </size>
+                    </property>
+                    <property name="maximumSize">
+                        <size>
+                            <width>50</width>
+                            <height>35</height>
+                        </size>
+                    </property>
+                    <property name="cursor">
+                        <cursor>0</cursor>
+                    </property>
+                    <property name="text">
+                        <string>Std</string>
+                    </property>
+                    <property name="toolTip" stdset="0">
+                        <string>Set standard view</string>
+                    </property>
+                </widget>
+                <widget class="QPushButton">
+                    <property name="name">
+                        <cstring>lighting</cstring>
+                    </property>
+                    <property name="enabled">
+                        <bool>false</bool>
+                    </property>
+                    <property name="sizePolicy">
+                        <sizepolicy>
+                            <hsizetype>0</hsizetype>
+                            <vsizetype>0</vsizetype>
+                            <horstretch>0</horstretch>
+                            <verstretch>0</verstretch>
+                        </sizepolicy>
+                    </property>
+                    <property name="minimumSize">
+                        <size>
+                            <width>60</width>
+                            <height>35</height>
+                        </size>
+                    </property>
+                    <property name="maximumSize">
+                        <size>
+                            <width>80</width>
+                            <height>35</height>
+                        </size>
+                    </property>
+                    <property name="cursor">
+                        <cursor>0</cursor>
+                    </property>
+                    <property name="text">
+                        <string>Lighting</string>
+                    </property>
+                    <property name="toolTip" stdset="0">
+                        <string>Calibrate Lighting</string>
+                    </property>
+                </widget>
+                <widget class="QCheckBox">
+                    <property name="name">
+                        <cstring>lightingswitch</cstring>
+                    </property>
+                    <property name="text">
+                        <string></string>
+                    </property>
+                    <property name="toolTip" stdset="0">
+                        <string>Turn Lighting on/off.</string>
+                    </property>
+                </widget>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>Layout10</cstring>
+                    </property>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <property name="margin">
+                            <number>0</number>
+                        </property>
+                        <property name="spacing">
+                            <number>6</number>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>TextLabel2</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Polygon Offset</string>
+                            </property>
+                            <property name="alignment">
+                                <set>AlignCenter</set>
+                            </property>
+                        </widget>
+                        <widget class="QSlider">
+                            <property name="name">
+                                <cstring>offsSlider</cstring>
+                            </property>
+                            <property name="minimumSize">
+                                <size>
+                                    <width>0</width>
+                                    <height>25</height>
+                                </size>
+                            </property>
+                            <property name="maxValue">
+                                <number>30</number>
+                            </property>
+                            <property name="lineStep">
+                                <number>1</number>
+                            </property>
+                            <property name="pageStep">
+                                <number>5</number>
+                            </property>
+                            <property name="value">
+                                <number>5</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                            <property name="tickmarks">
+                                <enum>Above</enum>
+                            </property>
+                            <property name="tickInterval">
+                                <number>2</number>
+                            </property>
+                            <property name="toolTip" stdset="0">
+                                <string>Increase surface quality by setting polygon offset (OpenGL specific)</string>
+                            </property>
+                        </widget>
+                    </vbox>
+                </widget>
+                <spacer>
+                    <property name="name">
+                        <cstring>Spacer5</cstring>
+                    </property>
+                    <property name="orientation">
+                        <enum>Horizontal</enum>
+                    </property>
+                    <property name="sizeType">
+                        <enum>Preferred</enum>
+                    </property>
+                    <property name="sizeHint">
+                        <size>
+                            <width>41</width>
+                            <height>16</height>
+                        </size>
+                    </property>
+                </spacer>
+                <widget class="QLayoutWidget">
+                    <property name="name">
+                        <cstring>Layout9</cstring>
+                    </property>
+                    <vbox>
+                        <property name="name">
+                            <cstring>unnamed</cstring>
+                        </property>
+                        <property name="margin">
+                            <number>0</number>
+                        </property>
+                        <property name="spacing">
+                            <number>6</number>
+                        </property>
+                        <widget class="QLabel">
+                            <property name="name">
+                                <cstring>TextLabel1_2</cstring>
+                            </property>
+                            <property name="text">
+                                <string>Resolution</string>
+                            </property>
+                            <property name="alignment">
+                                <set>AlignCenter</set>
+                            </property>
+                        </widget>
+                        <widget class="QSlider">
+                            <property name="name">
+                                <cstring>resSlider</cstring>
+                            </property>
+                            <property name="minimumSize">
+                                <size>
+                                    <width>0</width>
+                                    <height>25</height>
+                                </size>
+                            </property>
+                            <property name="minValue">
+                                <number>1</number>
+                            </property>
+                            <property name="maxValue">
+                                <number>100</number>
+                            </property>
+                            <property name="lineStep">
+                                <number>1</number>
+                            </property>
+                            <property name="orientation">
+                                <enum>Horizontal</enum>
+                            </property>
+                            <property name="tickmarks">
+                                <enum>Above</enum>
+                            </property>
+                            <property name="tickInterval">
+                                <number>5</number>
+                            </property>
+                            <property name="toolTip" stdset="0">
+                                <string>Set data resolution (no effect for nonrectangular data)</string>
+                            </property>
+                        </widget>
+                    </vbox>
+                </widget>
+            </hbox>
+        </widget>
+    </grid>
+</widget>
+<menubar>
+    <property name="name">
+        <cstring>menubar</cstring>
+    </property>
+    <item text="&File" name="file">
+        <action name="openFile"/>
+        <action name="openMeshFile"/>
+        <action name="animation"/>
+        <action name="Exit"/>
+    </item>
+    <item text="&Color" name="PopupMenu_3">
+        <action name="axescolor"/>
+        <action name="backgroundcolor"/>
+        <action name="meshcolor"/>
+        <action name="numbercolor"/>
+        <action name="labelcolor"/>
+        <action name="titlecolor"/>
+        <action name="datacolor"/>
+        <action name="resetcolor"/>
+    </item>
+    <item text="&Font" name="PopupMenu">
+        <action name="numberfont"/>
+        <action name="labelfont"/>
+        <action name="titlefont"/>
+        <action name="resetfont"/>
+    </item>
+</menubar>
+<toolbars>
+    <toolbar dock="2">
+        <property name="name">
+            <cstring>Toolbar</cstring>
+        </property>
+        <property name="enabled">
+            <bool>true</bool>
+        </property>
+        <property name="cursor">
+            <cursor>0</cursor>
+        </property>
+        <property name="movingEnabled">
+            <bool>false</bool>
+        </property>
+        <property name="horizontallyStretchable">
+            <bool>false</bool>
+        </property>
+        <property name="verticallyStretchable">
+            <bool>false</bool>
+        </property>
+        <property name="label">
+            <string>Toolbar</string>
+        </property>
+        <action name="openFile"/>
+        <action name="openMeshFile"/>
+        <action name="dump"/>
+        <widget class="QComboBox">
+            <item>
+                <property name="text">
+                    <string>png</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>bmp</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>ppm</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>xpm</string>
+                </property>
+            </item>
+            <property name="name">
+                <cstring>filetypeCB</cstring>
+            </property>
+        </widget>
+        <widget class="Spacer">
+            <property name="name">
+                <cstring>Spacer3</cstring>
+            </property>
+            <property name="orientation">
+                <enum>Horizontal</enum>
+            </property>
+            <property name="sizeType">
+                <enum>Fixed</enum>
+            </property>
+            <property name="sizeHint">
+                <size>
+                    <width>20</width>
+                    <height>20</height>
+                </size>
+            </property>
+        </widget>
+        <widget class="QComboBox">
+            <item>
+                <property name="text">
+                    <string>---</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>Hat</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>Rosenbrock</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>Saddle</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>Sombrero</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>Ripple</string>
+                </property>
+            </item>
+            <property name="name">
+                <cstring>functionCB</cstring>
+            </property>
+            <property name="minimumSize">
+                <size>
+                    <width>150</width>
+                    <height>0</height>
+                </size>
+            </property>
+            <property name="toolTip" stdset="0">
+                <string>Display function</string>
+            </property>
+        </widget>
+        <widget class="QComboBox">
+            <item>
+                <property name="text">
+                    <string>---</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>Torus</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>Seashell</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>Boy</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>Dini</string>
+                </property>
+            </item>
+            <item>
+                <property name="text">
+                    <string>Cone</string>
+                </property>
+            </item>
+            <property name="name">
+                <cstring>psurfaceCB</cstring>
+            </property>
+            <property name="toolTip" stdset="0">
+                <string>Display parametric surface. Turn Lighting on for better quality.</string>
+            </property>
+        </widget>
+        <action name="animation"/>
+    </toolbar>
+    <toolbar dock="2">
+        <property name="name">
+            <cstring>Toolbar_2</cstring>
+        </property>
+        <property name="enabled">
+            <bool>true</bool>
+        </property>
+        <property name="cursor">
+            <cursor>0</cursor>
+        </property>
+        <property name="resizeEnabled">
+            <bool>false</bool>
+        </property>
+        <property name="movingEnabled">
+            <bool>false</bool>
+        </property>
+        <property name="horizontallyStretchable">
+            <bool>false</bool>
+        </property>
+        <property name="verticallyStretchable">
+            <bool>false</bool>
+        </property>
+        <property name="label">
+            <string>Toolbar_2</string>
+        </property>
+        <action name="Frame"/>
+        <action name="Box"/>
+        <action name="None"/>
+        <separator/>
+        <action name="front"/>
+        <action name="back"/>
+        <action name="right"/>
+        <action name="left"/>
+        <action name="ceil"/>
+        <action name="floor"/>
+        <separator/>
+        <action name="pointstyle"/>
+        <action name="wireframe"/>
+        <action name="hiddenline"/>
+        <action name="polygon"/>
+        <action name="filledmesh"/>
+        <action name="nodata"/>
+        <separator/>
+        <action name="floordata"/>
+        <action name="flooriso"/>
+        <action name="floornone"/>
+        <action name="normals"/>
+    </toolbar>
+</toolbars>
+<actions>
+    <action>
+        <property name="name">
+            <cstring>openFile</cstring>
+        </property>
+        <property name="iconSet">
+            <iconset>image0</iconset>
+        </property>
+        <property name="text">
+            <string>Open File</string>
+        </property>
+        <property name="menuText">
+            <string>&Open File</string>
+        </property>
+        <property name="statusTip">
+            <string>Open File</string>
+        </property>
+        <property name="accel">
+            <string>Ctrl+O</string>
+        </property>
+    </action>
+    <action>
+        <property name="name">
+            <cstring>Exit</cstring>
+        </property>
+        <property name="text">
+            <string>Exit</string>
+        </property>
+        <property name="menuText">
+            <string>Exit</string>
+        </property>
+        <property name="statusTip">
+            <string>Exit</string>
+        </property>
+        <property name="accel">
+            <string>Ctrl+Q</string>
+        </property>
+    </action>
+    <actiongroup>
+        <property name="name">
+            <cstring>coord</cstring>
+        </property>
+        <property name="text">
+            <string>Coordinates</string>
+        </property>
+        <property name="menuText">
+            <string>&Coord</string>
+        </property>
+        <property name="statusTip">
+            <string>Coordinates</string>
+        </property>
+        <property name="usesDropDown">
+            <bool>false</bool>
+        </property>
+        <action>
+            <property name="name">
+                <cstring>Box</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image1</iconset>
+            </property>
+            <property name="text">
+                <string>Box</string>
+            </property>
+            <property name="menuText">
+                <string>Box</string>
+            </property>
+            <property name="toolTip">
+                <string>Box</string>
+            </property>
+            <property name="statusTip">
+                <string>Box</string>
+            </property>
+            <property name="accel">
+                <string>A</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>Frame</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image2</iconset>
+            </property>
+            <property name="text">
+                <string>Frame</string>
+            </property>
+            <property name="menuText">
+                <string>&Frame</string>
+            </property>
+            <property name="toolTip">
+                <string>Frame</string>
+            </property>
+            <property name="statusTip">
+                <string>Frame</string>
+            </property>
+            <property name="accel">
+                <string>F</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>None</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="on">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image3</iconset>
+            </property>
+            <property name="text">
+                <string>No Axes</string>
+            </property>
+            <property name="menuText">
+                <string>No Axes</string>
+            </property>
+            <property name="toolTip">
+                <string>No Axes</string>
+            </property>
+            <property name="statusTip">
+                <string>No Axes</string>
+            </property>
+        </action>
+    </actiongroup>
+    <action>
+        <property name="name">
+            <cstring>animation</cstring>
+        </property>
+        <property name="toggleAction">
+            <bool>true</bool>
+        </property>
+        <property name="iconSet">
+            <iconset>image4</iconset>
+        </property>
+        <property name="text">
+            <string>Animation</string>
+        </property>
+        <property name="menuText">
+            <string>Animation</string>
+        </property>
+        <property name="statusTip">
+            <string>Animation</string>
+        </property>
+        <property name="accel">
+            <string>Ctrl+A</string>
+        </property>
+    </action>
+    <action>
+        <property name="name">
+            <cstring>dump</cstring>
+        </property>
+        <property name="iconSet">
+            <iconset>image5</iconset>
+        </property>
+        <property name="text">
+            <string>Dump Content</string>
+        </property>
+        <property name="menuText">
+            <string>Dump Content</string>
+        </property>
+        <property name="toolTip">
+            <string>Dump Content</string>
+        </property>
+        <property name="statusTip">
+            <string>Dump Content</string>
+        </property>
+    </action>
+    <actiongroup>
+        <property name="name">
+            <cstring>plotstyle</cstring>
+        </property>
+        <property name="text">
+            <string>Plot Style</string>
+        </property>
+        <property name="menuText">
+            <string>Plot Style</string>
+        </property>
+        <property name="statusTip">
+            <string>Plot Style</string>
+        </property>
+        <property name="usesDropDown">
+            <bool>false</bool>
+        </property>
+        <action>
+            <property name="name">
+                <cstring>wireframe</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="enabled">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image6</iconset>
+            </property>
+            <property name="text">
+                <string>Wireframe</string>
+            </property>
+            <property name="menuText">
+                <string>Wireframe</string>
+            </property>
+            <property name="toolTip">
+                <string>Wireframe</string>
+            </property>
+            <property name="statusTip">
+                <string>Wireframe</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>hiddenline</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="enabled">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image7</iconset>
+            </property>
+            <property name="text">
+                <string>Hidden Line</string>
+            </property>
+            <property name="menuText">
+                <string>Hidden Line</string>
+            </property>
+            <property name="toolTip">
+                <string>Hidden Line (EXPERIMENTAL!)</string>
+            </property>
+            <property name="statusTip">
+                <string>Hidden Line (EXPERIMENTAL!)</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>polygon</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="enabled">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image8</iconset>
+            </property>
+            <property name="text">
+                <string>Polygon only</string>
+            </property>
+            <property name="menuText">
+                <string>Polygon only</string>
+            </property>
+            <property name="toolTip">
+                <string>Polygon only</string>
+            </property>
+            <property name="statusTip">
+                <string>Polygon only</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>filledmesh</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="on">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image9</iconset>
+            </property>
+            <property name="text">
+                <string>Mesh & filled Polygons</string>
+            </property>
+            <property name="menuText">
+                <string>Mesh & filled Polygons</string>
+            </property>
+            <property name="toolTip">
+                <string>Mesh & filled Polygons</string>
+            </property>
+            <property name="statusTip">
+                <string>Mesh & filled Polygons</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>nodata</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="on">
+                <bool>false</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image10</iconset>
+            </property>
+            <property name="text">
+                <string>No Data</string>
+            </property>
+            <property name="menuText">
+                <string>No Data</string>
+            </property>
+            <property name="toolTip">
+                <string>No Data</string>
+            </property>
+            <property name="statusTip">
+                <string>No Data</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>pointstyle</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image11</iconset>
+            </property>
+            <property name="text">
+                <string>Points</string>
+            </property>
+            <property name="menuText">
+                <string>Points</string>
+            </property>
+            <property name="toolTip">
+                <string>Points</string>
+            </property>
+        </action>
+    </actiongroup>
+    <actiongroup>
+        <property name="name">
+            <cstring>color</cstring>
+        </property>
+        <property name="text">
+            <string>Color</string>
+        </property>
+        <property name="menuText">
+            <string>&Color</string>
+        </property>
+        <property name="toolTip">
+            <string>Color</string>
+        </property>
+        <property name="statusTip">
+            <string>Color</string>
+        </property>
+        <property name="exclusive">
+            <bool>false</bool>
+        </property>
+        <property name="usesDropDown">
+            <bool>false</bool>
+        </property>
+        <action>
+            <property name="name">
+                <cstring>axescolor</cstring>
+            </property>
+            <property name="text">
+                <string>Axes</string>
+            </property>
+            <property name="menuText">
+                <string>&Axes</string>
+            </property>
+            <property name="toolTip">
+                <string>Axes</string>
+            </property>
+            <property name="statusTip">
+                <string>Axes</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>backgroundcolor</cstring>
+            </property>
+            <property name="text">
+                <string>Background</string>
+            </property>
+            <property name="menuText">
+                <string>&Background</string>
+            </property>
+            <property name="toolTip">
+                <string>Background</string>
+            </property>
+            <property name="statusTip">
+                <string>Background</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>meshcolor</cstring>
+            </property>
+            <property name="text">
+                <string>Mesh</string>
+            </property>
+            <property name="menuText">
+                <string>&Mesh</string>
+            </property>
+            <property name="toolTip">
+                <string>Mesh</string>
+            </property>
+            <property name="statusTip">
+                <string>Mesh</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>numbercolor</cstring>
+            </property>
+            <property name="text">
+                <string>Numbers</string>
+            </property>
+            <property name="menuText">
+                <string>&Numbers</string>
+            </property>
+            <property name="toolTip">
+                <string>Numbers</string>
+            </property>
+            <property name="statusTip">
+                <string>Numbers</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>labelcolor</cstring>
+            </property>
+            <property name="text">
+                <string>Label</string>
+            </property>
+            <property name="menuText">
+                <string>&Label</string>
+            </property>
+            <property name="toolTip">
+                <string>Label</string>
+            </property>
+            <property name="statusTip">
+                <string>Label</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>titlecolor</cstring>
+            </property>
+            <property name="text">
+                <string>Caption</string>
+            </property>
+            <property name="menuText">
+                <string>Caption</string>
+            </property>
+            <property name="toolTip">
+                <string>Caption</string>
+            </property>
+            <property name="statusTip">
+                <string>Caption</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>datacolor</cstring>
+            </property>
+            <property name="text">
+                <string>Data Color</string>
+            </property>
+            <property name="menuText">
+                <string>Data Color</string>
+            </property>
+            <property name="toolTip">
+                <string>Data Color</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>resetcolor</cstring>
+            </property>
+            <property name="text">
+                <string>Reset</string>
+            </property>
+            <property name="menuText">
+                <string>&Reset</string>
+            </property>
+            <property name="toolTip">
+                <string>Reset</string>
+            </property>
+            <property name="statusTip">
+                <string>Reset</string>
+            </property>
+        </action>
+    </actiongroup>
+    <actiongroup>
+        <property name="name">
+            <cstring>font</cstring>
+        </property>
+        <property name="text">
+            <string>Fonts</string>
+        </property>
+        <property name="menuText">
+            <string>&Fonts</string>
+        </property>
+        <property name="statusTip">
+            <string>Fonts</string>
+        </property>
+        <property name="exclusive">
+            <bool>false</bool>
+        </property>
+        <property name="usesDropDown">
+            <bool>false</bool>
+        </property>
+        <action>
+            <property name="name">
+                <cstring>numberfont</cstring>
+            </property>
+            <property name="text">
+                <string>Scale numbering</string>
+            </property>
+            <property name="menuText">
+                <string>&Scale numbering</string>
+            </property>
+            <property name="toolTip">
+                <string>Scale numbering</string>
+            </property>
+            <property name="statusTip">
+                <string>Scale numbering</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>labelfont</cstring>
+            </property>
+            <property name="text">
+                <string>Axis label</string>
+            </property>
+            <property name="menuText">
+                <string>&Axis label</string>
+            </property>
+            <property name="toolTip">
+                <string>Axis label</string>
+            </property>
+            <property name="statusTip">
+                <string>Axis label</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>titlefont</cstring>
+            </property>
+            <property name="text">
+                <string>Caption</string>
+            </property>
+            <property name="menuText">
+                <string>&Caption</string>
+            </property>
+            <property name="toolTip">
+                <string>Caption</string>
+            </property>
+            <property name="statusTip">
+                <string>Caption</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>resetfont</cstring>
+            </property>
+            <property name="text">
+                <string>Reset</string>
+            </property>
+            <property name="menuText">
+                <string>&Reset</string>
+            </property>
+            <property name="toolTip">
+                <string>Reset</string>
+            </property>
+            <property name="statusTip">
+                <string>Reset</string>
+            </property>
+        </action>
+    </actiongroup>
+    <actiongroup>
+        <property name="name">
+            <cstring>floorstyle</cstring>
+        </property>
+        <property name="text">
+            <string>Floor Style</string>
+        </property>
+        <property name="menuText">
+            <string>Floor Style</string>
+        </property>
+        <property name="statusTip">
+            <string>Floor Style</string>
+        </property>
+        <property name="usesDropDown">
+            <bool>false</bool>
+        </property>
+        <action>
+            <property name="name">
+                <cstring>floordata</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image12</iconset>
+            </property>
+            <property name="text">
+                <string>Floor Data Projection</string>
+            </property>
+            <property name="menuText">
+                <string>Floor Data Projection</string>
+            </property>
+            <property name="toolTip">
+                <string>Floor Data Projection</string>
+            </property>
+            <property name="statusTip">
+                <string>Floor Data Projection</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>flooriso</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image13</iconset>
+            </property>
+            <property name="text">
+                <string>Floor Isolines</string>
+            </property>
+            <property name="menuText">
+                <string>Floor Isolines</string>
+            </property>
+            <property name="toolTip">
+                <string>Floor Isolines</string>
+            </property>
+            <property name="statusTip">
+                <string>Floor Isolines</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>floornone</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="on">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image14</iconset>
+            </property>
+            <property name="text">
+                <string>Empty Floor</string>
+            </property>
+            <property name="menuText">
+                <string>Empty Floor</string>
+            </property>
+            <property name="toolTip">
+                <string>Empty Floor</string>
+            </property>
+            <property name="statusTip">
+                <string>Empty Floor</string>
+            </property>
+        </action>
+    </actiongroup>
+    <action>
+        <property name="name">
+            <cstring>openMeshFile</cstring>
+        </property>
+        <property name="iconSet">
+            <iconset>image15</iconset>
+        </property>
+        <property name="text">
+            <string>Open FEM files</string>
+        </property>
+        <property name="menuText">
+            <string>Open FEM files</string>
+        </property>
+    </action>
+    <action>
+        <property name="name">
+            <cstring>normals</cstring>
+        </property>
+        <property name="toggleAction">
+            <bool>true</bool>
+        </property>
+        <property name="iconSet">
+            <iconset>image16</iconset>
+        </property>
+        <property name="text">
+            <string>Show normal vectors</string>
+        </property>
+        <property name="menuText">
+            <string>Show normal vectors</string>
+        </property>
+    </action>
+    <actiongroup>
+        <property name="name">
+            <cstring>grids</cstring>
+        </property>
+        <property name="enabled">
+            <bool>true</bool>
+        </property>
+        <property name="text">
+            <string>grid</string>
+        </property>
+        <property name="menuText">
+            <string>grid</string>
+        </property>
+        <property name="statusTip">
+            <string>grid</string>
+        </property>
+        <property name="exclusive">
+            <bool>false</bool>
+        </property>
+        <property name="usesDropDown">
+            <bool>false</bool>
+        </property>
+        <action>
+            <property name="name">
+                <cstring>front</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image17</iconset>
+            </property>
+            <property name="text">
+                <string>Action</string>
+            </property>
+            <property name="menuText">
+                <string>Action</string>
+            </property>
+            <property name="toolTip">
+                <string>Front Grid</string>
+            </property>
+            <property name="accel">
+                <string></string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>back</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image18</iconset>
+            </property>
+            <property name="text">
+                <string>Action_2</string>
+            </property>
+            <property name="menuText">
+                <string>Action_2</string>
+            </property>
+            <property name="toolTip">
+                <string>Back Grid</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>right</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image19</iconset>
+            </property>
+            <property name="text">
+                <string>Action_3</string>
+            </property>
+            <property name="menuText">
+                <string>Action_3</string>
+            </property>
+            <property name="toolTip">
+                <string>Right Grid</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>left</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image20</iconset>
+            </property>
+            <property name="text">
+                <string>Action_4</string>
+            </property>
+            <property name="menuText">
+                <string>Action_4</string>
+            </property>
+            <property name="toolTip">
+                <string>Left Grid</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>ceil</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image21</iconset>
+            </property>
+            <property name="text">
+                <string>Action_5</string>
+            </property>
+            <property name="menuText">
+                <string>Action_5</string>
+            </property>
+            <property name="toolTip">
+                <string>Ceiling Grid</string>
+            </property>
+        </action>
+        <action>
+            <property name="name">
+                <cstring>floor</cstring>
+            </property>
+            <property name="toggleAction">
+                <bool>true</bool>
+            </property>
+            <property name="iconSet">
+                <iconset>image22</iconset>
+            </property>
+            <property name="text">
+                <string>Action_6</string>
+            </property>
+            <property name="menuText">
+                <string>Action_6</string>
+            </property>
+            <property name="toolTip">
+                <string>Floor Grid</string>
+            </property>
+        </action>
+    </actiongroup>
+</actions>
+<images>
+    <image name="image0">
+        <data format="PNG" length="201">89504e470d0a1a0a0000000d49484452000000100000000d0806000000a0bbee240000009049444154789c9d92410ac4200c457f4ab65de4429e6c6018989365e1755cf40076a18106621503f2157d21ff23e59c31ab9452b5bdaad2f3ee588155956c5933535a99603491aa12cf461cc156c4ccb55c00500008e41cc351736ed260a0a05ce2cea6724ad8b48718435ee3ea16fce3371b030b1efe7ce7e0ffd732e916f660e091c10e0cf40c803dd83558a9e81fdc37d14cdbb2be9c140000000049454e44ae426082</data>
+    </image>
+    <image name="image1">
+        <data format="PNG" length="215">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000009e49444154789c633c76ec1803b5010b2e09df88f7ff3f7efa4d9261ac2c8c0c5c5c2cd80db5f37af5ffd0363146121dc860e7f5eaff8f9f7f1998a869e0a16d628c3f7ffe4335945203617c265c12e41ac8c0008d283baf57ff79785818ecbc5efd27d5506c0e8147d4b6554264b9129b38464451038c1a3a6a2895002c7751cd50e4ec4a1543711628d43290810129ef9353983030e02950c829f2f00100bdf84c6a92a74e8d0000000049454e44ae426082</data>
+    </image>
+    <image name="image2">
+        <data format="PNG" length="167">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000006e49444154789c633c76ec1803b5011332c7ceebd57faa1b4a2d306ae8a8a1a3865203c0b239d50cb5f37af5ffd03631460c430f6d1363b4f37af59fd48205d94006060606167405304998c1c88a893110aba1a4188ecd40bc8612321c978144194a8acb493614dd707c8026891f00185139a40ba3f8e90000000049454e44ae426082</data>
+    </image>
+    <image name="image3">
+        <data format="PNG" length="216">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000009f49444154789c633c76ec1803b501133e493baf57ff49a19dfd5eff6760606060c4e6523baf57ff0f6d136324c795ae816ffe6375293906c25cbb7bbd08231336097200cc21765eaf505d4a890b91cd801bea15f68ea44881d1e80eb1f37af59ff1d8b16364470c2e7d58639f12000f537223089bbe43dbc418475d3a925dca0463906328b23e640ba8e652640b2876293607a1b8941c9a2e799f81818101000a06a3357133957f0000000049454e44ae426082</data>
+    </image>
+    <image name="image4">
+        <data format="PNG" length="772">89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af4000002cb49444154789ced97cd6b134118879f6d420ba5474f62ff0441410f2e054fb9d4a3207ab5a8d05341a95aa546a8c58f2a9e02d2f6e6492f82a41e7a119115f16040a490a326d9cb26fd486c63348c87cd6c6626b3695a68eba12f2c939979dff7f7cce76e1ccff33848eb3b50f54380ff0120a9565cd7153627cff39cdd0a6c97b34f75948d66e9baae884bd44d58c6d8f2ca3ec7f3bc48bc1baddad76d4654d16ed0b23f6906026432f0b7de7e7a496afac87a26038d5af84058de7dd6 [...]
+    </image>
+    <image name="image5">
+        <data format="XPM.GZ" length="2144">789cbdd45b4fdb301407f0f77e8a08bfa1e99034899d68da03f7fba5dc61da83e3246d81722db430edbbcfe76f070d08d39e963f48f9d5a7c6764e989b0d4ef7b683d9b9cec3588f872630037d1fcc968fa3d1f3f71fdf7e7666ba61607f940cba335f3a3334084c20425cf0269c71e01538e7c04f70c181e7d951cc81fb70c681c7b0e6c0d7ecaee4c0f7b0e2c0353bd61cf8929de0822b38e3c025ac396c71011749e1f76360c3c138be9f2669e2c70b1817bc066769e6c74fe03ccd9dc510d6a9f6e38b7091367faf0b9bd4784bb84a2bef295b86b239ef235849e5ad1b4b [...]
+    </image>
+    <image name="image6">
+        <data format="PNG" length="923">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000036249444154789cad955f485b6718c67fc71c63625193e11facc6d6ceaca9b55d7ae18522bd50acb13427548d10e386462c0c7b212d2c92ad7485c2d04ba1174abb9be1dd50a8f462ea5a5c87b8ddc82a6a2f8a7fd0760612ab47433c9e846f17838d4e5775f4b97ebf1fcffb3eeff77dd2d4d4141f5a29c73d70f76ea10804be17efab918f0af3f97c229148c36e7fc2a9534edc6eb7906599919111e97f396d686810555555f4f77f8bc1f09a8a8acfe8ebeb2391481c587f28545114e1 [...]
+    </image>
+    <image name="image7">
+        <data format="PNG" length="872">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000032f49444154789ccd954b48aa6b14869f5fff3684110a6184a905890e0a0cb1081a841199a24245176c104917880641749b37e832286892831a3588a068e2406ad04428a22b5d402a68521405997929ed3f8320d8b4f7ae7d3883b3868bf53debfdd6fbf12d21140af15f87ec6f0f381c0ec9e9744a7faa11bf0b6b6d6d9592c924e9741abd5e8fcbe592445164757555f8574aebebeba5caca4a666767c9cacaa2a4a48489890952a9d42febbf84badd6ec9e3f1e0f7fbb9bdbd45ad5673 [...]
+    </image>
+    <image name="image8">
+        <data format="PNG" length="554">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000001f149444154789ccd95bf6b5a5114c73fef298d20c14715b120e2f806e990ada34aab0ebe27a2832e85f817b410dedfe01808b45b978810a18180a393e1b5a1b482143a6490fe701031a9b4b12ae8ed906290e7cfd2a107ce70bff7dccffd9e33dc2b99a6c9bf0e79db03d96c56a45229b1aac6be292c97cb89c964422814c2e170904c2685dd6ee7f4f454fa2b683a9d16d16894e3e76f80cb3faa0bcf93fec2fab5ed6b9a26745de778ff037cdf994b5555c964329651ac756ab3d978f9 [...]
+    </image>
+    <image name="image9">
+        <data format="PNG" length="744">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000002af49444154789ccd953d4c535118869f7b7b2929a505c34fd55aa988112126c41023098383290dd8de188146347132ea6270eaee62181c5c4c18d88418217670c1451773a3c60583160d52498c3f840a2df4f68a2dc7413dd814f9310e9ee44ddeefdcef3cf77cdfb93f8a6118fceba16e77416767a7e8eaea121be5685b855d8844c4c2b76fe4f3791af7ec410f8584aa69c46231e5afa017755d4c8ebb80121a3a05cf6e7f052af00452ebe66f5a7e5f28245edca986c552582ca5c2e3 [...]
+    </image>
+    <image name="image10">
+        <data format="PNG" length="653">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000025449444154789cad95bf4b725118809ffb71cda09f46dca1a5fe0169edd2108498e2d022414d91fd030d39b555343605d190181886e020b8b40971c5868c96a2200871b0a0522aaf50be0d1f5e3efbae7dfad1b31ddef33ee73de73d87a31886c14ff3abd3048fc7237ebf5f7e4cbabcbc2c9aa6e176bb191d1d6d296e5b3a313121b95c8e603048575717434343e8ba6e2b6e4baaebba288a42bd5ea756ab717777c7d3d3139148846030f897f89fd29b9b1ba9d56a00c4e3719e9f9f59 [...]
+    </image>
+    <image name="image11">
+        <data format="PNG" length="452">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000018b49444154789ca595c16ac2401086bf4421822028b2143df80a3dbaf8183ea78fa1b9f424f4d46bcd412c2156c1404c7a48679b351b6ddaff363bb3ffcc3f339b789bcd86b6582e7401b05a879ecbdf6d43a67549f6087e1b524194c3cb7bf47fd2f97c5e9c4e27263e4c7c188d468d95ff8a546b5d789e479ee7e62c8e63e36b4daab52ed2340560301810e5a5fc5eafd778e72ee972a18b890f4992b0dbed2cdff178b412b7aa1440290560fa09309bcd2cbb8abb2b15fdb490e9746a [...]
+    </image>
+    <image name="image12">
+        <data format="PNG" length="226">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000000a949444154789cedd4210ec2301886e1b764084e0306f38969041804090acb1948b8010967d805309304fb131cc7014c512c7475ed1024fb64c59357fca93333badea073b1477f8216ed07493e07343317a10093c52609bcd715d02a95e4a7ab35f04a423f8b4a8bd13309ba5627cccc05a8245f6ee7e4560628c030b1f2723c37950d2ac9cf76259086b6d794a656d6fb5b50095048f2cbc31878e4e57dcd01d9c71ea1fd7ffa1fe81b2e1b2dcf4b906cbb0000000049454e44ae426082</data>
+    </image>
+    <image name="image13">
+        <data format="PNG" length="238">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000000b549444154789ced94210e843010456736bd018223ec1d8ac490705e120c92b90ba266cdcaa2a6197e0b0858b109dff1075eff6f1b5844e86ebd6e273ed09f401d1adefb780528229c4175609fabb68b611a4f3d0de4d05460d57629317e7ca62ca9c210d4f47524229a8785756edfb5811254cd008b20ace9eb68c1d8aa9814810a38d2fbfbd99c83b329f7aa63624c86da24b575c234f23c2c8cf5f1d4ed5e2668c9b4b2f54bd7a82426a2cb973d833effd3ff80aec3fb78ab235e8473 [...]
+    </image>
+    <image name="image14">
+        <data format="PNG" length="153">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000006049444154789ced94410a00310803a3ecabfc3ff9d6eea950aca79a1e169a63846110d148421d97132ff408f4c94544bc1d20495ba063b0031c429ecb5de01cd94e6721afca6e24a659c8abb29bb66925e46a4b003000ed635fa0f79ffe03fa017ed12c22088282610000000049454e44ae426082</data>
+    </image>
+    <image name="image15">
+        <data format="PNG" length="237">89504e470d0a1a0a0000000d49484452000000100000000d0806000000a0bbee24000000b449444154789c9d92b109c3301444ef9b0ba4c94a1ec08517c8162e3580cb6ce1055c6400155e47858a182cf8298284432c47e8e07302f18ee34bb22c0bfea91f1f1acfb319647fd794c0b319244e0c8b2e250d728d66330801a06ddb54d15a2b39700f470949edb68069f5b85f6f785e98858fc21b00099e568f6e0b70defd784e0d80049f795624d5bfbcf68ae4248be770076ac2d91e3fcb1b096bad084975de55c1c0ee156ae01400a00afe0a28d1d13f780395128c0ebcec513300 [...]
+    </image>
+    <image name="image16">
+        <data format="PNG" length="1036">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000003d349444154789cad955d4c935718c77fefcb8b1d8375654851b4ad4416d88749759822ebdc3242305cf015207cc4cd091931123232b30e2f5d3243e2c7c55822178b81086431d130038b78e1dce21b8dcb00c900d18c0db715c720016d2994becf2eb05860cc64f19f9c9be79cffff3ce7fc9273145dd7791672166549ff455d01d0c285f06478623de5e5e589a2287477772faf8bf40328e14e9f165c515121f3f3f3f87c3e1c0e075eaf974d9aca2d2659ed53230be1e2ea9d8b8b8bc [...]
+    </image>
+    <image name="image17">
+        <data format="PNG" length="527">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000001d649444154789cad94bd6e13411485bf593b71a0c146c2a1020ccf00c52e72401148aca248502081441f3a9078803c000554d0d3514488c2a141518c3c083a1e00cc4f43369158689238b22f0d331acf4c420239cd68eedd337beeb9335769ad396c247b25db7921075967e7d70540c594b6f3426edf9a63e1ce7b75509557ae6f48f4d07f413b2fa4db692af0ca3765003c7d76417ce25e3007b6f3e2ff95ba0a0daa00833495fec4595a3b9ff85c39c599e157bb7eacb43837ec07f17e [...]
+    </image>
+    <image name="image18">
+        <data format="PNG" length="601">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000022049444154789cbd544d6b1351143d379f6d864ea682465d48d322fe8350c6121424b571ef42a9086ebaf00f7415b7baa94217821604578a6e131a2c81e03c24bf40d1dae2424d049b843469c666ae8b38d397f9282d8a67f378e7bd7bdeb9e732434208fc6b44820e4c5de78fe1699c1f7cc666388d99c1165aa422c96d67bf1d3e87a9c11767dd8ca431b3bf05f2737a7bbec60f07f7a1bd794d32dfd72f725c188772f5b96b1cf273f96c3d4389ee370f4fe0402e9b6f30004c5a3b18 [...]
+    </image>
+    <image name="image19">
+        <data format="PNG" length="452">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000018b49444154789cad94bd4e02511085cf6c02283f020df8136da8b4a222e49290d068dc589b6882356fe05368a9f696da8a89da68e426121b5f4134c62d600984c8168c05b98bb8a0bb614f738bbd33fbcd99b943524af82dedaf8f45dd602fe76de9902d21982691167583f7f7765029d7c92d9d25040340478b616252afb284e00e45d198cf60a3f7325ebe2a0300cece73ec0c9f4e18e32eb277a764527c36524b087ed3966184d790edd6d1a330a2dc1d91eabb4d4f4d39d87a660078 [...]
+    </image>
+    <image name="image20">
+        <data format="PNG" length="496">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000001b749444154789cad944f4b1b4118879f775bb361ab348945db2248f150f00388cc4a3c94169b43a128bdf7de0fd4bb070f1e7a2901e9a12071ce822741d4937f626b23d8e82ed5d74399ed26ae66433a971766769ff799df0c23d65afef7f0b22663633436463f2c6c2940b5d6cc555fbd3b5100c9323d0e6b1a143c46be7f957e2d5fbfffa1b74c6363b4ac2dfce8b42f98b3fdf6e589744077e79614a060adb483677d41d7eb63e2e00934364627ae0f28582bcdf0ad16db477d19a6e1 [...]
+    </image>
+    <image name="image21">
+        <data format="PNG" length="446">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000018549444154789ced95414b024114c7ff6f152b08db223d98873282fc021dc6f21015e8a50f10de3dd457a83e46f7e8d6d98282c0720e42e782b02e5b9041b9218186be2eedb0ee4eb946dd7a97997d33fffffce6bd852129257e3bc2ba645b080680ebd01ce63b37782113e3dc402d3483d9ce9defdb191bc618ccaeed376d0bc18f460cb5c51d88f226188421b4109192d2005e33cb6cb28d371a41fafc800020fda933bb3676cd6d90fbfa0e2100300804f69ef965d81445ac724c3dd7 [...]
+    </image>
+    <image name="image22">
+        <data format="PNG" length="492">89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000001b349444154789ced94bf6b144114c73fb3b7779eec9122c64b90588414162a5888e244b7500cdc220111442336da68e79f23889585b6a6486171e081235af9a34825118c928c21a0b9c0b9c7f92c64c6cbdd1073674a1f2cb36fdebcef7ededbc728630c7b6dd14ec134b332c87a61eeab00a810699a5999bf7e893b375fab41292f5e5e97a0e8309666561a8b55053de5bb3200ee3f3a25bd893b99134c33fbefa4dd84ce3c69767563a09fe2d65e414f1afadab0949e3414d84d4f4379 [...]
+    </image>
+</images>
+<connections>
+    <connection>
+        <sender>Exit</sender>
+        <signal>activated()</signal>
+        <receiver>Mesh2MainWindowBase</receiver>
+        <slot>close()</slot>
+    </connection>
+    <connection>
+        <sender>lightingswitch</sender>
+        <signal>toggled(bool)</signal>
+        <receiver>lighting</receiver>
+        <slot>setEnabled(bool)</slot>
+    </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/mesh2/src/mesh2mainwindowbase4.ui b/examples/mesh2/src/mesh2mainwindowbase4.ui
new file mode 100644
index 0000000..a2e07ca
--- /dev/null
+++ b/examples/mesh2/src/mesh2mainwindowbase4.ui
@@ -0,0 +1,479 @@
+<ui version="4.0" >
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>800</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Mesh2</string>
+  </property>
+  <widget class="QWidget" name="centralWidget" >
+   <layout class="QGridLayout" >
+    <property name="leftMargin" >
+     <number>8</number>
+    </property>
+    <property name="topMargin" >
+     <number>8</number>
+    </property>
+    <property name="rightMargin" >
+     <number>8</number>
+    </property>
+    <property name="bottomMargin" >
+     <number>8</number>
+    </property>
+    <property name="horizontalSpacing" >
+     <number>6</number>
+    </property>
+    <property name="verticalSpacing" >
+     <number>6</number>
+    </property>
+    <item row="1" column="0" >
+     <layout class="QHBoxLayout" >
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <property name="leftMargin" >
+       <number>0</number>
+      </property>
+      <property name="topMargin" >
+       <number>0</number>
+      </property>
+      <property name="rightMargin" >
+       <number>0</number>
+      </property>
+      <property name="bottomMargin" >
+       <number>0</number>
+      </property>
+      <item>
+       <layout class="QHBoxLayout" >
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <property name="leftMargin" >
+         <number>0</number>
+        </property>
+        <property name="topMargin" >
+         <number>0</number>
+        </property>
+        <property name="rightMargin" >
+         <number>0</number>
+        </property>
+        <property name="bottomMargin" >
+         <number>0</number>
+        </property>
+        <item>
+         <widget class="QPushButton" name="normButton" >
+          <property name="text" >
+           <string>Std</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="lighting" >
+          <property name="enabled" >
+           <bool>false</bool>
+          </property>
+          <property name="text" >
+           <string>Lighting</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QCheckBox" name="lightingswitch" >
+          <property name="text" >
+           <string/>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <layout class="QVBoxLayout" >
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <property name="leftMargin" >
+           <number>0</number>
+          </property>
+          <property name="topMargin" >
+           <number>0</number>
+          </property>
+          <property name="rightMargin" >
+           <number>0</number>
+          </property>
+          <property name="bottomMargin" >
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="label_2" >
+            <property name="text" >
+             <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Polygon Offset</p></body></html></string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QSlider" name="offsSlider" >
+            <property name="maximum" >
+             <number>30</number>
+            </property>
+            <property name="pageStep" >
+             <number>5</number>
+            </property>
+            <property name="value" >
+             <number>5</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="tickPosition" >
+             <enum>QSlider::TicksAbove</enum>
+            </property>
+            <property name="tickInterval" >
+             <number>2</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <spacer>
+          <property name="orientation" >
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType" >
+           <enum>QSizePolicy::Fixed</enum>
+          </property>
+          <property name="sizeHint" >
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <layout class="QVBoxLayout" >
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <property name="leftMargin" >
+           <number>0</number>
+          </property>
+          <property name="topMargin" >
+           <number>0</number>
+          </property>
+          <property name="rightMargin" >
+           <number>0</number>
+          </property>
+          <property name="bottomMargin" >
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="label_3" >
+            <property name="text" >
+             <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Resolution</p></body></html></string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QSlider" name="resSlider" >
+            <property name="minimum" >
+             <number>1</number>
+            </property>
+            <property name="maximum" >
+             <number>100</number>
+            </property>
+            <property name="orientation" >
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="tickPosition" >
+             <enum>QSlider::TicksAbove</enum>
+            </property>
+            <property name="tickInterval" >
+             <number>5</number>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <spacer>
+        <property name="orientation" >
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeType" >
+         <enum>QSizePolicy::Fixed</enum>
+        </property>
+        <property name="sizeHint" >
+         <size>
+          <width>71</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </item>
+    <item row="0" column="0" >
+     <layout class="QHBoxLayout" >
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <property name="leftMargin" >
+       <number>0</number>
+      </property>
+      <property name="topMargin" >
+       <number>0</number>
+      </property>
+      <property name="rightMargin" >
+       <number>0</number>
+      </property>
+      <property name="bottomMargin" >
+       <number>0</number>
+      </property>
+      <item>
+       <widget class="QFrame" name="frame" >
+        <property name="sizePolicy" >
+         <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" >
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="frameShape" >
+         <enum>QFrame::StyledPanel</enum>
+        </property>
+        <property name="frameShadow" >
+         <enum>QFrame::Sunken</enum>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" >
+        <property name="spacing" >
+         <number>6</number>
+        </property>
+        <property name="leftMargin" >
+         <number>0</number>
+        </property>
+        <property name="topMargin" >
+         <number>0</number>
+        </property>
+        <property name="rightMargin" >
+         <number>0</number>
+        </property>
+        <property name="bottomMargin" >
+         <number>0</number>
+        </property>
+        <item>
+         <layout class="QVBoxLayout" >
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <property name="leftMargin" >
+           <number>0</number>
+          </property>
+          <property name="topMargin" >
+           <number>0</number>
+          </property>
+          <property name="rightMargin" >
+           <number>0</number>
+          </property>
+          <property name="bottomMargin" >
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QCheckBox" name="projection" >
+            <property name="text" >
+             <string>Ortho</string>
+            </property>
+            <property name="checked" >
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="colorlegend" >
+            <property name="text" >
+             <string>Legend</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="autoscale" >
+            <property name="text" >
+             <string>Autoscale</string>
+            </property>
+            <property name="checked" >
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="mouseinput" >
+            <property name="text" >
+             <string>Mouse</string>
+            </property>
+            <property name="checked" >
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="shader" >
+            <property name="text" >
+             <string>Shading</string>
+            </property>
+            <property name="checked" >
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QVBoxLayout" >
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <property name="leftMargin" >
+           <number>0</number>
+          </property>
+          <property name="topMargin" >
+           <number>0</number>
+          </property>
+          <property name="rightMargin" >
+           <number>0</number>
+          </property>
+          <property name="bottomMargin" >
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="label" >
+            <property name="sizePolicy" >
+             <sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text" >
+             <string><html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Normals</p></body></html></string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" >
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <property name="leftMargin" >
+             <number>0</number>
+            </property>
+            <property name="topMargin" >
+             <number>0</number>
+            </property>
+            <property name="rightMargin" >
+             <number>0</number>
+            </property>
+            <property name="bottomMargin" >
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QSlider" name="normalsquality" >
+              <property name="sizePolicy" >
+               <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimum" >
+               <number>3</number>
+              </property>
+              <property name="maximum" >
+               <number>32</number>
+              </property>
+              <property name="pageStep" >
+               <number>4</number>
+              </property>
+              <property name="value" >
+               <number>3</number>
+              </property>
+              <property name="orientation" >
+               <enum>Qt::Vertical</enum>
+              </property>
+              <property name="invertedAppearance" >
+               <bool>true</bool>
+              </property>
+              <property name="tickPosition" >
+               <enum>QSlider::TicksAbove</enum>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSlider" name="normalslength" >
+              <property name="sizePolicy" >
+               <sizepolicy vsizetype="Minimum" hsizetype="Minimum" >
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimum" >
+               <number>1</number>
+              </property>
+              <property name="maximum" >
+               <number>100</number>
+              </property>
+              <property name="pageStep" >
+               <number>5</number>
+              </property>
+              <property name="value" >
+               <number>8</number>
+              </property>
+              <property name="orientation" >
+               <enum>Qt::Vertical</enum>
+              </property>
+              <property name="invertedAppearance" >
+               <bool>true</bool>
+              </property>
+              <property name="tickPosition" >
+               <enum>QSlider::TicksAbove</enum>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <resources>
+  <include location="../../images.qrc" />
+ </resources>
+ <connections>
+  <connection>
+   <sender>lightingswitch</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>lighting</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>181</x>
+     <y>568</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>144</x>
+     <y>568</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/examples/mesh2/src/thesis.tex b/examples/mesh2/src/thesis.tex
new file mode 100644
index 0000000..909b127
--- /dev/null
+++ b/examples/mesh2/src/thesis.tex
@@ -0,0 +1,9 @@
+\documentclass{slides}
+\usepackage[dvips]{color}
+\usepackage{times}
+\usepackage{graphicx}
+
+\begin{document}
+\include{dump_0.pdf}
+%\include{dump3b}
+\end{document}
diff --git a/examples/movie.png b/examples/movie.png
new file mode 100644
index 0000000..cf57682
Binary files /dev/null and b/examples/movie.png differ
diff --git a/examples/nodata.png b/examples/nodata.png
new file mode 100644
index 0000000..9279c36
Binary files /dev/null and b/examples/nodata.png differ
diff --git a/examples/none.png b/examples/none.png
new file mode 100644
index 0000000..9a50ce9
Binary files /dev/null and b/examples/none.png differ
diff --git a/examples/normals.png b/examples/normals.png
new file mode 100644
index 0000000..427574a
Binary files /dev/null and b/examples/normals.png differ
diff --git a/examples/polygon.png b/examples/polygon.png
new file mode 100644
index 0000000..1b0bacf
Binary files /dev/null and b/examples/polygon.png differ
diff --git a/examples/qwtplot.png b/examples/qwtplot.png
new file mode 100644
index 0000000..8e1ca4e
Binary files /dev/null and b/examples/qwtplot.png differ
diff --git a/examples/savecontent.png b/examples/savecontent.png
new file mode 100644
index 0000000..06e0d8b
Binary files /dev/null and b/examples/savecontent.png differ
diff --git a/examples/scattered.png b/examples/scattered.png
new file mode 100644
index 0000000..a23a865
Binary files /dev/null and b/examples/scattered.png differ
diff --git a/examples/simpleplot/simpleplot.cpp b/examples/simpleplot/simpleplot.cpp
new file mode 100644
index 0000000..4fa96c5
--- /dev/null
+++ b/examples/simpleplot/simpleplot.cpp
@@ -0,0 +1,83 @@
+  //-----------------------------------------------------------------
+  //              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;
+#if QT_VERSION < 0x040000
+      a.setMainWidget(&plot);
+#endif
+      plot.resize(800,600);
+      plot.show();
+      return a.exec();
+  }
diff --git a/examples/simpleplot/simpleplot.pro b/examples/simpleplot/simpleplot.pro
new file mode 100644
index 0000000..ceb0c15
--- /dev/null
+++ b/examples/simpleplot/simpleplot.pro
@@ -0,0 +1,3 @@
+include( ../common.pro )
+
+SOURCES = simpleplot.cpp
diff --git a/examples/wireframe.png b/examples/wireframe.png
new file mode 100644
index 0000000..8628429
Binary files /dev/null and b/examples/wireframe.png differ
diff --git a/include/qwt3d_autoptr.h b/include/qwt3d_autoptr.h
new file mode 100644
index 0000000..cb2287d
--- /dev/null
+++ b/include/qwt3d_autoptr.h
@@ -0,0 +1,75 @@
+#ifndef qwt3d_autoptr_h__2004_05_14_18_57_begin_guarded_code
+#define qwt3d_autoptr_h__2004_05_14_18_57_begin_guarded_code
+
+namespace Qwt3D
+{
+
+//! Simple Auto pointer providing deep copies for raw pointer  
+/*!
+  Requirements: \n
+  virtual T* T::clone() const;\n
+  T::destroy() const;
+  virtual ~T() private/protected\n\n
+  clone() is necessary for the pointer to preserve polymorphic behaviour.
+  The pointer requires also heap based objects with regard to the template 
+  argument in order to be able to get ownership and control over destruction.
+  */
+template <typename T>
+class  qwt3d_ptr
+{
+public:
+  //! Standard ctor
+  explicit qwt3d_ptr(T* ptr = 0)
+  :rawptr_(ptr)
+  {
+  }
+  //! Dtor (calls T::destroy)
+  ~qwt3d_ptr()
+  {
+    destroyRawPtr();
+  }
+
+  //! Copy ctor (calls (virtual) clone())
+  qwt3d_ptr(qwt3d_ptr const& val)
+  {
+    rawptr_ = val.rawptr_->clone();
+  }
+  
+  //! Assignment in the same spirit as copy ctor
+  qwt3d_ptr<T>& operator=(qwt3d_ptr const& val)
+  {
+    if (this == &val)
+      return *this;
+
+    destroyRawPtr();
+    rawptr_ = val.rawptr_->clone();
+
+    return *this;
+  }
+
+  //! It's a pointerlike object, isn't it ?
+  T* operator->() const
+  {
+    return rawptr_;
+  }
+
+  //! Dereferencing
+  T& operator*() const
+  {
+    return *rawptr_;
+  }
+
+
+private:
+  T* rawptr_;
+  void destroyRawPtr() 
+  {
+    if (rawptr_) 
+      rawptr_->destroy();
+    rawptr_ = 0;
+  }
+};  
+
+} // ns
+
+#endif /* include guarded */
diff --git a/include/qwt3d_autoscaler.h b/include/qwt3d_autoscaler.h
new file mode 100644
index 0000000..56a0c96
--- /dev/null
+++ b/include/qwt3d_autoscaler.h
@@ -0,0 +1,51 @@
+#ifndef __qwt3d_autoscaler_2003_08_18_12_05__
+#define __qwt3d_autoscaler_2003_08_18_12_05__
+
+#include <vector>
+#include "qwt3d_global.h"
+#include "qwt3d_autoptr.h"
+
+namespace Qwt3D
+{
+
+//! ABC for autoscaler
+class QWT3D_EXPORT AutoScaler
+{
+friend class qwt3d_ptr<AutoScaler>;
+protected:
+  //! Returns a new heap based object of the derived class.  
+  virtual AutoScaler* clone() const = 0;
+  //! To implement from subclasses
+  virtual int execute(double& a, double& b, double start, double stop, int ivals) = 0;
+  virtual ~AutoScaler(){}
+
+private:
+  void destroy() const {delete this;} //!< Used by qwt3d_ptr      
+};
+
+//! Automatic beautifying of linear scales
+class QWT3D_EXPORT LinearAutoScaler : public AutoScaler
+{
+friend class LinearScale;
+protected:
+  LinearAutoScaler();
+  explicit LinearAutoScaler(std::vector<double>& mantisses);
+  //! Returns a new heap based object utilized from qwt3d_ptr
+  AutoScaler* clone() const {return new LinearAutoScaler(*this);}
+	int execute(double& a, double& b, double start, double stop, int ivals);
+
+private:
+	
+	double start_, stop_;
+	int intervals_; 
+
+	void init(double start, double stop, int ivals);
+	double anchorvalue(double start, double mantisse, int exponent);
+	int segments(int& l_intervals, int& r_intervals, double start, double stop, double anchor, double mantissa, int exponent);
+  std::vector<double> mantissi_;
+};
+
+} // ns
+
+
+#endif
diff --git a/include/qwt3d_axis.h b/include/qwt3d_axis.h
new file mode 100644
index 0000000..52d6243
--- /dev/null
+++ b/include/qwt3d_axis.h
@@ -0,0 +1,131 @@
+#ifndef __AXIS_H__
+#define __AXIS_H__
+
+#include "qwt3d_autoptr.h"
+#include "qwt3d_label.h"
+#include "qwt3d_scale.h"
+#include "qwt3d_autoscaler.h"
+
+namespace Qwt3D
+{
+
+//! Autoscalable axis with caption. 
+/*!
+  Axes are highly customizable especially in terms
+  of labeling and scaling.
+*/
+class QWT3D_EXPORT Axis : public Drawable
+{
+
+public:
+
+	Axis(); //!< Constructs standard axis
+	Axis(Qwt3D::Triple beg, Qwt3D::Triple end); //!< Constructs a new axis with specified limits
+	virtual ~Axis(); // dtor
+	
+	virtual void draw(); //!< Draws axis
+
+	void setPosition(const Qwt3D::Triple& beg, const Qwt3D::Triple& end); //!< Positionate axis
+	void position(Qwt3D::Triple& beg, Qwt3D::Triple& end) const {beg = beg_; end = end_;} //!< Returns axis' position
+  Qwt3D::Triple begin() const { return beg_; } //!< Returns axis' beginning position
+  Qwt3D::Triple end() const { return end_; } //!< Returns axis' ending position 
+  double length() const { return (end_-beg_).length(); } //!< Returns axis' length
+
+	void setTicLength(double majorl, double minorl); //!< Sets tics lengths in world coordinates
+	//! Returns tics lengths
+  void ticLength(double& majorl, double& minorl) const {majorl = lmaj_; minorl = lmin_;}
+	void setTicOrientation(double tx, double ty, double tz); //!< Sets tic orientation
+	void setTicOrientation(const Qwt3D::Triple& val); //!< Same function as above
+  Qwt3D::Triple ticOrientation() const { return orientation_;} //!< Returns tic orientation
+  void setSymmetricTics( bool b) { symtics_ = b;} //!< Sets two-sided tics (default is false) 
+	
+  //! Sets font for axis label
+	void setLabelFont(QString const& family, int pointSize, int weight = QFont::Normal, bool italic = false);
+	void setLabelFont(QFont const& font); //!< Sets font for axis label
+  QFont const& labelFont() const {return labelfont_;} //!< Returns current label font 
+  
+  void setLabelString(QString const& name);   //!< Sets label content
+	void setLabelPosition(const Qwt3D::Triple& pos, Qwt3D::ANCHOR);
+	void setLabelColor(Qwt3D::RGBA col);
+  void setLabel(bool d) {drawLabel_ = d;} //!< Turns label drawing on or off
+	void adjustLabel(int val) {labelgap_ = val;} //!< Shifts label in device coordinates dependent on anchor;
+
+	void setScaling(bool d) {drawTics_ = d;} //!< Turns scale drawing on or off
+	bool scaling() const {return drawTics_;} //!< Returns, if scale drawing is on or off
+  void setScale(Qwt3D::SCALETYPE);
+  void setScale(Scale* item);
+	void setNumbers(bool d) {drawNumbers_ = d;} //!< Turns number drawing on or off
+	bool numbers() const {return drawNumbers_;} //!< Returns, if number drawing is on or off
+	void setNumberColor(Qwt3D::RGBA col); //!< Sets the color for axes numbers
+	Qwt3D::RGBA numberColor() const {return numbercolor_;} //!< Returns the color for axes numbers
+	//! Sets font for numbering
+	void setNumberFont(QString const& family, int pointSize, int weight = QFont::Normal, bool italic = false);
+	void setNumberFont(QFont const&); //!< Overloaded member, works like the above function
+  QFont const& numberFont() const {return numberfont_;} //!< Returns current numbering font
+  void setNumberAnchor(Qwt3D::ANCHOR a) { scaleNumberAnchor_ = a;} //!< Sets anchor position for numbers
+	void adjustNumbers(int val) {numbergap_ = val;} //!< Shifts axis numbers in device coordinates dependent on anchor;
+
+	void setAutoScale(bool val = true) {autoscale_ = val;} //!< Turns Autoscaling on or off
+	bool autoScale() const { return autoscale_;} //!< actual Autoscaling mode
+
+	void setMajors(int val); //!< Requests major intervals (maybe changed, if autoscaling is present)
+	void setMinors(int val); //!< Requests minor intervals
+	int majors() const { return majorintervals_; } //!< Returns number of major intervals
+	int minors() const { return minorintervals_; } //!< Returns number of minor intervals
+	Qwt3D::TripleField const& majorPositions() const {return majorpos_;} //!< Returns positions for actual major tics (also if invisible)
+	Qwt3D::TripleField const& minorPositions() const {return minorpos_;} //!< Returns positions for actual minor tics (also if invisible)
+	
+	//! Sets line width for axis components
+	void setLineWidth(double val, double majfac = 0.9, double minfac = 0.5);
+	double lineWidth() const { return lineWidth_;} //!< Returns line width for axis body
+	double majLineWidth() const { return majLineWidth_;} //!< Returns Line width for major tics
+	double minLineWidth() const { return minLineWidth_;} //!< Returns Line width for minor tics
+
+	void setLimits(double start, double stop) {start_=start; stop_=stop;} //!< Sets interval
+	void limits(double& start, double& stop) const {start = start_; stop = stop_;} //!< Returns axis interval
+  void recalculateTics(); //!< Enforces recalculation of ticmark positions
+
+
+private:
+
+	void init();
+	void drawBase();
+	void drawTics();
+	void drawTicLabel(Qwt3D::Triple Pos, int mtic);
+	Qwt3D::Triple drawTic(Qwt3D::Triple nadir, double length);
+	void drawLabel();
+  bool prepTicCalculation(Triple& startpoint);
+
+	Qwt3D::Triple biggestNumberString();
+	
+	
+	Qwt3D::ANCHOR scaleNumberAnchor_;
+	Qwt3D::Label label_;
+	std::vector<Qwt3D::Label> markerLabel_;
+
+	Qwt3D::Triple beg_, end_;
+	Qwt3D::TripleField majorpos_, minorpos_; //! vectors, holding major resp. minor tic positions;
+
+	Qwt3D::Triple ncube_beg_, ncube_end_; //!< enclosing parallelepiped for axis numbering
+
+	double start_, stop_, autostart_, autostop_;
+	double lmaj_, lmin_;
+	Qwt3D::Triple orientation_;
+
+	int majorintervals_, minorintervals_;
+
+	double lineWidth_, majLineWidth_, minLineWidth_;
+	bool symtics_;
+	bool drawNumbers_, drawTics_, drawLabel_;
+	bool autoscale_;
+	QFont numberfont_, labelfont_;
+	Qwt3D::RGBA  numbercolor_;
+
+	int numbergap_, labelgap_; 
+
+  Qwt3D::qwt3d_ptr<Qwt3D::Scale> scale_;
+};
+
+} // ns 
+
+#endif
diff --git a/include/qwt3d_color.h b/include/qwt3d_color.h
new file mode 100644
index 0000000..0c195fc
--- /dev/null
+++ b/include/qwt3d_color.h
@@ -0,0 +1,63 @@
+#ifndef __COLORGENERATOR_H__
+#define __COLORGENERATOR_H__
+
+#include <qstring.h>
+#include "qwt3d_global.h"
+#include "qwt3d_types.h"
+
+namespace Qwt3D
+{
+
+//! Abstract base class for color functors
+/*!
+Use your own color model by providing an implementation of operator()(double x, double y, double z).
+Colors destructor has been declared \c protected, in order to use only heap based objects. Plot3D 
+will handle the objects destruction.
+See StandardColor for an example
+*/
+class QWT3D_EXPORT Color
+{
+public:
+	virtual Qwt3D::RGBA operator()(double x, double y, double z) const = 0; //!< Implement your color model here
+  virtual Qwt3D::RGBA operator()(Qwt3D::Triple const& t) const {return this->operator()(t.x,t.y,t.z);} 
+	//! Should create a color vector usable by ColorLegend. The default implementation returns his argument
+	virtual Qwt3D::ColorVector& createVector(Qwt3D::ColorVector& vec) { return vec; }
+
+	void destroy() const { delete this;}
+
+protected:
+	virtual ~Color(){} //!< Allow heap based objects only
+};
+
+
+
+class Plot3D;
+//! Standard color model for Plot3D - implements the data driven operator()(double x, double y, double z)
+/*!
+The class has a ColorVector representing z values, which will be used by operator()(double x, double y, double z)
+*/
+class QWT3D_EXPORT StandardColor : public Color
+{
+public:
+	//! Initializes with data and set up a ColorVector with a size of 100 z values (default);
+  explicit StandardColor(Qwt3D::Plot3D* data, unsigned size = 100);
+	Qwt3D::RGBA operator()(double x, double y, double z) const; //!< Receives z-dependend color from ColorVector
+	void setColorVector(Qwt3D::ColorVector const& cv);
+	void reset(unsigned size=100); //!< Resets the standard colors; 
+	void setAlpha(double a); //!< Sets unitary alpha value for all colors
+	/** 
+		\brief Creates color vector
+		
+		Creates a color vector used by ColorLegend. This is essentially a copy from the internal used vector.
+		\return The vector created
+	*/
+	Qwt3D::ColorVector& createVector(Qwt3D::ColorVector& vec) {vec = colors_; return vec;}
+
+protected:
+	Qwt3D::ColorVector colors_;
+	Qwt3D::Plot3D* data_;
+};
+
+} // ns
+
+#endif
diff --git a/include/qwt3d_colorlegend.h b/include/qwt3d_colorlegend.h
new file mode 100644
index 0000000..8e06730
--- /dev/null
+++ b/include/qwt3d_colorlegend.h
@@ -0,0 +1,77 @@
+#ifndef __PLANE_H__
+#define __PLANE_H__
+
+#include "qwt3d_global.h"
+#include "qwt3d_drawable.h"
+#include "qwt3d_axis.h"
+#include "qwt3d_color.h"
+
+namespace Qwt3D
+{
+
+//! A flat color legend
+/**
+	The class visualizes a ColorVector together with a scale (axis)  and a caption. ColorLegends are vertical 
+	or horizontal
+*/
+class QWT3D_EXPORT ColorLegend : public Drawable
+{
+
+public:
+	
+	//! Possible anchor points for caption and axis
+	enum SCALEPOSITION
+	{
+		Top,      //!< scale on top
+    Bottom,   //!< scale on bottom
+		Left,     //!< scale left
+		Right     //!< scale right
+	};
+	
+	//! Orientation of the legend
+	enum ORIENTATION
+	{
+    BottomTop, //!< Positionate the legend vertically, the lowest color index is on the bottom
+		LeftRight  //!< Positionate the legend horizontally, the lowest color index is on left side
+	};
+
+	ColorLegend(); //!< Standard constructor
+
+	void draw(); //!< Draws the object. You should not use this explicitely - the function is called by updateGL().
+	
+	void setRelPosition(Qwt3D::Tuple relMin, Qwt3D::Tuple relMax); //!< Sets the relative position of the legend inside widget
+	void setOrientation(ORIENTATION, SCALEPOSITION); //!< Sets legend orientation and scale position
+	void setLimits(double start, double stop); //!< Sets the limit of the scale.
+	void setMajors(int); //!< Sets scale major tics.
+	void setMinors(int); //!< Sets scale minor tics.
+	void drawScale(bool val) { showaxis_ = val; } //!< Sets whether a scale will be drawn.
+	void drawNumbers(bool val) { axis_.setNumbers(val); } //!< Sets whether the scale will have scale numbers.
+	void setAutoScale(bool val); //!< Sets, whether the axis is autoscaled or not.
+  void setScale(Qwt3D::Scale *scale); //!< Sets another scale
+  void setScale(Qwt3D::SCALETYPE); //!< Sets one of the predefined scale types
+
+	void setTitleString(QString const& s); //!< Sets the legends caption string.
+	
+	//! Sets the legends caption font.
+	void setTitleFont(QString const& family, int pointSize, int weight = QFont::Normal, bool italic = false); 
+
+	Qwt3D::ColorVector colors; //!< The color vector
+
+private:
+	
+	Qwt3D::Label caption_;
+	Qwt3D::ParallelEpiped geometry() const { return pe_;}
+	void setGeometryInternal();
+
+	Qwt3D::ParallelEpiped pe_;
+	Qwt3D::Tuple relMin_, relMax_;
+	Qwt3D::Axis axis_;
+	SCALEPOSITION axisposition_;
+	ORIENTATION orientation_;
+
+	bool showaxis_;
+};
+
+} // ns
+
+#endif
diff --git a/include/qwt3d_coordsys.h b/include/qwt3d_coordsys.h
new file mode 100644
index 0000000..43c36f3
--- /dev/null
+++ b/include/qwt3d_coordsys.h
@@ -0,0 +1,100 @@
+#ifndef __COORDSYS_H__
+#define __COORDSYS_H__
+
+#include "qwt3d_axis.h"
+#include "qwt3d_colorlegend.h"
+
+namespace Qwt3D
+{
+
+//! A coordinate system with different styles (BOX, FRAME)
+class QWT3D_EXPORT CoordinateSystem : public Drawable
+{
+
+public:
+	explicit CoordinateSystem(Qwt3D::Triple blb = Qwt3D::Triple(0,0,0), Qwt3D::Triple ftr = Qwt3D::Triple(0,0,0), Qwt3D::COORDSTYLE = Qwt3D::BOX);
+  ~CoordinateSystem();	
+	
+	void init(Qwt3D::Triple beg = Qwt3D::Triple(0,0,0), Qwt3D::Triple end = Qwt3D::Triple(0,0,0));
+	//! Set style for the coordinate system (NOCOORD, FRAME or BOX)
+  void setStyle(Qwt3D::COORDSTYLE s,	Qwt3D::AXIS frame_1 = Qwt3D::X1, 
+																			Qwt3D::AXIS frame_2 = Qwt3D::Y1, 
+																			Qwt3D::AXIS frame_3 = Qwt3D::Z1);
+  Qwt3D::COORDSTYLE style() const { return style_;} 	//!< Return style oft the coordinate system 
+	void setPosition(Qwt3D::Triple first, Qwt3D::Triple second); //!< first == front_left_bottom, second == back_right_top
+	
+	void setAxesColor(Qwt3D::RGBA val); //!< Set common color for all axes
+	//! Set common font for all axis numberings
+  void setNumberFont(QString const& family, int pointSize, int weight = QFont::Normal, bool italic = false);
+	//! Set common font for all axis numberings
+	void setNumberFont(QFont const& font);
+	//! Set common color for all axis numberings
+	void setNumberColor(Qwt3D::RGBA val);
+  void setStandardScale(); //!< Sets an linear axis with real number items
+
+ 	void adjustNumbers(int val); //!< Fine tunes distance between axis numbering and axis body
+	void adjustLabels(int val); //!< Fine tunes distance between axis label and axis body
+
+	//! Sets color for the grid lines
+  void setGridLinesColor(Qwt3D::RGBA val) {gridlinecolor_ = val;}
+	
+	//! Set common font for all axis labels
+	void setLabelFont(QString const& family, int pointSize, int weight = QFont::Normal, bool italic = false);
+	//! Set common font for all axis labels
+	void setLabelFont(QFont const& font);
+	//! Set common color for all axis labels
+	void setLabelColor(Qwt3D::RGBA val);
+
+	//! Set line width for tic marks and axes
+	void setLineWidth(double val, double majfac = 0.9, double minfac = 0.5);
+	//! Set length for tic marks
+	void setTicLength(double major, double minor);
+
+	//! Switch autoscaling of axes
+  void setAutoScale(bool val = true);
+
+	Qwt3D::Triple first() const { return first_;}
+	Qwt3D::Triple second() const { return second_;}
+
+	void setAutoDecoration(bool val = true) {autodecoration_ = val;}
+	bool autoDecoration() const { return autodecoration_;}
+
+	void setLineSmooth(bool val = true) {smooth_ = val;} //!< draw smooth axes
+	bool lineSmooth() const {return smooth_;}            //!< smooth axes ? 
+
+	void draw();
+	
+	//! Defines whether a grid between the major and/or minor tics should be drawn
+  void setGridLines(bool majors, bool minors, int sides = Qwt3D::NOSIDEGRID); 
+  int grids() const {return sides_;} //!< Returns grids switched on
+	
+	//! The vector of all12 axes - use them to set axis properties individually.
+  std::vector<Axis> axes;
+
+
+private:
+	void destroy();
+	
+	Qwt3D::Triple first_, second_;
+	Qwt3D::COORDSTYLE style_;
+	
+	Qwt3D::RGBA gridlinecolor_;
+
+	bool smooth_;
+	
+	void chooseAxes();
+	void autoDecorateExposedAxis(Axis& ax, bool left);
+  void drawMajorGridLines(); //!< Draws a grid between the major tics on the site
+	void drawMinorGridLines(); //!< Draws a grid between the minor tics on the site
+  void drawMajorGridLines(Qwt3D::Axis&, Qwt3D::Axis&); //! Helper
+  void drawMinorGridLines(Qwt3D::Axis&, Qwt3D::Axis&); //! Helper
+  void recalculateAxesTics();
+
+	bool autodecoration_;
+	bool majorgridlines_, minorgridlines_;
+  int  sides_;
+};
+
+} // ns
+
+#endif
diff --git a/include/qwt3d_drawable.h b/include/qwt3d_drawable.h
new file mode 100644
index 0000000..ebad96d
--- /dev/null
+++ b/include/qwt3d_drawable.h
@@ -0,0 +1,66 @@
+#ifndef __DRAWABLE_H__
+#define __DRAWABLE_H__
+
+
+#include <list>
+#include "qwt3d_global.h"
+#include "qwt3d_types.h"
+#include "qwt3d_io_gl2ps.h"
+
+namespace Qwt3D
+{
+
+//! ABC for Drawables
+class QWT3D_EXPORT Drawable 
+{
+
+public:
+
+	virtual ~Drawable() = 0;
+	
+	virtual void draw();
+
+	virtual void saveGLState();
+	virtual void restoreGLState();
+
+	void attach(Drawable*);
+	void detach(Drawable*);
+	void detachAll();
+	
+	virtual void setColor(double r, double g, double b, double a = 1);	
+	virtual void setColor(Qwt3D::RGBA rgba);	
+	Qwt3D::Triple relativePosition(Qwt3D::Triple rel); 
+
+protected:
+	
+	Qwt3D::RGBA color;
+	void Enable(GLenum what, GLboolean val);
+	Qwt3D::Triple ViewPort2World(Qwt3D::Triple win, bool* err = 0);
+	Qwt3D::Triple World2ViewPort(Qwt3D::Triple obj, bool* err = 0);
+
+	GLdouble modelMatrix[16];
+  GLdouble projMatrix[16];
+  GLint viewport[4];
+	
+
+private:
+
+	GLboolean ls;
+	GLboolean pols;
+	GLint polmode[2];
+	GLfloat lw;
+	GLint blsrc, bldst;
+	GLdouble col[4];
+	GLint pattern, factor;
+	GLboolean sallowed;
+	GLboolean tex2d;
+	GLint matrixmode;
+	GLfloat poloffs[2];
+	GLboolean poloffsfill;
+
+	std::list<Drawable*> dlist;
+};
+
+} // ns
+
+#endif
diff --git a/include/qwt3d_enrichment.h b/include/qwt3d_enrichment.h
new file mode 100644
index 0000000..1a85f21
--- /dev/null
+++ b/include/qwt3d_enrichment.h
@@ -0,0 +1,62 @@
+#ifndef qwt3d_enrichment_h__2004_02_23_19_24_begin_guarded_code
+#define qwt3d_enrichment_h__2004_02_23_19_24_begin_guarded_code
+
+#include "qwt3d_global.h"
+#include "qwt3d_types.h"
+
+namespace Qwt3D
+{
+
+class Plot3D;
+
+
+//! Abstract base class for data dependent visible user objects
+/**
+Enrichments provide a framework for user defined OPenGL objects. The base class has a pure virtuell 
+function clone(). 2 additional functions are per default empty and could also get a new implementation
+in derived classes. They can be used for initialization issues or actions not depending on the related
+primitive. 
+*/
+class QWT3D_EXPORT Enrichment
+{
+public:
+  enum TYPE{
+    VERTEXENRICHMENT,
+    EDGEENRICHMENT,
+    FACEENRICHMENT,
+    VOXELENRICHMENT
+  }; //!< Type of the Enrichment - only VERTEXENRICHMENT's are defined at this moment.
+  
+  Enrichment() : plot(0) {}
+  virtual ~Enrichment(){}
+  virtual Enrichment* clone() const = 0; //!< The derived class should give back a new Derived(something) here
+  virtual void drawBegin(){}; //!< Empty per default. Can be overwritten.
+  virtual void drawEnd(){}; //!< Empty per default. Can be overwritten.
+  virtual void assign(Plot3D const& pl) {plot = &pl;} //!< Assign to existent plot;
+  virtual TYPE type() const = 0; //!< Overwrite 
+
+protected:
+  const Plot3D* plot;
+};
+
+//! Abstract base class for vertex dependent visible user objects
+/**
+VertexEnrichments introduce a specialized draw routine for vertex dependent data.
+draw() is called, when the Plot realizes its internal OpenGL data representation 
+for every Vertex associated to his argument.
+*/
+class QWT3D_EXPORT VertexEnrichment : public Enrichment
+{
+public:
+  
+  VertexEnrichment() : Qwt3D::Enrichment() {}
+  virtual Enrichment* clone() const = 0; //!< The derived class should give back a new Derived(something) here
+  virtual void draw(Qwt3D::Triple const&) = 0; //!< Overwrite this
+  virtual TYPE type() const {return Qwt3D::Enrichment::VERTEXENRICHMENT;} //!< This gives VERTEXENRICHMENT
+};
+
+// todo EdgeEnrichment, FaceEnrichment, VoxelEnrichment etc.
+
+} // ns
+
+#endif
diff --git a/include/qwt3d_enrichment_std.h b/include/qwt3d_enrichment_std.h
new file mode 100644
index 0000000..ec1fa25
--- /dev/null
+++ b/include/qwt3d_enrichment_std.h
@@ -0,0 +1,116 @@
+#ifndef qwt3d_enrichment_std_h__2004_02_23_19_25_begin_guarded_code
+#define qwt3d_enrichment_std_h__2004_02_23_19_25_begin_guarded_code
+
+#include "qwt3d_enrichment.h"
+
+namespace Qwt3D
+{
+
+class Plot3D;
+
+//! The Cross Hair Style
+class QWT3D_EXPORT CrossHair : public VertexEnrichment
+{
+public:
+  CrossHair();
+  CrossHair(double rad, double linewidth, bool smooth, bool boxed);
+
+  Qwt3D::Enrichment* clone() const {return new CrossHair(*this);}
+  
+  void configure(double rad, double linewidth, bool smooth, bool boxed);
+  void drawBegin();
+  void drawEnd();
+  void draw(Qwt3D::Triple const&);
+
+private:
+  bool boxed_, smooth_;
+  double linewidth_, radius_;
+  GLboolean oldstate_;
+};
+
+//! The Point Style
+class QWT3D_EXPORT Dot : public VertexEnrichment
+{
+public: 
+  Dot();
+  Dot(double pointsize, bool smooth);
+
+  Qwt3D::Enrichment* clone() const {return new Dot(*this);}
+
+  void configure(double pointsize, bool smooth);
+  void drawBegin();
+  void drawEnd();
+  void draw(Qwt3D::Triple const&);
+
+private:
+  bool smooth_;
+  double pointsize_;
+  GLboolean oldstate_;
+};
+
+//! The Cone Style
+class QWT3D_EXPORT Cone : public VertexEnrichment
+{
+public:
+  Cone();
+  Cone(double rad, unsigned quality);
+  ~Cone();
+
+  Qwt3D::Enrichment* clone() const {return new Cone(*this);}
+  
+  void configure(double rad, unsigned quality);
+  void draw(Qwt3D::Triple const&);
+
+private:
+	GLUquadricObj *hat;
+	GLUquadricObj *disk;
+  unsigned quality_;
+  double radius_;
+  GLboolean oldstate_;
+};
+
+//! 3D vector field. 
+/**
+	The class encapsulates a vector field including his OpenGL representation as arrow field. 
+	The arrows can be configured in different aspects (color, shape, painting quality).
+	
+*/
+class QWT3D_EXPORT Arrow : public VertexEnrichment
+{
+public:
+	
+	Arrow();
+	~Arrow();
+
+  Qwt3D::Enrichment* clone() const {return new Arrow(*this);}
+
+	void configure(int segs, double relconelength, double relconerad, double relstemrad);
+  void setQuality(int val) {segments_ = val;} //!< Set the number of faces for the arrow
+  void draw(Qwt3D::Triple const&);
+
+  void setTop(Qwt3D::Triple t){top_ = t;}
+  void setColor(Qwt3D::RGBA rgba) {rgba_ = rgba;}
+
+private:
+
+	GLUquadricObj *hat;
+	GLUquadricObj *disk;
+	GLUquadricObj *base;
+	GLUquadricObj *bottom;
+  GLboolean oldstate_;
+
+	double calcRotation(Qwt3D::Triple& axis, Qwt3D::FreeVector const& vec);
+
+	int segments_;
+	double rel_cone_length;
+	
+	double rel_cone_radius;
+	double rel_stem_radius;
+
+  Qwt3D::Triple top_;
+  Qwt3D::RGBA rgba_;
+};
+
+} // ns
+
+#endif
diff --git a/include/qwt3d_function.h b/include/qwt3d_function.h
new file mode 100644
index 0000000..c87939d
--- /dev/null
+++ b/include/qwt3d_function.h
@@ -0,0 +1,41 @@
+#ifndef qwt3d_function_h__2004_03_05_13_51_begin_guarded_code
+#define qwt3d_function_h__2004_03_05_13_51_begin_guarded_code
+
+#include "qwt3d_gridmapping.h"
+
+namespace Qwt3D
+{
+
+class SurfacePlot;
+
+//! Abstract base class for mathematical functions
+/**
+	A Function encapsulates a mathematical function with rectangular domain. The user has to adapt the pure virtual operator() 
+	to get a working object. Also, the client code should call setDomain, setMesh and create for reasonable operating conditions.
+*/
+class QWT3D_EXPORT Function : public GridMapping
+{
+
+public:
+	
+  Function(); //!< Constructs Function object w/o assigned SurfacePlot.
+  explicit Function(Qwt3D::SurfacePlot& plotWidget); //!< Constructs Function object and assigns a SurfacePlot
+  explicit Function(Qwt3D::SurfacePlot* plotWidget); //!< Constructs Function object and assigns a SurfacePlot
+	virtual double operator()(double x, double y) = 0; //!< Overwrite this.
+		
+	void setMinZ(double val); //!< Sets minimal z value.
+	void setMaxZ(double val); //!< Sets maximal z value.
+
+	//! Assigns a new SurfacePlot and creates a data representation for it.
+	virtual bool create(Qwt3D::SurfacePlot& plotWidget);
+	//! Creates data representation for the actual assigned SurfacePlot.
+	virtual bool create();
+  //! Assigns the object to another widget. To see the changes, you have to call this function before create().
+  void assign(Qwt3D::SurfacePlot& plotWidget); 
+  //! Assigns the object to another widget. To see the changes, you have to call this function before create().
+  void assign(Qwt3D::SurfacePlot* plotWidget); 
+};
+
+} // ns
+
+#endif /* include guarded */
diff --git a/include/qwt3d_global.h b/include/qwt3d_global.h
new file mode 100644
index 0000000..eb66a44
--- /dev/null
+++ b/include/qwt3d_global.h
@@ -0,0 +1,58 @@
+#ifndef QWT3D_GLOBAL_H
+#define QWT3D_GLOBAL_H
+
+#include <qglobal.h>
+#if QT_VERSION < 0x040000
+#include <qmodules.h>
+#endif
+
+#define QWT3D_MAJOR_VERSION 0
+#define QWT3D_MINOR_VERSION 2
+#define QWT3D_PATCH_VERSION 6
+
+//
+// Create Qwt3d DLL if QWT3D_DLL is defined (Windows only)
+//
+
+#if defined(Q_WS_WIN)
+  #if defined(_MSC_VER) /* MSVC Compiler */
+    #pragma warning(disable: 4251) // dll interface required for stl templates
+	   //pragma warning(disable: 4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data
+    #pragma warning(disable: 4786) // truncating debug info after 255 characters
+    #pragma warning(disable: 4660) // template-class specialization 'identifier' is already instantiated
+    #if (_MSC_VER >= 1400) /* VS8 - not sure about VC7 */
+      #pragma warning(disable: 4996) /* MS security enhancements */
+    #endif
+  #endif
+
+  #if defined(QWT3D_NODLL)
+    #undef QWT3D_MAKEDLL
+    #undef QWT3D_DLL
+    #undef QWT3D_TEMPLATEDLL
+  #endif
+
+  #ifdef QWT3D_DLL
+    #if defined(QWT3D_MAKEDLL)     /* create a Qwt3d DLL library */
+      #undef QWT3D_DLL
+      #define QWT3D_EXPORT  __declspec(dllexport)
+      #define QWT3D_TEMPLATEDLL
+    #endif
+  #endif
+
+  #if defined(QWT3D_DLL)     /* use a Qwt3d DLL library */
+    #define QWT3D_EXPORT  __declspec(dllimport)
+    #define QWT3D_TEMPLATEDLL
+  #endif
+
+#else // ! Q_WS_WIN
+  #undef QWT3D_MAKEDLL       /* ignore these for other platforms */
+  #undef QWT3D_DLL
+  #undef QWT3D_TEMPLATEDLL
+#endif
+
+#ifndef QWT3D_EXPORT
+  #define QWT3D_EXPORT
+#endif
+
+
+#endif
diff --git a/include/qwt3d_graphplot.h b/include/qwt3d_graphplot.h
new file mode 100644
index 0000000..9a6382c
--- /dev/null
+++ b/include/qwt3d_graphplot.h
@@ -0,0 +1,24 @@
+#ifndef qwt3d_graphplot_h__2004_03_06_01_57_begin_guarded_code
+#define qwt3d_graphplot_h__2004_03_06_01_57_begin_guarded_code
+
+#include "qwt3d_plot.h"
+
+namespace Qwt3D
+{
+
+//! TODO
+class QWT3D_EXPORT GraphPlot : public Plot3D
+{
+//    Q_OBJECT
+
+public:
+  GraphPlot( QWidget* parent = 0, const char* name = 0 );
+
+protected:
+	virtual void createData() = 0;
+};
+
+} // ns
+
+
+#endif
diff --git a/include/qwt3d_gridmapping.h b/include/qwt3d_gridmapping.h
new file mode 100644
index 0000000..7b9700b
--- /dev/null
+++ b/include/qwt3d_gridmapping.h
@@ -0,0 +1,34 @@
+#ifndef qwt3d_gridmapping_h__2004_03_06_12_31_begin_guarded_code
+#define qwt3d_gridmapping_h__2004_03_06_12_31_begin_guarded_code
+
+#include "qwt3d_mapping.h"
+
+namespace Qwt3D
+{
+
+class SurfacePlot;
+
+
+//! Abstract base class for mappings acting on rectangular grids
+/**
+
+*/
+class QWT3D_EXPORT GridMapping : public Mapping
+{
+public:
+  GridMapping(); //!< Constructs GridMapping object w/o assigned SurfacePlot.
+
+	void setMesh(unsigned int columns, unsigned int rows); //!< Sets number of rows and columns. 
+	void setDomain(double minu, double maxu, double minv, double maxv); //!< Sets u-v domain boundaries.
+  void restrictRange(Qwt3D::ParallelEpiped const&); //!< Restrict the mappings range to the parallelepiped 
+
+protected:
+  Qwt3D::ParallelEpiped range_p;
+  Qwt3D::SurfacePlot* plotwidget_p;
+	unsigned int umesh_p, vmesh_p;
+	double minu_p, maxu_p, minv_p, maxv_p;
+};
+
+} // ns
+
+#endif /* include guarded */
diff --git a/include/qwt3d_helper.h b/include/qwt3d_helper.h
new file mode 100644
index 0000000..9596483
--- /dev/null
+++ b/include/qwt3d_helper.h
@@ -0,0 +1,36 @@
+#ifndef __HELPER_H__
+#define __HELPER_H__
+
+#include <math.h>
+#include <float.h>
+#include <vector>
+#include <algorithm>
+
+namespace
+{
+	inline double Min_(double a, double b)
+	{
+		return (a<b) ? a : b;
+	}
+}
+
+namespace Qwt3D
+{
+
+inline bool isPracticallyZero(double a, double b = 0)
+{
+  if (!b)
+		return (fabs (a) <=  DBL_MIN);	
+
+	return (fabs (a - b) <= Min_(fabs(a), fabs(b))*DBL_EPSILON);	
+}
+ 
+inline int round(double d)
+{
+	return (d>0) ? int(d+0.5) : int(d-0.5);
+}
+
+
+} //ns
+
+#endif
diff --git a/include/qwt3d_io.h b/include/qwt3d_io.h
new file mode 100644
index 0000000..9512e1d
--- /dev/null
+++ b/include/qwt3d_io.h
@@ -0,0 +1,141 @@
+#ifndef __qwt3d_io_2003_07_04_23_27__
+#define __qwt3d_io_2003_07_04_23_27__
+
+#include <vector>
+#include <algorithm>
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include "qwt3d_global.h"
+
+namespace Qwt3D
+{
+
+class Plot3D;
+/** 
+IO provides a generic interface for standard and user written I/O handlers. 
+It also provides functionality for the registering of such handlers in the
+framework.\n 
+The interface mimics roughly Qt's QImageIO functions for defining  
+image input/output functions. 
+*/
+class QWT3D_EXPORT IO
+{
+
+public:
+  /*! 
+    The function type that can be processed by the define... members.
+    An extension is the IO::Functor.
+  */
+  typedef bool (*Function)(Plot3D*, QString const& fname);
+  
+  
+  /*! 
+    This class gives more flexibility in implementing 
+    userdefined IO handlers than the simple IO::Function type. 
+  */
+  class Functor
+  {
+  public:
+    virtual ~Functor() {}
+    /*! Must clone the content of *this for an object of a derived class with 
+    \c new and return the pointer. Like operator() the predefined Functors 
+    hide this function from the user, still allowing IO access 
+    (friend declaration)
+    */
+    virtual Functor* clone() const = 0;
+    /*! The workhorse of the user-defined implementation. Eventually, the 
+    framework will call this operator.
+    */
+    virtual bool operator()(Plot3D* plot, QString const& fname) = 0;
+  };
+  
+  static bool defineInputHandler( QString const& format, Function func);
+  static bool defineOutputHandler( QString const& format, Function func);
+  static bool defineInputHandler( QString const& format, Functor const& func);
+  static bool defineOutputHandler( QString const& format, Functor const& func);
+  static bool save(Plot3D*, QString const& fname, QString const& format);
+  static bool load(Plot3D*, QString const& fname, QString const& format);
+  static QStringList inputFormatList();
+  static QStringList outputFormatList();
+  static Functor* outputHandler(QString const& format);
+  static Functor* inputHandler(QString const& format);
+  
+private:  
+  IO(){}
+  
+  //! Lightweight Functor encapsulating an IO::Function
+  class Wrapper : public Functor
+  {
+  public:
+    //! Performs actual input
+    Functor* clone() const { return new Wrapper(*this); }
+    //! Creates a Wrapper object from a function pointer
+    explicit Wrapper(Function h) : hdl(h) {}
+    //! Returns a pointer to the wrapped function
+    bool operator()(Plot3D* plot, QString const& fname)
+    {
+      return (hdl) ? (*hdl)(plot, fname) : false;
+    }
+  private: 
+    Function hdl;
+  };  
+  
+  struct Entry
+  {
+    Entry();    
+    ~Entry();
+
+    Entry(Entry const& e);
+    void operator=(Entry const& e);
+    
+    Entry(QString const& s, Functor const& f);
+    Entry(QString const& s, Function f);
+    
+    QString fmt;
+    Functor* iofunc;
+  };
+
+  struct FormatCompare
+  {
+    explicit FormatCompare(Entry const& e);
+    bool operator() (Entry const& e);
+
+    Entry e_;
+  };
+ 
+  struct FormatCompare2
+  {
+    explicit FormatCompare2(QString s);
+    bool operator() (Entry const& e);
+
+    QString s_;
+  };
+    
+  typedef std::vector<Entry> Container;
+  typedef Container::iterator IT;
+
+  static bool add_unique(Container& l, Entry const& e);
+  static IT find(Container& l, QString const& fmt);
+  static Container& rlist();
+  static Container& wlist();
+  static void setupHandler();
+};
+
+//! Provides Qt's Pixmap output facilities
+class QWT3D_EXPORT PixmapWriter : public IO::Functor
+{
+friend class IO;
+public:  
+  PixmapWriter() : quality_(-1) {}
+  void setQuality(int val);
+private:
+  IO::Functor* clone() const {return new PixmapWriter(*this);}
+  bool operator()(Plot3D* plot, QString const& fname);
+  QString fmt_;
+  int quality_;
+};
+
+} //ns
+
+#endif
diff --git a/include/qwt3d_io_gl2ps.h b/include/qwt3d_io_gl2ps.h
new file mode 100644
index 0000000..f79489f
--- /dev/null
+++ b/include/qwt3d_io_gl2ps.h
@@ -0,0 +1,91 @@
+#ifndef qwt3d_io_gl2ps_h__2004_05_07_01_16_begin_guarded_code
+#define qwt3d_io_gl2ps_h__2004_05_07_01_16_begin_guarded_code
+
+#include <time.h>
+
+#if QT_VERSION < 0x040000
+#include <qgl.h>
+#else
+#include <QtOpenGL/qgl.h>
+#endif
+
+#include "qwt3d_types.h"
+#include "qwt3d_io.h"
+
+namespace Qwt3D
+{
+
+//! Provides EPS, PS, PDF and TeX output
+/*!
+
+ */
+class QWT3D_EXPORT VectorWriter : public IO::Functor
+{
+friend class IO;
+
+public:
+  //! The possible output formats for the text parts of the scene
+  enum TEXTMODE
+  {
+    PIXEL, //!< All text will be converted to pixmaps
+    NATIVE, //!< Text output in the native output format
+    TEX //!< Text output in additional LaTeX file as an overlay
+  };
+  //! The possible behaviour for landscape settings 
+  enum LANDSCAPEMODE
+  {
+    ON,  //!< Landscape mode on
+    OFF, //!< Landscape mode off
+    AUTO //!< The output orientation depends on the plot widgets aspect ratio (default)
+  };
+  
+  //! The possible sorting types which are translated in gl2ps types  
+  enum SORTMODE
+  {
+    NOSORT,  //!< No sorting at all
+    SIMPLESORT, //!< A more simple (yet quicker) algorithm (default)
+    BSPSORT //!< BSP SORT (best and slow!)
+  };
+  
+  VectorWriter(); 
+
+  void setLandscape(LANDSCAPEMODE val) {landscape_ = val;} //!< Sets landscape mode.
+  LANDSCAPEMODE landscape() const {return landscape_;} //!< Returns the current landscape mode
+  
+  void setTextMode(TEXTMODE val, QString fname = "");
+  TEXTMODE textMode() const {return textmode_;} //!< Return current text output mode.
+  
+  
+  //! Sets one of the SORTMODE sorting modes.
+  void setSortMode(SORTMODE val) {sortmode_ = val;}
+  SORTMODE sortMode() const {return sortmode_;} //!< Returns gl2ps sorting type.
+  //! Turns compressed output on or off (no effect if zlib support is not available)
+  void setCompressed(bool val);
+  //! Returns compression mode (always false if zlib support has not been set) 
+  bool compressed() const {return compressed_;} 
+
+  bool setFormat(QString const& format);
+
+private:
+  IO::Functor* clone() const;
+  bool operator()(Plot3D* plot, QString const& fname);
+
+  GLint gl2ps_format_;
+  bool formaterror_;
+  bool compressed_;
+  SORTMODE sortmode_;
+  LANDSCAPEMODE landscape_;
+  TEXTMODE textmode_;
+  QString texfname_;
+};
+
+GLint setDeviceLineWidth(GLfloat val);
+GLint setDevicePointSize(GLfloat val);
+GLint drawDevicePixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GLint drawDeviceText(const char* str, const char* fontname, int fontsize, Qwt3D::Triple pos, Qwt3D::RGBA rgba, Qwt3D::ANCHOR align, double gap);
+void setDevicePolygonOffset(GLfloat factor, GLfloat units);
+
+
+} // ns
+
+#endif /* include guarded */
diff --git a/include/qwt3d_io_reader.h b/include/qwt3d_io_reader.h
new file mode 100644
index 0000000..1b991ee
--- /dev/null
+++ b/include/qwt3d_io_reader.h
@@ -0,0 +1,35 @@
+#ifndef qwt3d_reader_h__2004_03_07_14_03_begin_guarded_code
+#define qwt3d_reader_h__2004_03_07_14_03_begin_guarded_code
+
+#include "qwt3d_io.h"
+
+namespace Qwt3D
+{
+
+/*! 
+Functor for reading of native files containing grid data. 
+As a standart input functor associated with "mes" and "MES"
+file extensions.   
+*/
+class QWT3D_EXPORT NativeReader : public IO::Functor
+{
+friend class IO;
+
+public:		
+  NativeReader();
+
+private:
+  //! Provides new NativeReader object. 
+  IO::Functor* clone() const{return new NativeReader(*this);}
+  //! Performs actual input
+  bool operator()(Plot3D* plot, QString const& fname);
+	static const char* magicstring;
+  double minz_, maxz_;
+	bool collectInfo(FILE*& file, QString const& fname, unsigned& xmesh, unsigned& ymesh, 
+									 double& minx, double& maxx, double& miny, double& maxy);
+};
+
+
+} // ns
+
+#endif
diff --git a/include/qwt3d_label.h b/include/qwt3d_label.h
new file mode 100644
index 0000000..3fffc59
--- /dev/null
+++ b/include/qwt3d_label.h
@@ -0,0 +1,80 @@
+#ifndef __LABELPIXMAP_H__
+#define __LABELPIXMAP_H__
+
+#include <qpixmap.h>
+#include <qimage.h>
+#include <qfont.h>
+#include <qpainter.h>
+#include <qfontmetrics.h>
+
+#include "qwt3d_drawable.h"
+
+namespace Qwt3D
+{
+
+//! A Qt string or an output device dependent string
+class QWT3D_EXPORT Label : public Drawable 
+{
+		
+public:
+
+  Label();
+ 	//! Construct label and initialize with font 
+	Label(const QString & family, int pointSize, int weight = QFont::Normal, bool italic = false);
+	
+	//! Sets the labels font
+	void setFont(QString const& family, int pointSize, int weight = QFont::Normal, bool italic = false);
+
+	void adjust(int gap); //!< Fine tunes label;
+	double gap() const {return gap_;} //!< Returns the gap caused by adjust();
+	void setPosition(Qwt3D::Triple pos, ANCHOR a = BottomLeft); //!< Sets the labels position
+	void setRelPosition(Tuple rpos, ANCHOR a); //!< Sets the labels position relative to screen
+	Qwt3D::Triple first() const { return beg_;} //!< Receives bottom left label position
+	Qwt3D::Triple second() const { return end_;} //!< Receives top right label position
+	ANCHOR anchor() const { return anchor_; } //!< Defines an anchor point for the labels surrounding rectangle
+	virtual void setColor(double r, double g, double b, double a = 1);	
+	virtual void setColor(Qwt3D::RGBA rgba);	
+
+	/*!
+	\brief Sets the labels string
+	For unicode labeling (<tt> QChar(0x3c0) </tt> etc.) please look at <a href="http://www.unicode.org/charts/">www.unicode.org</a>.
+	*/
+	void setString(QString const& s);
+	void draw(); //!< Actual drawing
+
+	/**
+		\brief Decides about use of PDF standard fonts for PDF output 
+		If true, Label can use one of the PDF standard fonts (unprecise positioning for now), 
+		otherwise it dumps  pixmaps in the PDF stream (poor quality) 
+	*/
+	static void useDeviceFonts(bool val); 
+	
+
+private:
+
+	Qwt3D::Triple beg_, end_, pos_;
+	QPixmap pm_;
+	QImage  buf_, tex_;
+	QFont font_;
+	QString text_;
+
+	ANCHOR anchor_;
+	
+	void init();
+  void init(const QString & family, int pointSize, int weight = QFont::Normal, bool italic = false);
+	void update(); //!< Enforces an update of the internal pixmap
+	void convert2screen();
+	double width() const;
+	double height() const;
+
+	int gap_;
+
+	bool flagforupdate_;
+
+	static bool devicefonts_;
+
+};
+
+} // ns
+
+#endif
diff --git a/include/qwt3d_mapping.h b/include/qwt3d_mapping.h
new file mode 100644
index 0000000..9779468
--- /dev/null
+++ b/include/qwt3d_mapping.h
@@ -0,0 +1,27 @@
+#ifndef qwt3d_mapping_h__2004_03_05_13_51_begin_guarded_code
+#define qwt3d_mapping_h__2004_03_05_13_51_begin_guarded_code
+
+#include <qstring.h>
+#include "qwt3d_global.h"
+#include "qwt3d_types.h"
+
+namespace Qwt3D
+{
+
+//! Abstract base class for general mappings
+/**
+
+*/
+class QWT3D_EXPORT Mapping
+{
+
+public:
+	
+  virtual ~Mapping(){} //!< Destructor.
+	virtual QString name() const { return QString(""); } //!< Descriptive String.
+};
+
+
+} // ns
+
+#endif /* include guarded */
diff --git a/include/qwt3d_multiplot.h b/include/qwt3d_multiplot.h
new file mode 100644
index 0000000..5a1e7cc
--- /dev/null
+++ b/include/qwt3d_multiplot.h
@@ -0,0 +1,24 @@
+#ifndef qwt3d_multiplot_h__2004_03_06_02_05_begin_guarded_code
+#define qwt3d_multiplot_h__2004_03_06_02_05_begin_guarded_code
+
+#include "qwt3d_plot.h"
+
+namespace Qwt3D
+{
+
+//! TODO
+class QWT3D_EXPORT MultiPlot : public Plot3D
+{
+//    Q_OBJECT
+
+public:
+  MultiPlot( QWidget* parent = 0, const char* name = 0 ){}
+
+protected:
+	virtual void createData() = 0;
+};
+
+} // ns
+
+
+#endif
diff --git a/include/qwt3d_openglhelper.h b/include/qwt3d_openglhelper.h
new file mode 100644
index 0000000..0ee80de
--- /dev/null
+++ b/include/qwt3d_openglhelper.h
@@ -0,0 +1,130 @@
+#ifndef __openglhelper_2003_06_06_15_49__
+#define __openglhelper_2003_06_06_15_49__
+
+#include "qglobal.h"
+#if QT_VERSION < 0x040000
+#include <qgl.h>
+#else
+#include <QtOpenGL/qgl.h>
+#endif
+
+namespace Qwt3D
+{
+
+#ifndef QWT3D_NOT_FOR_DOXYGEN
+
+class GLStateBewarer
+{
+public:
+	
+	GLStateBewarer(GLenum what, bool on, bool persist=false)
+	{
+		state_ = what;
+		stateval_ = glIsEnabled(what);	
+		if (on)
+			turnOn(persist);
+		else
+			turnOff(persist);
+	}
+
+	~GLStateBewarer() 
+	{
+		if (stateval_)
+			glEnable(state_);
+		else
+			glDisable(state_);
+	}
+	
+	void turnOn(bool persist = false)
+	{
+		glEnable(state_);
+		if (persist)
+			stateval_ = true;
+	}
+	
+	void turnOff(bool persist = false)
+	{
+		glDisable(state_);
+		if (persist)
+			stateval_ = false;
+	}
+
+
+private:
+	
+	GLenum state_;
+	bool stateval_;
+
+};
+
+inline const GLubyte* gl_error()
+{
+	GLenum errcode;
+	const GLubyte* err = 0;
+	
+	if ((errcode = glGetError()) != GL_NO_ERROR)
+	{
+		err = gluErrorString(errcode);
+	}
+	return err;
+}
+
+inline	void SaveGlDeleteLists(GLuint& lstidx, GLsizei range)
+{
+	if (glIsList(lstidx))
+		glDeleteLists(lstidx, range);
+	lstidx = 0;
+}
+
+//! get OpenGL transformation matrices
+/**
+	Don't rely on (use) this in display lists !
+	\param modelMatrix should be a GLdouble[16]
+	\param projMatrix should be a GLdouble[16]
+	\param viewport should be a GLint[4]
+*/
+inline void getMatrices(GLdouble* modelMatrix, GLdouble* projMatrix, GLint* viewport)
+{
+	glGetIntegerv(GL_VIEWPORT, viewport);
+	glGetDoublev(GL_MODELVIEW_MATRIX,	modelMatrix);
+	glGetDoublev(GL_PROJECTION_MATRIX,	projMatrix);
+}
+
+//! simplified glut routine (glUnProject): windows coordinates_p --> object coordinates_p 
+/**
+	Don't rely on (use) this in display lists !
+*/
+inline bool ViewPort2World(double& objx, double& objy, double& objz, double winx, double winy, double winz)
+{
+	GLdouble modelMatrix[16];
+  GLdouble projMatrix[16];
+  GLint viewport[4];
+
+	getMatrices(modelMatrix, projMatrix, viewport);
+	int res = gluUnProject(winx, winy, winz, modelMatrix, projMatrix, viewport, &objx, &objy, &objz);
+
+	return (res == GL_FALSE) ? false : true;
+}
+
+//! simplified glut routine (glProject): object coordinates_p --> windows coordinates_p 
+/**
+	Don't rely on (use) this in display lists !
+*/
+inline bool World2ViewPort(double& winx, double& winy, double& winz, double objx, double objy, double objz )
+{
+	GLdouble modelMatrix[16];
+  GLdouble projMatrix[16];
+  GLint viewport[4];
+
+	getMatrices(modelMatrix, projMatrix, viewport);
+	int res = gluProject(objx, objy, objz, modelMatrix, projMatrix, viewport, &winx, &winy, &winz);
+
+	return (res == GL_FALSE) ? false : true;
+}
+
+
+#endif // QWT3D_NOT_FOR_DOXYGEN
+
+} // ns
+
+#endif
diff --git a/include/qwt3d_parametricsurface.h b/include/qwt3d_parametricsurface.h
new file mode 100644
index 0000000..7947557
--- /dev/null
+++ b/include/qwt3d_parametricsurface.h
@@ -0,0 +1,44 @@
+#ifndef qwt3d_parametricsurface_h__2004_03_05_23_43_begin_guarded_code
+#define qwt3d_parametricsurface_h__2004_03_05_23_43_begin_guarded_code
+
+#include "qwt3d_gridmapping.h"
+
+namespace Qwt3D
+{
+
+class SurfacePlot;
+
+
+//! Abstract base class for parametric surfaces
+/**
+
+*/
+class QWT3D_EXPORT ParametricSurface : public GridMapping
+{
+
+public:
+  ParametricSurface(); //!< Constructs ParametricSurface object w/o assigned SurfacePlot.
+  //! Constructs ParametricSurface object and assigns a SurfacePlot
+  explicit ParametricSurface(Qwt3D::SurfacePlot& plotWidget); 
+  //! Constructs ParametricSurface object and assigns a SurfacePlot
+  explicit ParametricSurface(Qwt3D::SurfacePlot* plotWidget); 
+  //! Overwrite this
+  virtual Qwt3D::Triple operator()(double u, double v) = 0; 
+	//! Assigns a new SurfacePlot and creates a data representation for it.
+	virtual bool create(Qwt3D::SurfacePlot& plotWidget);
+	//! Creates data representation for the actual assigned SurfacePlot.
+	virtual bool create();
+  //! Assigns the object to another widget. To see the changes, you have to call this function before create().
+  void assign(Qwt3D::SurfacePlot& plotWidget);
+  //! Assigns the object to another widget. To see the changes, you have to call this function before create().
+  void assign(Qwt3D::SurfacePlot* plotWidget);
+  //! Provide information about periodicity of the 'u' resp. 'v' domains.
+  void setPeriodic(bool u, bool v); 
+
+private:
+  bool uperiodic_, vperiodic_;
+};
+
+} // ns
+
+#endif /* include guarded */
diff --git a/include/qwt3d_plot.h b/include/qwt3d_plot.h
new file mode 100644
index 0000000..ec60d70
--- /dev/null
+++ b/include/qwt3d_plot.h
@@ -0,0 +1,315 @@
+#ifndef __plot3d_2003_06_09_12_14__
+#define __plot3d_2003_06_09_12_14__
+
+#include "qwt3d_coordsys.h"
+#include "qwt3d_enrichment_std.h"
+
+namespace Qwt3D
+{
+  
+//! Base class for all plotting widgets
+/*!
+  Plot3D handles all the common features for plotting widgets - coordinate system, transformations, mouse/keyboard
+  handling, labeling etc.. It contains some pure virtual functions and is, in so far, an abstract base class.
+	The class provides interfaces for data handling and implements basic data controlled color allocation.
+*/
+class QWT3D_EXPORT Plot3D : public QGLWidget
+{
+    Q_OBJECT
+
+public:
+	
+#if QT_VERSION < 0x040000
+    Plot3D( QWidget* parent = 0, const char* name = 0 );
+#else
+    Plot3D ( QWidget * parent = 0, const QGLWidget * shareWidget = 0 );
+#endif
+    virtual ~Plot3D();
+
+    QPixmap renderPixmap (int w=0, int h=0, bool useContext=false);	  
+    void updateData(); //!< Recalculate data
+		void createCoordinateSystem(Qwt3D::Triple beg, Qwt3D::Triple end);
+		Qwt3D::CoordinateSystem* coordinates() { return &coordinates_p; } //!< Returns pointer to CoordinateSystem object
+		Qwt3D::ColorLegend* legend() { return &legend_;} //!< Returns pointer to ColorLegend object
+		
+		double xRotation() const { return xRot_;}  //!< Returns rotation around X axis [-360..360] (some angles are equivalent)
+		double yRotation() const { return yRot_;}  //!< Returns rotation around Y axis [-360..360] (some angles are equivalent)
+		double zRotation() const { return zRot_;}  //!< Returns rotation around Z axis [-360..360] (some angles are equivalent)
+
+		double xShift() const { return xShift_;} //!< Returns shift along X axis (object coordinates)
+		double yShift() const { return yShift_;} //!< Returns shift along Y axis (object coordinates)
+		double zShift() const { return zShift_;} //!< Returns shift along Z axis (object coordinates)
+		
+		double xViewportShift() const { return xVPShift_;} //!< Returns relative shift [-1..1] along X axis (view coordinates)
+		double yViewportShift() const { return yVPShift_;} //!< Returns relative shift [-1..1] along Y axis (view coordinates)
+		
+		double xScale() const { return xScale_;} //!< Returns scaling for X values [0..inf]
+		double yScale() const { return yScale_;} //!< Returns scaling for Y values [0..inf]
+		double zScale() const { return zScale_;} //!< Returns scaling for Z values [0..inf]
+
+		double zoom() const { return zoom_;} //!< Returns zoom (0..inf)
+
+		bool ortho() const { return ortho_; } //!< Returns orthogonal (true) or perspective (false) projection
+		void setPlotStyle( Qwt3D::PLOTSTYLE val);
+		Qwt3D::Enrichment* setPlotStyle( Qwt3D::Enrichment const& val);
+		Qwt3D::PLOTSTYLE plotStyle() const { return plotstyle_; }//!< Returns plotting style
+    //! Returns current Enrichment object used for plotting styles (if set, zero else)
+    Qwt3D::Enrichment* userStyle() const { return userplotstyle_p; }
+    void		setShading( Qwt3D::SHADINGSTYLE val );
+		Qwt3D::SHADINGSTYLE shading() const { return shading_; }//!< Returns shading style
+		void setIsolines(int isolines);
+		int isolines() const { return isolines_;} //!< Returns number of isolines
+	
+  	void setSmoothMesh(bool val) {smoothdatamesh_p = val;} //!< Enables/disables smooth data mesh lines. Default is false
+    bool smoothDataMesh() const {return smoothdatamesh_p;} //!< True if mesh antialiasing is on
+		void setBackgroundColor(Qwt3D::RGBA rgba); //!< Sets widgets background color
+		Qwt3D::RGBA backgroundRGBAColor() const {return bgcolor_;} //!< Returns the widgets background color
+		void setMeshColor(Qwt3D::RGBA rgba); //!< Sets color for data mesh
+		Qwt3D::RGBA meshColor() const {return meshcolor_;} //!< Returns color for data mesh
+		void setMeshLineWidth(double lw); //!< Sets line width for data mesh
+		double meshLineWidth() const {return meshLineWidth_;} //!< Returns line width for data mesh
+		void setDataColor(Color* col); //!< Sets new data color object
+    const Color* dataColor() const {return datacolor_p;} //!< Returns data color object
+
+    virtual Qwt3D::Enrichment* addEnrichment(Qwt3D::Enrichment const&); //!< Add an Enrichment
+    virtual bool degrade(Qwt3D::Enrichment*); //!< Remove an Enrichment
+
+		Qwt3D::ParallelEpiped hull() const { return hull_;} //!< Returns rectangular hull   
+
+		void showColorLegend(bool);
+		
+		void setCoordinateStyle(Qwt3D::COORDSTYLE st); //!< Sets style of coordinate system.
+		void setPolygonOffset(double d);
+		double polygonOffset() const {return polygonOffset_;} //!< Returns relative value for polygon offset [0..1]
+		
+		void setTitlePosition(double rely, double relx = 0.5, Qwt3D::ANCHOR = Qwt3D::TopCenter);
+		void setTitleFont(const QString& family, int pointSize, int weight = QFont::Normal, bool italic = false);
+		void setTitleColor(Qwt3D::RGBA col) {title_.setColor(col);} //!< Set caption color
+		void setTitle(const QString& title) {title_.setString(title);} //!< Set caption text (one row only)
+
+		
+		void assignMouse(MouseState xrot, MouseState yrot, MouseState zrot,
+										 MouseState xscale, MouseState yscale, MouseState zscale,
+										 MouseState zoom, MouseState xshift, MouseState yshift);
+		
+		bool mouseEnabled() const; //!< Returns true, if the widget accept mouse input from the user
+		void assignKeyboard(
+       KeyboardState xrot_n, KeyboardState xrot_p
+      ,KeyboardState yrot_n, KeyboardState yrot_p
+      ,KeyboardState zrot_n, KeyboardState zrot_p
+			,KeyboardState xscale_n, KeyboardState xscale_p 
+      ,KeyboardState yscale_n, KeyboardState yscale_p
+      ,KeyboardState zscale_n, KeyboardState zscale_p
+			,KeyboardState zoom_n, KeyboardState zoom_p
+      ,KeyboardState xshift_n, KeyboardState xshift_p
+      ,KeyboardState yshift_n, KeyboardState yshift_p
+      );
+		
+		bool keyboardEnabled() const; //!< Returns true, if the widget accept keyboard input from the user
+    //! Sets speed for keyboard driven transformations
+    void setKeySpeed(double rot, double scale, double shift); 
+    //! Gets speed for keyboard driven transformations
+    void keySpeed(double& rot, double& scale, double& shift) const; 
+      
+    bool lightingEnabled() const; //!< Returns true, if Lighting is enabled, false else
+    //! Turn light on
+    void illuminate(unsigned light = 0);
+    //! Turn light off
+    void blowout(unsigned light = 0);
+
+    void setMaterialComponent(GLenum property, double r, double g, double b, double a = 1.0);    
+    void setMaterialComponent(GLenum property, double intensity);    
+    void setShininess(double exponent);
+    void setLightComponent(GLenum property, double r, double g, double b, double a = 1.0, unsigned light=0);    
+    void setLightComponent(GLenum property, double intensity, unsigned light=0);    
+
+    //! Returns Light 'idx' rotation around X axis [-360..360] (some angles are equivalent)
+    double xLightRotation(unsigned idx = 0) const { return (idx<8) ? lights_[idx].rot.x : 0;}
+    //! Returns Light 'idx' rotation around Y axis [-360..360] (some angles are equivalent)
+    double yLightRotation(unsigned idx = 0) const { return (idx<8) ? lights_[idx].rot.y : 0;}
+    //! Returns Light 'idx' rotation around Z axis [-360..360] (some angles are equivalent)
+    double zLightRotation(unsigned idx = 0) const { return (idx<8) ? lights_[idx].rot.z : 0;}
+
+    //! Returns shift of Light 'idx 'along X axis (object coordinates)
+    double xLightShift(unsigned idx = 0) const {return (idx<8) ? lights_[idx].shift.x : 0;} 
+    //! Returns shift of Light 'idx 'along Y axis (object coordinates)
+    double yLightShift(unsigned idx = 0) const {return (idx<8) ? lights_[idx].shift.y : 0;} 
+    //! Returns shift of Light 'idx 'along Z axis (object coordinates)
+    double zLightShift(unsigned idx = 0) const {return (idx<8) ? lights_[idx].shift.z : 0;}
+	  //! Returns true if valid data available, false else
+    bool hasData() const { return (actualData_p) ? !actualData_p->empty() : false;}
+
+    
+signals:
+		
+		//! Emitted, if the rotation is changed
+    void rotationChanged( double xAngle, double yAngle, double zAngle ); 
+		//! Emitted, if the shift is changed
+		void shiftChanged( double xShift, double yShift, double zShift );
+		//! Emitted, if the viewport shift is changed
+		void vieportShiftChanged( double xShift, double yShift );
+		//! Emitted, if the scaling is changed
+    void scaleChanged( double xScale, double yScale, double zScale );
+		//! Emitted, if the zoom is changed
+		void zoomChanged(double);
+		//! Emitted, if the projection mode is changed
+    void projectionChanged(bool);
+
+public slots:
+
+		void	setRotation( double xVal, double yVal, double zVal ); 																														
+		void	setShift( double xVal, double yVal, double zVal );    																														
+		void	setViewportShift( double xVal, double yVal );         																														
+		void	setScale( double xVal, double yVal, double zVal );    																														
+		void	setZoom( double );                                    																														
+		                                                              																														
+		void  setOrtho(bool);                                       																														
+    
+		void	enableMouse(bool val=true); //!< Enable mouse input   																														
+		void	disableMouse(bool val =true); //!< Disable mouse input																														
+		void	enableKeyboard(bool val=true); //!< Enable keyboard input   																														
+		void	disableKeyboard(bool val =true); //!< Disable keyboard input																														
+
+    void enableLighting(bool val = true); //!< Turn Lighting on or off
+    void disableLighting(bool val = true); //!< Turn Lighting on or off
+
+    void	setLightRotation( double xVal, double yVal, double zVal, unsigned int idx = 0 ); 																														
+		void	setLightShift( double xVal, double yVal, double zVal, unsigned int idx = 0 );    																														
+
+    virtual bool savePixmap(QString const& fileName, QString const& format); //!<  Saves content to pixmap format
+		//!  Saves content to vector format
+    virtual bool saveVector(QString const& fileName, QString const& format, VectorWriter::TEXTMODE text, VectorWriter::SORTMODE sortmode);
+		virtual bool save(QString const& fileName, QString const& format); //!<  Saves content
+
+protected:
+    typedef std::list<Qwt3D::Enrichment*> EnrichmentList;
+    typedef EnrichmentList::iterator ELIT;
+    
+		void	initializeGL();
+    void	paintGL();
+    void	resizeGL( int w, int h );
+
+		void mousePressEvent( QMouseEvent *e );
+		void mouseReleaseEvent( QMouseEvent *e );
+		void mouseMoveEvent( QMouseEvent *e );
+		void wheelEvent( QWheelEvent *e );		
+
+    void keyPressEvent( QKeyEvent *e );
+
+    Qwt3D::CoordinateSystem coordinates_p;
+		Qwt3D::Color* datacolor_p;
+    Qwt3D::Enrichment* userplotstyle_p;
+    EnrichmentList elist_p;
+
+		virtual void calculateHull() = 0;
+		virtual void createData() = 0;
+    virtual void createEnrichment(Qwt3D::Enrichment&){}
+    virtual void createEnrichments();
+
+		void createCoordinateSystem();
+		void setHull(Qwt3D::ParallelEpiped p) {hull_ = p;}
+
+    bool initializedGL() const {return initializedGL_;}
+
+		enum OBJECTS
+		{
+			DataObject,
+			LegendObject,
+			NormalObject,
+			DisplayListSize // only to have a vector length ...
+		};
+		std::vector<GLuint> displaylists_p;
+    Qwt3D::Data* actualData_p;
+
+
+private:
+    struct Light
+    {  
+      Light() : unlit(true){}
+      bool unlit;  
+      Qwt3D::Triple rot;
+      Qwt3D::Triple shift;
+    };
+    std::vector<Light> lights_;
+
+    GLdouble xRot_, yRot_, zRot_, xShift_, yShift_, zShift_, zoom_
+             , xScale_, yScale_, zScale_, xVPShift_, yVPShift_;
+		
+		Qwt3D::RGBA meshcolor_;
+		double meshLineWidth_;
+		Qwt3D::RGBA bgcolor_;
+		Qwt3D::PLOTSTYLE plotstyle_;
+		Qwt3D::SHADINGSTYLE shading_;
+		Qwt3D::FLOORSTYLE floorstyle_;
+		bool ortho_;
+		double polygonOffset_;
+		int isolines_;
+		bool displaylegend_;
+    bool smoothdatamesh_p;
+
+		Qwt3D::ParallelEpiped hull_;
+
+    Qwt3D::ColorLegend legend_;
+ 
+		Label title_;
+		Qwt3D::Tuple titlerel_;
+		Qwt3D::ANCHOR titleanchor_;
+
+		
+    // mouse
+    
+    QPoint lastMouseMovePosition_;
+		bool mpressed_;
+
+		MouseState xrot_mstate_, 
+				yrot_mstate_, 
+				zrot_mstate_, 
+				xscale_mstate_, 
+				yscale_mstate_, 
+				zscale_mstate_,
+        zoom_mstate_,
+				xshift_mstate_,
+				yshift_mstate_;
+
+		bool mouse_input_enabled_;
+
+		void setRotationMouse(MouseState bstate, double accel, QPoint diff);
+		void setScaleMouse(MouseState bstate, double accel, QPoint diff);
+		void setShiftMouse(MouseState bstate, double accel, QPoint diff);
+
+    // keyboard
+
+		bool kpressed_;
+
+		KeyboardState xrot_kstate_[2], 
+				yrot_kstate_[2], 
+				zrot_kstate_[2], 
+				xscale_kstate_[2], 
+				yscale_kstate_[2], 
+				zscale_kstate_[2],
+        zoom_kstate_[2],
+				xshift_kstate_[2],
+				yshift_kstate_[2];
+
+		bool kbd_input_enabled_;
+    double kbd_rot_speed_, kbd_scale_speed_, kbd_shift_speed_;
+
+		void setRotationKeyboard(KeyboardState kseq, double speed);
+		void setScaleKeyboard(KeyboardState kseq, double speed);
+		void setShiftKeyboard(KeyboardState kseq, double speed);
+
+    
+
+    bool lighting_enabled_;
+    void applyLight(unsigned idx);
+    void applyLights();
+
+    bool initializedGL_;
+    bool renderpixmaprequest_;
+};
+
+
+} // ns
+ 
+
+#endif
diff --git a/include/qwt3d_portability.h b/include/qwt3d_portability.h
new file mode 100644
index 0000000..567a216
--- /dev/null
+++ b/include/qwt3d_portability.h
@@ -0,0 +1,91 @@
+#ifndef qwt3d_portability_h__2005_07_02_11_55_begin_guarded_code
+#define qwt3d_portability_h__2005_07_02_11_55_begin_guarded_code
+
+//! Portability classes providing transparent Qt3/4 support
+
+#include <qnamespace.h>
+#include "qwt3d_global.h"
+
+#if QT_VERSION < 0x040000
+
+namespace Qwt3D
+{
+  #define QWT3DLOCAL8BIT(qstring) \
+  ((const char*)(qstring.local8Bit()))
+
+  typedef int MouseState;
+  typedef int KeyboardState;
+  const Qt::TextFlags SingleLine = Qt::SingleLine;
+} // ns
+
+
+#else // Qt4
+
+#include <QMouseEvent>
+
+namespace Qwt3D
+{
+
+  #define QWT3DLOCAL8BIT(qstring) \
+  ((const char*)(qstring.toLocal8Bit()))
+  
+  const Qt::TextFlag SingleLine = Qt::TextSingleLine;
+  
+  //! This class creates a (mouse-button,modifier) pair (ordinary typedef for int if Qt3 is used)
+  class MouseState
+  {
+  public:
+    MouseState(Qt::MouseButtons mb = Qt::NoButton, Qt::KeyboardModifiers km = Qt::NoModifier)
+      : mb_(mb), km_(km)
+    {
+    }
+
+    MouseState(Qt::MouseButton mb, Qt::KeyboardModifiers km = Qt::NoModifier)
+      : mb_(mb), km_(km)
+    {
+    }
+
+    bool operator==(const MouseState& ms)
+    {
+      return mb_ == ms.mb_ && km_ == ms.km_;
+    }
+
+    bool operator!=(const MouseState& ms)
+    {
+      return !operator==(ms);
+    }
+
+  private:
+    Qt::MouseButtons mb_;
+    Qt::KeyboardModifiers km_;
+  };
+  
+  //! This class creates a (key-button,modifier) pair (ordinary typedef for int if Qt3 is used)
+  class KeyboardState
+  {
+  public:
+    KeyboardState(int key = Qt::Key_unknown, Qt::KeyboardModifiers km = Qt::NoModifier)
+      : key_(key), km_(km)
+    {
+    }
+
+    bool operator==(const KeyboardState& ms)
+    {
+      return key_ == ms.key_ && km_ == ms.km_;
+    }
+
+    bool operator!=(const KeyboardState& ms)
+    {
+      return !operator==(ms);
+    }
+
+  private:
+    int key_;
+    Qt::KeyboardModifiers km_;
+  };
+} // ns
+
+#endif
+
+
+#endif
diff --git a/include/qwt3d_scale.h b/include/qwt3d_scale.h
new file mode 100644
index 0000000..c59c869
--- /dev/null
+++ b/include/qwt3d_scale.h
@@ -0,0 +1,87 @@
+#ifndef qwt3d_scale_h__2004_06_02_22_02_begin_guarded_code
+#define qwt3d_scale_h__2004_06_02_22_02_begin_guarded_code
+
+#include <qstring.h>
+#include "qwt3d_types.h"
+#include "qwt3d_autoscaler.h"
+#include "qwt3d_autoptr.h"
+
+namespace Qwt3D
+{
+
+/*! 
+The class encapsulates non-visual scales. 
+She is utilized by Axis and also collaborates closely with AutoScaler.
+A Scale allows control over all aspects of tic generation including 
+arbitrary transformations of tic values into corresponding strings. 
+The strings contain what eventually will be shown as tic labels.\n
+Standard linear and logarithmic scales have been integrated yet into the Axis 
+interface. User-defined axes can be derived from Scale, LinearScale et al.
+*/
+class QWT3D_EXPORT Scale
+{
+  friend class Axis;
+  friend class qwt3d_ptr<Scale>;
+
+  protected:
+    Scale();
+    virtual ~Scale(){}
+    virtual QString ticLabel(unsigned int idx) const;
+
+    virtual void setLimits(double start, double stop); 
+    virtual void setMajors(int val) {majorintervals_p=val;} //!< Sets number of major intervals
+    virtual void setMinors(int val) {minorintervals_p=val;} //!< Sets number of minor intervals per major interval
+    virtual void setMajorLimits(double start, double stop);
+
+    int majors() const {return majorintervals_p;} //!< Returns major intervals
+    int minors() const {return minorintervals_p;} //!< Returns minor intervals
+
+    //! Derived classes should return a new heap based object here.  
+    virtual Scale* clone() const = 0;
+    //! This function should setup the 2 vectors for major and minor positions;
+    virtual void calculate() = 0;
+    virtual int autoscale(double& a, double& b, double start, double stop, int ivals);
+
+    std::vector<double> majors_p, minors_p; 
+    double start_p, stop_p;
+    int majorintervals_p, minorintervals_p;
+    double mstart_p, mstop_p;
+  
+  private:
+    void destroy() const {delete this;} //!< Used by qwt3d_ptr   
+};
+
+//! The standard (1:1) mapping class for axis numbering
+class QWT3D_EXPORT LinearScale : public Scale
+{
+  friend class Axis;
+  friend class qwt3d_ptr<Scale>;
+protected:
+  int autoscale(double& a, double& b, double start, double stop, int ivals);
+  //! Returns a new heap based object utilized from qwt3d_ptr
+  Scale* clone() const {return new LinearScale(*this);}
+  void calculate();
+  LinearAutoScaler autoscaler_p;
+};
+
+//! log10 scale
+class QWT3D_EXPORT LogScale : public Scale
+{
+  friend class Axis;
+  friend class qwt3d_ptr<Scale>;
+protected:
+  QString ticLabel(unsigned int idx) const;
+  void setMinors(int val);
+  //! Standard ctor
+  LogScale();
+  //! Returns a new heap based object utilized from qwt3d_ptr
+  Scale* clone() const {return new LogScale;}
+  void calculate();
+private:
+  void setupCounter(double& k, int& step);
+};
+
+} // namespace Qwt3D
+
+
+#endif /* include guarded */
diff --git a/include/qwt3d_surfaceplot.h b/include/qwt3d_surfaceplot.h
new file mode 100644
index 0000000..60f8299
--- /dev/null
+++ b/include/qwt3d_surfaceplot.h
@@ -0,0 +1,132 @@
+#ifndef qwt3d_SurfacePlot_h__2004_03_05_11_36_begin_guarded_code
+#define qwt3d_SurfacePlot_h__2004_03_05_11_36_begin_guarded_code
+
+#include "qwt3d_plot.h"
+
+namespace Qwt3D
+{
+//! A class representing  Surfaces
+/**
+	A SurfacePlot ...
+	
+*/
+class QWT3D_EXPORT SurfacePlot : public Plot3D
+{
+    Q_OBJECT
+
+public:
+#if QT_VERSION < 0x040000
+  SurfacePlot( QWidget* parent = 0, const char* name = 0 );
+#else
+  SurfacePlot( QWidget * parent = 0, const QGLWidget * shareWidget = 0 );
+#endif  
+  ~SurfacePlot();
+	void updateNormals(); //!< Recalculates surface normals;
+	int	resolution() const {return resolution_p;} //!< Returns data resolution (1 means all data)
+	std::pair<int,int> facets() const; //!< Returns the number of mesh cells for the ORIGINAL data
+  bool loadFromData(Qwt3D::Triple** data, unsigned int columns, unsigned int rows
+    , bool uperiodic = false, bool vperiodic = false);
+	bool loadFromData(double** data, unsigned int columns, unsigned int rows
+																		,double minx, double maxx, double miny, double maxy);
+	bool loadFromData(Qwt3D::TripleField const& data, Qwt3D::CellField const& poly);
+ 	
+  
+  //! Equivalent to loadFromData();
+  /**
+  \deprecated  Use loadFromData instead
+  */
+  bool createDataRepresentation(Qwt3D::Triple** data, unsigned int columns, unsigned int rows
+    , bool uperiodic = false, bool vperiodic = false)
+  {
+    return loadFromData(data, columns, rows, uperiodic, vperiodic);
+  }
+  //! Equivalent to loadFromData();
+  /**
+  \deprecated  Use loadFromData instead
+  */
+	bool createDataRepresentation(double** data, unsigned int columns, unsigned int rows
+																		,double minx, double maxx, double miny, double maxy)
+  {
+    return loadFromData(data, columns, rows, minx, maxx, miny, maxy);
+  }
+  //! Equivalent to loadFromData();
+  /**
+  \deprecated  Use loadFromData instead
+  */
+  bool createDataRepresentation(Qwt3D::TripleField const& data, Qwt3D::CellField const& poly)
+  {
+    return loadFromData(data, poly);
+  }
+  
+  
+  Qwt3D::FLOORSTYLE floorStyle() const { return floorstyle_;} //!< Return floor style
+  void	setFloorStyle( Qwt3D::FLOORSTYLE val ) {floorstyle_ = val;} //!< Sets floor style
+	void showNormals(bool); //!< Draw normals to every vertex
+	bool normals() const { return datanormals_p;} //!< Returns \c true, if normal drawing is on
+	
+	void setNormalLength(double val); //!< Sets length of normals in percent per hull diagonale
+	double normalLength() const { return normalLength_p; }//!< Returns relative length of normals
+	void setNormalQuality(int val); //!< Increases plotting quality of normal arrows
+	int normalQuality() const { return normalQuality_p; }//!< Returns plotting quality of normal arrows
+
+
+signals:
+	void resolutionChanged(int);
+
+public slots:
+	void setResolution( int );
+
+protected:
+  bool datanormals_p;
+	double normalLength_p;
+	int normalQuality_p;
+  
+	virtual	void calculateHull();
+  virtual void createData();
+  virtual void createEnrichment(Qwt3D::Enrichment& p);
+	virtual void createFloorData();
+ 	void createNormals();
+	void createPoints();	
+
+	int resolution_p;
+
+  void readIn(Qwt3D::GridData& gdata, Triple** data, unsigned int columns, unsigned int rows);
+  void readIn(Qwt3D::GridData& gdata, double** data, unsigned int columns, unsigned int rows, 
+              double minx, double maxx, double miny, double maxy);
+  void calcNormals(GridData& gdata);
+  void sewPeriodic(GridData& gdata);
+
+  //void calcLowResolution();
+private:
+
+	void Data2Floor();
+	void Isolines2Floor();
+	
+  Qwt3D::FLOORSTYLE floorstyle_;
+
+  // grid plot
+  
+  Qwt3D::GridData* actualDataG_;
+	virtual void createDataG();
+	virtual void createFloorDataG();
+  void createNormalsG();
+	void Data2FloorG();
+	void Isolines2FloorG();
+	void setColorFromVertexG(int ix, int iy, bool skip = false);
+
+
+  // mesh plot
+
+  Qwt3D::CellData* actualDataC_;
+	virtual void createDataC();
+	virtual void createFloorDataC();
+  void createNormalsC();
+	void Data2FloorC();
+	void Isolines2FloorC();
+	void setColorFromVertexC(int node, bool skip = false);
+};
+
+} // ns
+
+
+#endif
diff --git a/include/qwt3d_types.h b/include/qwt3d_types.h
new file mode 100644
index 0000000..8e08b03
--- /dev/null
+++ b/include/qwt3d_types.h
@@ -0,0 +1,455 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4786 )
+#endif
+
+#ifndef __DATATYPES_H__
+#define __DATATYPES_H__
+
+#ifdef _DEBUG
+	#include <fstream>
+#endif
+
+#include <string>
+
+#include "qwt3d_global.h"
+
+#if defined(Q_WS_WIN)
+	#include <windows.h>
+#endif
+
+#ifndef WHEEL_DELTA
+	#define WHEEL_DELTA 120
+#endif
+
+#include "qwt3d_portability.h"
+#include "qwt3d_helper.h"
+#include "qwt3d_openglhelper.h"
+
+//! Common namespace for all QwtPlot3D classes
+namespace Qwt3D
+{
+
+const double PI = 3.14159265358979323846264338328;
+
+//! Plotting style
+enum PLOTSTYLE
+{
+	NOPLOT     , //!< No visible data
+	WIREFRAME  , //!< Wireframe style
+	HIDDENLINE , //!< Hidden Line style
+	FILLED     , //!< Color filled polygons w/o edges 
+	FILLEDMESH , //!< Color filled polygons w/ separately colored edges
+  POINTS     , //!< User defined style (used by Enrichments)
+  USER         //!< User defined style (used by Enrichments)
+};
+
+//! Shading style
+enum SHADINGSTYLE
+{
+	FLAT,      //!< Flat shading (OpenGL)
+	GOURAUD    //!< Gouraud Shading (OpenGL)
+};
+
+//! Style of Coordinate system
+enum COORDSTYLE
+{
+	NOCOORD, //!< Coordinate system is not visible 
+	BOX,     //!< Boxed
+	FRAME		 //!< Frame - 3 visible axes
+};
+
+//! Different types of axis scales
+enum SCALETYPE
+{
+	LINEARSCALE,//!< Linear scaling 
+	LOG10SCALE,	//!< Logarithmic scaling (base 10)
+  USERSCALE   //!< User-defined (for extensions)
+};
+
+//! Plotting style for floor data (projections)
+enum FLOORSTYLE
+{
+	NOFLOOR,   //!< Empty floor
+	FLOORISO,  //!< Isoline projections visible
+	FLOORDATA //!< Projected polygons visible
+};
+
+//! Mesh type
+enum DATATYPE
+{
+  GRID,		//!< Rectangular grid
+	POLYGON //!< Convex polygon
+};	
+
+//! The 12 axes
+/**
+\image html axes.png 
+*/
+enum AXIS
+{
+	X1 = 0,   //!<  1st x-axis
+	X2 = 3,   //!<  2nd x-axis
+	X3 = 4,   //!<  3th x-axis
+	X4 = 5,   //!<  4th x-axis
+	Y1 = 1,   //!<  1st y-axis
+	Y2 = 8,   //!<  2nd y-axis
+	Y3 = 7,   //!<  3th y-axis
+	Y4 = 6,   //!<  4th y-axis
+	Z1 = 2,   //!<  1st z-axis
+	Z2 = 9,   //!<  2nd z-axis
+	Z3 = 11,  //!<  3th z-axis
+	Z4 = 10   //!<  4th z-axis
+};
+
+//! The 6 sides
+enum SIDE
+{
+  NOSIDEGRID = 0,
+  LEFT   = 1 << 0,
+  RIGHT  = 1 << 1,
+  CEIL   = 1 << 2,
+  FLOOR  = 1 << 3,
+  FRONT  = 1 << 4,
+  BACK   = 1 << 5
+};
+
+//! Possible anchor points for drawing operations
+enum ANCHOR
+{
+	BottomLeft,
+	BottomRight,
+	BottomCenter,
+	TopLeft,
+	TopRight,
+	TopCenter,
+	CenterLeft,
+	CenterRight,
+	Center
+};
+
+
+//! Tuple <tt>[x,y]</tt>
+struct QWT3D_EXPORT Tuple
+{
+	Tuple() : x(0), y(0) {} //!< Calls Tuple(0,0)
+	Tuple(double X, double Y) : x(X), y(Y) {} //!< Initialize Tuple with x and y
+	//! Tuple coordinates
+  double x,y; 
+};
+
+//! Triple <tt>[x,y,z]</tt>
+/**
+Consider Triples also as vectors in R^3
+*/
+struct QWT3D_EXPORT Triple
+{
+	//! Initialize Triple with x,y and z
+	explicit Triple(double xv = 0,double yv = 0,double zv = 0) 
+		: x(xv), y(yv), z(zv)
+	{
+	}
+	
+#ifndef QWT3D_NOT_FOR_DOXYGEN
+#ifdef Q_OS_IRIX
+  Triple(const Triple& val)
+  {
+    if (&val == this)
+       return;
+    x = val.x;
+    y = val.y;
+    z = val.z;
+  }
+  const Triple& operator=(const Triple& val)
+  {
+    if (&val == this)
+      return *this;
+    x = val.x;
+    y = val.y;
+    z = val.z;
+    return *this;
+  }
+#endif 
+#endif // QWT3D_NOT_FOR_DOXYGEN
+
+  //! Triple coordinates
+	double x,y,z; 
+
+	Triple& operator+=(Triple t)
+	{
+		x += t.x;
+		y += t.y;
+		z += t.z;
+
+		return *this;
+	}
+	
+	Triple& operator-=(Triple t)
+	{
+		x -= t.x;
+		y -= t.y;
+		z -= t.z;
+
+		return *this;
+	}
+	Triple& operator*=(double d)
+	{
+		x *= d;
+		y *= d;
+		z *= d;
+
+		return *this;
+	}
+	Triple& operator/=(double d)
+	{
+		x /= d;
+		y /= d;
+		z /= d;
+
+		return *this;
+	}
+	Triple& operator*=(Triple t) // scale
+	{
+		x *= t.x;
+		y *= t.y;
+		z *= t.z;
+
+		return *this;
+	}
+
+	bool operator!=(Triple t) const
+	{
+		return !isPracticallyZero(x,t.x) || !isPracticallyZero(y,t.y) || !isPracticallyZero(z,t.z);
+	}
+	
+	bool operator==(Triple t) const
+	{
+		return !operator!=(t);
+	}
+
+	double length() const
+	{
+		double l2 = x*x + y*y + z*z;
+		return (isPracticallyZero(l2)) ? 0 :sqrt(l2);
+	}
+	
+	void normalize()
+	{
+		double l = length();
+		if (l)
+			*this /= l;
+	}
+};
+
+inline const Triple operator+(const Triple& t, const Triple& t2)
+{
+	return Triple(t) += t2;
+}
+inline const Triple operator-(const Triple& t, const Triple& t2)
+{
+	return Triple(t) -= t2;
+}
+inline const Triple operator*(double d, const Triple& t)
+{
+	return Triple(t) *= d;
+}
+inline const Triple operator*(const Triple& t, double d)
+{
+	return Triple(t) *= d;
+}
+inline const Triple operator/(double d, const Triple& t)
+{
+	return Triple(t) /= d;
+}
+inline const Triple operator/(const Triple& t, double d)
+{
+	return Triple(t) /= d;
+}
+inline const Triple operator*(const Triple& t, const Triple& t2)
+{
+	return Triple(t) *= t2;
+}
+
+//! Parallelepiped spanned by 2 Triples
+/**
+Please use \em normalized Parallelepipeds:\n\n
+minVertex.x <= maxVertex.x\n
+minVertex.y <= maxVertex.y\n
+minVertex.z <= maxVertex.z\n
+*/
+struct QWT3D_EXPORT ParallelEpiped
+{
+	//! Construct non-initialized Parallelepiped
+	ParallelEpiped()
+	{
+	}
+
+	//! Construct initialized Parallelepiped
+	/**
+		minv -> minVertex\n
+		maxv -> maxVertex\n
+	*/
+	ParallelEpiped(Triple minv, Triple maxv)
+	: minVertex(minv), maxVertex(maxv)
+	{
+	}
+	
+	Triple minVertex;
+	Triple maxVertex;
+};
+
+//! Free vector
+/**
+	FreeVectors represent objects like normal vectors and other vector fields inside R^3 
+*/
+struct QWT3D_EXPORT FreeVector
+{
+	FreeVector()
+	{
+	}
+
+	//! Construct initialized vector
+	/**
+		b -> base\n
+		e -> top\n
+	*/
+	FreeVector(Triple b, Triple t)
+	: base(b), top(t)
+	{
+	}
+	
+	Triple base;
+	Triple top;
+};
+
+//! A free vector field in R^3
+typedef std::vector<FreeVector> FreeVectorField;
+
+//! A point field in R^3
+typedef std::vector<Triple> TripleField;
+//! Holds indices in a TripleField interpreted as counterclockwise node numbering for a convex polygon
+typedef std::vector<unsigned> Cell;
+//! Vector of convex polygons. You need a TripleField as base for the node data
+typedef std::vector<Cell> CellField;
+//! Returns the sum over the sizes of the single cells
+unsigned tesselationSize(Qwt3D::CellField const& t);
+
+//! Red-Green-Blue-Alpha value
+struct QWT3D_EXPORT RGBA
+{
+	RGBA()
+		: r(0), g(0), b(0), a(1)
+		{}
+	RGBA(double rr, double gg, double bb, double aa = 1)
+		: r(rr), g(gg), b(bb), a(aa)
+		{}
+	double r,g,b,a;
+};
+
+//! A Color field
+typedef std::vector<RGBA> ColorVector;
+
+#ifndef QWT3D_NOT_FOR_DOXYGEN
+
+QWT3D_EXPORT QColor GL2Qt(GLdouble r, GLdouble g, GLdouble b); //!< RGB -> QColor
+QWT3D_EXPORT Qwt3D::RGBA Qt2GL(QColor col); //!< QColor -> RGBA
+
+typedef double *Vertex;
+typedef std::vector<Vertex> DataRow;
+typedef std::vector<DataRow> DataMatrix;
+
+
+class Data
+{
+public:
+  Qwt3D::DATATYPE datatype;
+  Data() {datatype= Qwt3D::POLYGON;}
+  virtual ~Data() {}
+  virtual void clear() = 0; //!< destroy content
+  virtual bool empty() const = 0; //!< no data
+  void setHull(Qwt3D::ParallelEpiped const& h) {hull_p = h;}
+  Qwt3D::ParallelEpiped const& hull() const {return hull_p;} 
+
+protected:
+  Qwt3D::ParallelEpiped hull_p;
+};
+
+
+//! Implements a matrix of z-Values with limit access functions 
+class GridData : public Data
+{
+public:
+  GridData();
+	GridData(unsigned int columns, unsigned int rows);//!< see setSize()
+  ~GridData() { clear();}
+
+	int columns() const;
+	int rows() const;
+
+	void clear(); //!< destroy content
+	bool empty() const { return vertices.empty();}
+	void setSize(unsigned int columns, unsigned int rows); //!< destroys content and set new size, elements are uninitialized
+	
+	DataMatrix vertices;		//!< mesh vertices
+	DataMatrix normals;		//!< mesh normals
+  void setPeriodic(bool u, bool v) {uperiodic_ = u; vperiodic_ = v;}
+  bool uperiodic() const {return uperiodic_;} 
+  bool vperiodic() const {return vperiodic_;} 
+
+private:
+  bool uperiodic_, vperiodic_;
+};
+
+
+//! Implements a graph-like cell structure with limit access functions 
+class CellData : public Data
+{
+public:
+  CellData() {datatype=Qwt3D::POLYGON;}
+  ~CellData() { clear();}
+
+	void clear(); //!< destroy content
+	bool empty() const { return cells.empty();}
+	
+	Triple const& operator()(unsigned cellnumber, unsigned vertexnumber);
+	
+	CellField cells;   //!< polygon/cell mesh 
+	TripleField    nodes;
+	TripleField    normals; //!< mesh normals
+};
+
+inline Triple normalizedcross(Triple const& u, Triple const& v)
+{
+	Triple n;
+
+  /* compute the cross product (u x v for right-handed [ccw]) */
+  n.x = u.y * v.z - u.z * v.y;
+  n.y = u.z * v.x - u.x * v.z;
+  n.z = u.x * v.y - u.y * v.x;
+
+  /* normalize */
+  double l = n.length();
+  if (l)
+	{
+		n /= l;
+	}
+	else
+	{
+		n = Triple(0,0,0);
+	}
+	
+	return n;
+}
+
+inline double dotProduct(Triple const& u, Triple const& v)
+{
+	return u.x*v.x + u.y*v.y + u.z*v.z;
+}
+
+void convexhull2d( std::vector<unsigned>& idx, const std::vector<Qwt3D::Tuple>& src );
+
+
+#endif // QWT3D_NOT_FOR_DOXYGEN 
+
+} // ns
+
+#endif
diff --git a/include/qwt3d_volumeplot.h b/include/qwt3d_volumeplot.h
new file mode 100644
index 0000000..45181ea
--- /dev/null
+++ b/include/qwt3d_volumeplot.h
@@ -0,0 +1,24 @@
+#ifndef qwt3d_volumeplot_h__2004_03_06_01_52_begin_guarded_code
+#define qwt3d_volumeplot_h__2004_03_06_01_52_begin_guarded_code
+
+#include "qwt3d_plot.h"
+
+namespace Qwt3D
+{
+
+//! TODO
+class QWT3D_EXPORT VolumePlot : public Plot3D
+{
+//    Q_OBJECT
+
+public:
+  VolumePlot( QWidget* parent = 0, const char* name = 0 ){}
+
+protected:
+	virtual void createData() = 0;
+};
+
+} // ns
+
+
+#endif
diff --git a/lingua_de.ts b/lingua_de.ts
new file mode 100644
index 0000000..7dadd45
--- /dev/null
+++ b/lingua_de.ts
@@ -0,0 +1,10 @@
+<!DOCTYPE TS><TS>
+<context>
+    <name>NativeReader</name>
+    <message>
+        <source>NativeReader::read: cannot open data file "%s"
+</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+</TS>
diff --git a/qwtplot3d.pro b/qwtplot3d.pro
new file mode 100644
index 0000000..0bb45d5
--- /dev/null
+++ b/qwtplot3d.pro
@@ -0,0 +1,95 @@
+# pro file for building the makefile for qwtplot3d
+#
+
+TARGET            = qwtplot3d
+TEMPLATE          = lib
+CONFIG           += qt warn_on opengl thread zlib debug
+MOC_DIR           = tmp
+OBJECTS_DIR       = tmp
+INCLUDEPATH       = include
+DEPENDPATH        = include src
+DESTDIR      			= lib
+#DESTDIR      			= ../../../lib
+QT += opengl
+
+win32:TEMPLATE    = vclib
+win32:CONFIG     += dll exceptions
+win32:dll:DEFINES    += QT_DLL QWT3D_DLL QWT3D_MAKEDLL
+win32:QMAKE_CXXFLAGS     += $$QMAKE_CFLAGS_STL
+
+# Comment the next line, if you have zlib on your windows system
+win32:CONFIG -= zlib
+
+linux-g++:TMAKE_CXXFLAGS += -fno-exceptions
+unix:VERSION = 0.2.7
+
+# Input
+SOURCES += src/qwt3d_axis.cpp \
+           src/qwt3d_color.cpp \
+           src/qwt3d_coordsys.cpp \
+           src/qwt3d_drawable.cpp \
+           src/qwt3d_mousekeyboard.cpp \
+           src/qwt3d_movements.cpp \
+           src/qwt3d_lighting.cpp \
+           src/qwt3d_colorlegend.cpp \
+           src/qwt3d_plot.cpp \
+           src/qwt3d_label.cpp \
+           src/qwt3d_types.cpp \
+           src/qwt3d_enrichment_std.cpp \
+           src/qwt3d_autoscaler.cpp \
+           src/qwt3d_io_reader.cpp \
+           src/qwt3d_io.cpp \
+           src/qwt3d_scale.cpp
+
+SOURCES += src/qwt3d_gridmapping.cpp \
+					 src/qwt3d_parametricsurface.cpp \
+           src/qwt3d_function.cpp
+
+SOURCES += src/qwt3d_surfaceplot.cpp \
+           src/qwt3d_gridplot.cpp \
+           src/qwt3d_meshplot.cpp
+          
+
+HEADERS += include/qwt3d_color.h \
+           include/qwt3d_global.h \
+           include/qwt3d_types.h \
+	         include/qwt3d_axis.h \
+           include/qwt3d_coordsys.h \
+           include/qwt3d_drawable.h \
+           include/qwt3d_helper.h \
+           include/qwt3d_label.h \
+           include/qwt3d_openglhelper.h \
+           include/qwt3d_colorlegend.h \
+           include/qwt3d_plot.h \
+           include/qwt3d_enrichment.h \
+           include/qwt3d_enrichment_std.h \
+           include/qwt3d_autoscaler.h \
+           include/qwt3d_autoptr.h \
+           include/qwt3d_io.h \
+           include/qwt3d_io_reader.h \
+           include/qwt3d_scale.h \
+           include/qwt3d_portability.h
+						
+HEADERS += include/qwt3d_mapping.h \
+					 include/qwt3d_gridmapping.h \
+           include/qwt3d_parametricsurface.h \
+           include/qwt3d_function.h
+
+HEADERS += include/qwt3d_surfaceplot.h \
+           include/qwt3d_volumeplot.h \
+           include/qwt3d_graphplot.h \
+           include/qwt3d_multiplot.h
+
+# gl2ps support
+HEADERS+=3rdparty/gl2ps/gl2ps.h \
+         include/qwt3d_io_gl2ps.h
+         
+SOURCES+=src/qwt3d_io_gl2ps.cpp \
+         3rdparty/gl2ps/gl2ps.c
+
+# zlib support for gl2ps
+zlib {
+  DEFINES += GL2PS_HAVE_ZLIB
+  win32:LIBS += zlib.lib
+	unix:LIBS  += -lz
+}
\ No newline at end of file
diff --git a/scripts/fixvc7.py b/scripts/fixvc7.py
new file mode 100644
index 0000000..b38c61e
--- /dev/null
+++ b/scripts/fixvc7.py
@@ -0,0 +1,16 @@
+sourcedir = 'V:\\\\cvs\\qwtplot3d\\'
+stext=""$(QTDIR)"\\bin\\"
+rtext="$(QTDIR)\\bin\\"
+
+import os, string, sys
+from os.path import join, getsize
+for root, dirs, files in os.walk(sourcedir):
+    for name in files:
+        if '.vcproj' in name:
+            f = file(join(root,name),'r')
+            s = f.read()
+            f.close()
+            ss = string.replace(s,stext,rtext)
+            f = file(join(root,name),'w+')
+            f.write(ss);
+            f.close();
diff --git a/scripts/makedistro.py b/scripts/makedistro.py
new file mode 100644
index 0000000..759d9fc
--- /dev/null
+++ b/scripts/makedistro.py
@@ -0,0 +1,67 @@
+import os.path
+import shutil
+import tarfile
+import zlib
+import zipfile
+from time import gmtime, strftime
+
+refuseddirs = ['CVS','Debug','Release','moc','obj','tmp','data','hannes','doc','lib','bin']
+refusedfiles = ['Makefile','.cvsignore','gl2psTest.c','gl2ps.bat','gl2ps.pro']
+requiredfiles = ['qwtplot3d.dsw','examples.dsw','qwtplot3d.sln','examples.sln','thesis.tex','valgr.sh','qwtplot3d.supp','install.nsi']
+requiredfiletypes = ['pro','bat','cpp','c','h','ui','ts','png','rc','ico','py','qrc']
+srcfiletypes = ['cpp','c','h']
+
+source = 'V:\\\\cvs\\porting24\\qwtplot3d\\'
+
+#tstr = strftime("%y%m%d", gmtime())
+#tarname = 'V:\\\\cvs\\uploads\\' + tstr + 'plot3d.tgz'
+#zipname = 'V:\\\\cvs\\uploads\\' + tstr + 'plot3d.zip'
+
+refuseddirs.append('scripts')
+tarname = 'V:\\\\cvs\\uploads\\qwtplot3d-0.2.6.tgz'
+zipname = 'V:\\\\cvs\\uploads\\qwtplot3d-0.2.6.zip'
+
+
+
+def dos2unix(filename):
+    if os.path.isdir(filename):
+        print filename, "Directory!"
+        return
+    data = open(filename, "rb").read()
+    if '\0' in data:
+        print filename, "Binary!"
+        return
+    newdata = data.replace("\r\n", "\n")
+    if newdata != data:
+        print filename
+        f = open(filename, "wb")
+        f.write(newdata)
+        f.close()
+    
+
+def compresstree(src, tar, zip):
+    names = os.listdir(src)
+   
+    for name in names:
+        srcname = os.path.join(src, name)
+        if os.path.isdir(srcname):
+            if name not in refuseddirs:
+                compresstree(srcname,tar, zip)
+        else:
+            (base,ext) = os.path.splitext(name)
+            ext2 = ext[1:]
+            if ((ext2 in requiredfiletypes) and (name not in refusedfiles)) or (name in requiredfiles):
+                zip.write(srcname, 'qwtplot3d/' + srcname[len(source):])
+                if (ext2 in srcfiletypes):
+                    dos2unix(srcname)
+                tar.add(srcname, 'qwtplot3d/' + srcname[len(source):])
+                
+
+if os.path.exists(tarname):
+   os.remove(tarname)
+
+tar = tarfile.open(tarname, "w:gz")
+zip = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
+compresstree(source,tar, zip)
+tar.close()
+zip.close()
diff --git a/scripts/makedocu.py b/scripts/makedocu.py
new file mode 100644
index 0000000..47923df
--- /dev/null
+++ b/scripts/makedocu.py
@@ -0,0 +1,36 @@
+import os.path
+import shutil
+import tarfile
+import zlib
+import zipfile
+from time import gmtime, strftime
+
+refuseddirs = ['CVS','images']
+refuseddirsextra = ['CVS','small']
+
+source = 'V:\\\\cvs\\porting24\\qwtplot3d\\doc\\'
+sourceim = 'V:\\\\cvs\\porting24\\qwtplot3d\\doc\\images\\'
+zipname = 'V:\\\\cvs\\uploads\\qwtplot3d-doc.zip'
+zipextraname = 'V:\\\\cvs\\uploads\\qwtplot3d-doc-extra.zip'
+
+def compresstree(src, zip, refdir):
+    names = os.listdir(src)
+   
+    for name in names:
+        srcname = os.path.join(src, name)
+        if os.path.isdir(srcname):
+            if name not in refdir:
+                compresstree(srcname, zip, refdir)
+            if name == 'images':    
+                compresstree(srcname +'\\small', zip, refdir)
+        else:
+            zip.write(srcname,'qwtplot3d\\doc\\' +  srcname[len(source):])
+                
+
+
+zip = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED)
+compresstree(source, zip, refuseddirs)
+zip.close()
+zip = zipfile.ZipFile(zipextraname, 'w', zipfile.ZIP_DEFLATED)
+compresstree(sourceim, zip, refuseddirsextra)
+zip.close()
diff --git a/scripts/qwtplot3d.supp b/scripts/qwtplot3d.supp
new file mode 100644
index 0000000..9eb3024
--- /dev/null
+++ b/scripts/qwtplot3d.supp
@@ -0,0 +1,17 @@
+{
+  nvidia_suppression
+  Addrcheck,Memcheck:Param
+  ioctl(generic)
+  obj:/lib/libc-2.3.2.so
+  fun:NvRm* 
+}
+{
+  nvidia_suppression_2
+  Addrcheck,Memcheck:Cond
+  fun:__nvsym* 
+}
+{
+  nvidia_suppression_3
+  Addrcheck,Memcheck:Cond
+  obj:/usr/lib/opengl/nvidia/lib/libGL*
+}
\ No newline at end of file
diff --git a/scripts/valgr.sh b/scripts/valgr.sh
new file mode 100644
index 0000000..6c3090a
--- /dev/null
+++ b/scripts/valgr.sh
@@ -0,0 +1 @@
+valgrind --logfile=valog --suppressions=qwtplot3d.supp --error-limit=no $1
\ No newline at end of file
diff --git a/src/qwt3d_autoscaler.cpp b/src/qwt3d_autoscaler.cpp
new file mode 100644
index 0000000..29d6758
--- /dev/null
+++ b/src/qwt3d_autoscaler.cpp
@@ -0,0 +1,253 @@
+#include "qwt3d_helper.h" 
+#include "qwt3d_autoscaler.h" 
+
+using namespace Qwt3D;
+
+namespace
+{
+
+double floorExt( int& exponent, double x, std::vector<double>& sortedmantissi)
+{
+    if (x == 0.0) 
+    {
+			exponent = 0;
+			return 0.0;
+		}
+    
+    double sign = (x > 0) ? 1.0 : -1.0;
+    double lx = log10(fabs(x));
+    exponent = (int)floor(lx);
+
+    double fr = pow(10.0, lx - exponent);
+    if (fr >= 10.0)
+		{
+			fr = 1.0;
+			++exponent;
+    }
+		else
+    {
+      for (int i=(int)sortedmantissi.size()-1; i>=0;--i)
+      {
+        if (fr>=sortedmantissi[i])
+        {   
+          fr = sortedmantissi[i];
+          break;
+        }
+      }
+    }
+    return sign * fr;
+} 
+
+/*
+  \brief Find the largest value out of {1,2,5}*10^n with an integer number n
+  which is smaller than or equal to x
+  \param exponent n
+  \param x Input value
+  \return Mantissa
+*/
+double floor125( int& exponent, double x)
+{
+  std::vector<double> m(2);
+  m[0] = 1;
+  m[1] = 2;
+  m[2] = 5;
+  return floorExt(exponent, x, m);
+}
+
+} // anon ns
+
+
+//! Initializes with an {1,2,5} sequence of mantissas
+LinearAutoScaler::LinearAutoScaler()
+{
+  init(0,1,1);
+  mantissi_ = std::vector<double>(3);
+  mantissi_[0] = 1;
+  mantissi_[1] = 2;
+  mantissi_[2] = 5;
+}
+//! Initialize with interval [0,1] and one requested interval 
+/*!
+val mantisse A increasing ordered vector of values representing 
+mantisse values between 1 and 9. 
+*/
+LinearAutoScaler::LinearAutoScaler(std::vector<double>& mantisse)
+{
+  init(0,1,1);
+  if (mantisse.empty())
+  {
+    mantissi_ = std::vector<double>(3);
+    mantissi_[0] = 1;
+    mantissi_[1] = 2;
+    mantissi_[2] = 5;
+    return;
+  }
+  mantissi_ = mantisse;
+}
+
+
+//! Initialize with interval [start,stop] and number of requested intervals
+/**
+	Switchs start and stop, if stop < start and sets intervals = 1 if ivals < 1
+*/
+void LinearAutoScaler::init(double start, double stop, int ivals)
+{
+	start_ = start;
+	stop_ = stop;
+	intervals_ = ivals;
+
+	if (start_ > stop_)
+	{
+		double tmp = start_;
+		start_ = stop_;
+		stop_ = tmp;
+	}
+	if (intervals_ < 1)
+		intervals_ = 1;
+}
+
+/*!
+\return Anchor value
+
+\verbatim
+|_______|____________ _ _ _ _  _____|_____________|________________
+
+0     m*10^n                      start         anchor := c*m*10^n	     
+	 
+c 'minimal' (anchor-start < m*10^n)
+\endverbatim
+*/
+double LinearAutoScaler::anchorvalue(double start, double m, int n)
+{
+	double stepval = m * pow(10.0, n);
+	return  stepval * ceil(start / stepval);
+}
+
+/*!
+\return New number of intervals (:= l_intervals + r_intervals)
+\param l_intervals  Number of intervals left from anchor
+\param r_intervals  Number of intervals right from anchor
+
+\verbatim
+                          -l_intervals * i    -2 * i    -i                 +r_intervals * i
+                                                                                   |
+|______|_______ _ _ _ ____|____|___ _ _ _ _ _ _ _|_______|_______|_ _ _ _ _ _ _____|__|_____
+       |                  |                                      |                    | 
+0   i := m*10^n         start                                  anchor	              stop
+	 
+c 'minimal' (anchor-start < m*10^n)
+\endverbatim
+*/
+int LinearAutoScaler::segments(int& l_intervals, int& r_intervals, double start, double stop, double anchor, double m, int n)
+{
+	double val =  m * pow(10.0, n);
+	double delta = (stop - anchor) / val;
+	
+	r_intervals = (int)floor(delta); // right side intervals
+	
+	delta = (anchor - start) / val;
+
+	l_intervals = (int)floor(delta); // left side intervals
+
+	return r_intervals + l_intervals; 
+}
+
+
+/*!
+	\brief Does the actual scaling
+	\return Number of intervals after rescaling. This will in the most cases differ 
+	from the requested interval number!  Always >0.
+	\param a Start value after scaling (always >= start)
+	\param b Stop value after scaling  (always <= stop)
+  \param start Start value
+  \param stop Stop value
+  \param ivals Requested intervals
+  \return Number of intervals after autoscaling
+
+	If the given interval has zero length the function returns the current 
+	interval number and a and b remain unchanged.
+*/
+int LinearAutoScaler::execute(double& a, double& b, double start, double stop, int ivals)
+{
+  init(start,stop,ivals);
+  
+  double delta = stop_ - start_;
+
+	if (isPracticallyZero(delta))
+		return intervals_;
+
+	double c; 
+	int n;
+
+	c = floorExt(n, delta, mantissi_);
+	
+	int l_ival, r_ival;
+
+	double anchor = anchorvalue(start_, c, n); 
+	int ival = segments(l_ival, r_ival, start_, stop_, anchor, c, n); 
+
+	if (ival >= intervals_)
+	{
+		a = anchor - l_ival * c * pow(10.0,n);
+		b = anchor + r_ival * c * pow(10.0,n);
+		intervals_ = ival;
+		return intervals_;
+	}
+	
+	int prev_ival, prev_l_ival, prev_r_ival;
+	double prev_anchor; 
+	double prev_c;
+	int prev_n;
+
+	while(1)
+	{
+		prev_c = c;
+		prev_n = n;
+		prev_anchor = anchor;
+		prev_ival = ival;
+		prev_l_ival = l_ival;
+		prev_r_ival = r_ival;
+	
+		
+    if (int(c) == 1)
+		{
+			c = mantissi_.back();
+			--n;
+		}
+    else
+    {
+      for (unsigned int i=mantissi_.size()-1; i>0; --i)
+      {
+        if (int(c) == mantissi_[i])
+        {
+          c = mantissi_[i-1];
+          break;
+        }
+      }
+    }
+
+    anchor = anchorvalue(start_, c, n); 
+		ival = segments(l_ival, r_ival, start_, stop_, anchor, c, n); 		
+
+		int prev_diff = intervals_ - prev_ival;
+		int actual_diff = ival - intervals_;
+		
+		if (prev_diff >= 0 && actual_diff >= 0) 
+		{
+			if (prev_diff < actual_diff)
+			{
+				c = prev_c;
+				n = prev_n;
+				anchor = prev_anchor;
+				ival = prev_ival;
+				l_ival = prev_l_ival;
+				r_ival = prev_r_ival;
+			}
+			a = anchor - l_ival * c * pow(10.0,n);
+			b = anchor + r_ival * c * pow(10.0,n);
+			intervals_ = ival;
+			break;
+		}
+	}
+	return intervals_;
+}
diff --git a/src/qwt3d_axis.cpp b/src/qwt3d_axis.cpp
new file mode 100644
index 0000000..7d1b462
--- /dev/null
+++ b/src/qwt3d_axis.cpp
@@ -0,0 +1,386 @@
+#include "qwt3d_axis.h"
+
+using namespace Qwt3D;
+
+Axis::Axis()
+{
+  init();
+};
+
+Axis::~Axis()
+{
+}
+
+Axis::Axis(Triple beg, Triple end)
+{
+ 	init();
+	setPosition(beg,end);
+}
+
+void Axis::init()
+{
+	detachAll();
+
+  scale_ = qwt3d_ptr<Scale>(new LinearScale);
+
+  beg_ = Triple(0.0, 0.0, 0.0);  
+  end_ = beg_;
+	
+	majorintervals_ = 0;
+	minorintervals_ = 0;
+	setMajors(1);	
+	setMinors(1);	
+	setLimits(0,0);
+
+	setTicOrientation(0.0, 0.0, 0.0);
+	setTicLength(0.0, 0.0);
+	setColor(0.0, 0.0, 0.0);
+	setLineWidth(1.0);
+	symtics_ = false;
+	drawNumbers_ = false;
+	drawLabel_ = false;
+
+	drawTics_ = false;
+	autoscale_ = true;
+	markerLabel_.clear();
+	numberfont_ = QFont("Courier",12);
+	setLabelFont(QFont("Courier",14));
+
+  numbercolor_ = RGBA(0,0,0,0);
+
+	setNumberAnchor(Center);
+
+	numbergap_ = 0;
+	labelgap_ = 0;
+}
+
+void Axis::setPosition(const Triple& beg, const Triple& end)
+{
+	beg_ = beg;
+	end_ = end;
+}
+
+void Axis::setMajors(int val)
+{
+	if (val == majorintervals_)
+		return;
+	
+	majorintervals_ = (val<=0) ? 1 : val; // always >= 1
+}
+
+/*!
+\see LogScale::setMinors().
+*/
+void Axis::setMinors(int val)
+{
+	if (val == minorintervals_)
+		return;
+
+	minorintervals_ = (val<=0) ? 1 : val; // always >= 1
+}
+
+void Axis::setTicLength(double majorl, double minorl)
+{
+	lmaj_ = majorl;
+	lmin_ = minorl;
+}
+
+void Axis::setTicOrientation(double tx, double ty, double tz)
+{
+	setTicOrientation(Triple(tx,ty,tz));
+}
+
+void Axis::setTicOrientation(const Triple& val)
+{
+	orientation_ = val;
+	orientation_.normalize();
+}
+
+/**
+\param val thickness for axis base line
+\param majfac relative thickness for axis major tics (majfac*val)
+\param minfac relative thickness for axis minor tics (minfac*val)
+*/
+void Axis::setLineWidth(double val, double majfac, double minfac)
+{
+	lineWidth_ = val;
+	majLineWidth_ = majfac * lineWidth_;
+	minLineWidth_ = minfac * lineWidth_;
+}
+
+void Axis::draw()
+{
+	Drawable::draw();
+
+	saveGLState();
+
+//	GLStateBewarer sb(GL_LINE_SMOOTH, true);
+//	glBlendFunc(GL_ONE, GL_ZERO);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glColor4d(color.r,color.g,color.b,color.a);		
+
+	drawBase();
+	drawTics();
+	drawLabel();	
+
+	restoreGLState();
+}
+
+/**
+Always use AFTER drawNumbers() ! (Needs length of number string)
+*/
+void Axis::drawLabel()
+{
+	if (!drawLabel_)
+		return;
+
+  Triple diff = end() - begin();
+	Triple center = begin() + diff/2;
+	
+	Triple bnumber = biggestNumberString(); 
+//	double fac = 6*(second()-first()).length() / 100;
+	
+	switch (scaleNumberAnchor_) 
+	{
+		case BottomLeft:
+		case TopLeft:
+		case CenterLeft:
+			bnumber.y = 0;
+			break;
+		case BottomRight:
+		case TopRight:
+		case CenterRight:
+			bnumber.x = -bnumber.x;
+			bnumber.y = 0;
+			break;
+		case TopCenter:
+			bnumber.x = 0;
+			bnumber.y = -bnumber.y;
+			break;
+		case BottomCenter:
+			bnumber.x = 0;
+			break;
+		default:
+			break;
+	}
+	
+	Triple pos = ViewPort2World(World2ViewPort(center + ticOrientation() * lmaj_) + bnumber);
+	setLabelPosition(pos, scaleNumberAnchor_);
+
+	label_.adjust(labelgap_);
+	label_.draw();
+}
+
+void Axis::drawBase()
+{
+	setDeviceLineWidth( lineWidth_ );
+	glBegin( GL_LINES );
+		glVertex3d( beg_.x, beg_.y, beg_.z); 
+		glVertex3d( end_.x, end_.y, end_.z);
+	glEnd();
+}	
+
+bool Axis::prepTicCalculation(Triple& startpoint)
+{
+  if (isPracticallyZero(start_, stop_))
+		return false;
+
+	autostart_ = start_;
+	autostop_ = stop_;
+
+ 	if (autoScale()) 
+  {  
+    setMajors(scale_->autoscale(autostart_, autostop_, start_, stop_, majors()));
+    if (isPracticallyZero(autostart_, autostop_))
+		  return false;
+  }
+  
+  scale_->setLimits(start_,stop_);
+  scale_->setMajors(majors());
+  scale_->setMinors(minors());
+  scale_->setMajorLimits(autostart_,autostop_);
+  scale_->calculate();
+
+	Triple normal = (end_ - beg_);
+	//normal.normalize();
+	Triple beg = beg_ + ((autostart_ - start_) / (stop_ - start_)) * normal;
+	Triple end = end_ - ((stop_ - autostop_) / (stop_ - start_))* normal;
+
+	startpoint = end_ - beg_;
+
+	majorpos_.clear();
+	minorpos_.clear();
+
+  return true;
+}
+
+void Axis::recalculateTics()
+{
+  Triple runningpoint;
+  if (false==prepTicCalculation(runningpoint))
+    return;
+
+	unsigned int i;
+	
+	for (i = 0; i != scale_->majors_p.size(); ++i) 
+	{
+		double t = (scale_->majors_p[i] - start_) / (stop_-start_);
+		majorpos_.push_back(beg_ + t * runningpoint);
+	}
+	for (i = 0; i != scale_->minors_p.size(); ++i) 
+	{
+		double t = (scale_->minors_p[i] - start_) / (stop_-start_);
+		minorpos_.push_back(beg_ + t * runningpoint);
+	}
+}
+
+void Axis::drawTics()
+{
+	Triple runningpoint;
+  if (!drawTics_ || false==prepTicCalculation(runningpoint))
+		return;
+  
+	unsigned int i;
+  Triple nadir;
+	
+  markerLabel_.resize(scale_->majors_p.size());
+	setDeviceLineWidth(majLineWidth_);
+	for (i = 0; i != scale_->majors_p.size(); ++i) 
+	{
+		double t = (scale_->majors_p[i] - start_) / (stop_-start_);
+    nadir = beg_ + t * runningpoint;
+    majorpos_.push_back(drawTic(nadir, lmaj_));
+		drawTicLabel(nadir + 1.2 * lmaj_ * orientation_, i);
+  }
+	setDeviceLineWidth(minLineWidth_);
+	for (i = 0; i != scale_->minors_p.size(); ++i) 
+	{
+		double t = (scale_->minors_p[i] - start_) / (stop_-start_);
+		nadir = beg_ + t * runningpoint;
+    minorpos_.push_back(drawTic(nadir, lmin_));
+  }
+}
+
+void Axis::drawTicLabel(Triple pos, int mtic)
+{
+	if (!drawNumbers_ || (mtic < 0))
+		return;
+	
+	markerLabel_[mtic].setFont(numberfont_.family(), numberfont_.pointSize(), numberfont_.weight(), numberfont_.italic());
+	markerLabel_[mtic].setColor(numbercolor_);
+  markerLabel_[mtic].setString(scale_->ticLabel(mtic));	  
+  markerLabel_[mtic].setPosition(pos, scaleNumberAnchor_);
+	markerLabel_[mtic].adjust(numbergap_);
+	markerLabel_[mtic].draw();
+}
+
+Triple Axis::drawTic(Triple nadir, double length)
+{
+	double ilength = (symtics_) ? -length : 0.0;
+
+	glBegin( GL_LINES );
+	glVertex3d( nadir.x  + ilength * orientation_.x,
+				      nadir.y  + ilength * orientation_.y,
+							nadir.z  + ilength * orientation_.z) ; 
+	glVertex3d( nadir.x  + length * orientation_.x,
+							nadir.y  + length * orientation_.y,
+							nadir.z  + length * orientation_.z);
+	glEnd();
+	return nadir;
+}
+
+void Axis::setNumberFont(QString const& family, int pointSize, int weight, bool italic)
+{
+	numberfont_ = QFont(family, pointSize, weight, italic );
+}
+
+void Axis::setNumberFont(QFont const& font)
+{
+	numberfont_ = font;
+}
+
+void Axis::setNumberColor(RGBA col)
+{
+	numbercolor_ = col;
+}
+
+void Axis::setLabelFont(QString const& family, int pointSize, int weight, bool italic)
+{
+	labelfont_ = QFont(family, pointSize, weight, italic );
+  label_.setFont(family, pointSize, weight, italic);
+}
+
+void Axis::setLabelFont(QFont const& font)
+{
+	setLabelFont(font.family(), font.pointSize(), font.weight(), font.italic());
+}
+
+void Axis::setLabelString(QString const& name)
+{
+	label_.setString(name);
+}
+
+/*!
+  Sets label position in conjunction with an anchoring strategy
+*/
+void Axis::setLabelPosition(const Triple& pos,Qwt3D::ANCHOR an)
+{
+	label_.setPosition(pos, an);
+}
+
+//! Sets color for label
+void Axis::setLabelColor(RGBA col)
+{
+	label_.setColor(col);
+}
+
+Triple Axis::biggestNumberString()
+{
+	Triple ret;
+	unsigned size = markerLabel_.size();
+
+	double width, height;
+
+	for (unsigned i=0; i!=size; ++i)
+	{
+		width = fabs( (World2ViewPort(markerLabel_[i].second())-World2ViewPort(markerLabel_[i].first())).x );
+		height = fabs( (World2ViewPort(markerLabel_[i].second())-World2ViewPort(markerLabel_[i].first())).y );
+
+		if (width > ret.x)
+			ret.x = width + markerLabel_[i].gap();
+		if (height > ret.y)
+			ret.y = height + markerLabel_[i].gap();;
+	}
+	return ret;
+}
+
+/*! 
+  This variant sets a user-defined scale object.
+  Use with a heap based initialized pointer only.
+  The axis adopts ownership. 
+*/
+void Axis::setScale(Scale* val)
+{
+  scale_ = qwt3d_ptr<Scale>(val); 
+}
+
+/*!
+  Sets one of the predefined scaling types.
+  \warning Too small intervals in logarithmic scales lead to  
+  empty scales (or perhaps a scale only containing an isolated 
+  major tic). Better switch to linear scales in such cases.
+*/
+void Axis::setScale(Qwt3D::SCALETYPE val)
+{
+  switch(val) {
+  case Qwt3D::LINEARSCALE:
+    setScale(new LinearScale);
+  	break;
+  case Qwt3D::LOG10SCALE:
+    setScale(new LogScale);
+    setMinors(9);
+  	break;
+  default:
+    break;
+  }
+}
diff --git a/src/qwt3d_color.cpp b/src/qwt3d_color.cpp
new file mode 100644
index 0000000..6b055a5
--- /dev/null
+++ b/src/qwt3d_color.cpp
@@ -0,0 +1,63 @@
+#include "qwt3d_color.h"
+#include "qwt3d_plot.h"
+
+using namespace Qwt3D;
+
+StandardColor::StandardColor(Plot3D* data, unsigned size)
+			: data_(data)
+{
+	Q_ASSERT(data_);
+	
+	reset(size);
+}
+
+void StandardColor::reset(unsigned size)
+{
+	colors_ = ColorVector(size);
+	RGBA elem;
+
+	double dsize = size;
+	
+	for (unsigned int i=0; i!=size; ++i)
+	{
+		elem.r = i / dsize;
+		elem.g = i / dsize / 4;
+		elem.b = 1 - i/dsize;
+		elem.a = 1.0;
+		colors_[i] = elem;
+	}
+}
+
+/**
+	Assigns a new ColorVector (Also overwrites the constructors size argument)
+*/
+void StandardColor::setColorVector(ColorVector const& cv)
+{
+	colors_ = cv;
+}
+
+void StandardColor::setAlpha(double a)
+{
+	if (a<0 || a>1)
+		return;
+	
+	RGBA elem;
+
+	for (unsigned int i=0; i!=colors_.size(); ++i)
+	{
+		elem = colors_[i];
+		elem.a = a;
+		colors_[i] = elem;
+	}	
+}	
+
+RGBA StandardColor::operator()(double, double, double z) const
+{
+	Q_ASSERT(data_);
+	int index = (int)((colors_.size()-1) * (z - data_->hull().minVertex.z) / (data_->hull().maxVertex.z-data_->hull().minVertex.z));
+	if (index < 0)
+		index = 0;
+	if ((unsigned int)index > colors_.size() - 1)
+		index = (int)(colors_.size() - 1);
+	return colors_[index];
+}
diff --git a/src/qwt3d_colorlegend.cpp b/src/qwt3d_colorlegend.cpp
new file mode 100644
index 0000000..6f84afe
--- /dev/null
+++ b/src/qwt3d_colorlegend.cpp
@@ -0,0 +1,223 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4305 )
+#endif
+
+#include "qwt3d_colorlegend.h"
+
+using namespace Qwt3D;
+
+/**
+Contructs a legend object with an axis at the left
+side. The legend resides in the top-right area 
+and has no caption. Scale numbering is shown.
+*/
+ColorLegend::ColorLegend()
+{
+	axis_.setNumbers(true);
+	axis_.setScaling(true);
+	axis_.setNumberColor(RGBA(0,0,0,1));
+	axis_.setNumberAnchor(CenterRight);
+	axis_.setNumberFont(QFont("Courier",8));
+
+	caption_.setFont("Courier", 10, QFont::Bold);
+	caption_.setColor(RGBA(0,0,0,1));
+	axisposition_ = ColorLegend::Left;
+	orientation_ = ColorLegend::BottomTop;
+	showaxis_ = true;
+	setRelPosition(Tuple(0.94, 1-0.36),Tuple(0.97, 1-0.04));
+}
+
+void ColorLegend::setTitleString(QString const& s) 
+{ 
+	caption_.setString(s); 
+}
+
+void ColorLegend::setTitleFont(QString const& family, int pointSize, int weight, bool italic) 
+{ 
+	caption_.setFont(family, pointSize, weight, italic);
+}
+
+void ColorLegend::setLimits(double start, double stop)
+{
+	axis_.setLimits(start, stop);
+}
+
+void ColorLegend::setMajors(int majors)
+{
+	axis_.setMajors(majors);
+}
+
+void ColorLegend::setMinors(int minors)
+{
+	axis_.setMinors(minors);
+}
+
+void ColorLegend::setAutoScale(bool val)
+{
+	axis_.setAutoScale(val);
+}
+
+void ColorLegend::setScale(SCALETYPE val)
+{
+	axis_.setScale(val);
+}
+
+void ColorLegend::setScale(Scale* val)
+{
+	axis_.setScale(val);
+}
+
+
+void ColorLegend::setOrientation(ORIENTATION orientation, SCALEPOSITION pos)
+{
+	orientation_ = orientation;
+	axisposition_ = pos;
+
+	if (orientation_==BottomTop)
+	{
+		if (axisposition_ == Bottom || axisposition_ == Top)
+			axisposition_ = Left;
+	}
+	else
+	{
+		if (axisposition_ == Left || axisposition_ == Right)
+			axisposition_ = Bottom;
+	}
+}
+
+void ColorLegend::setRelPosition(Tuple relMin, Tuple relMax)
+{
+	relMin_ = relMin;
+	relMax_ = relMax;
+}
+
+void ColorLegend::setGeometryInternal()
+{
+	double ot = .99;
+
+	getMatrices(modelMatrix, projMatrix, viewport);
+	pe_.minVertex = relativePosition(Triple(relMin_.x, relMin_.y, ot));
+	pe_.maxVertex = relativePosition(Triple(relMax_.x, relMax_.y, ot));
+
+	double diff = 0;
+	Triple b;
+	Triple e;
+
+	switch (axisposition_) 
+	{
+	case ColorLegend::Left:
+		b = pe_.minVertex;
+		e = pe_.maxVertex; e.x = b.x;
+		axis_.setTicOrientation(-1,0,0);
+		axis_.setNumberAnchor(CenterRight);
+		diff = pe_.maxVertex.x - pe_.minVertex.x;
+		break;
+	case ColorLegend::Right:
+		e = pe_.maxVertex;
+		b = pe_.minVertex; b.x = e.x; 
+		axis_.setTicOrientation(+1,0,0);
+		axis_.setNumberAnchor(CenterLeft);
+		diff = pe_.maxVertex.x - pe_.minVertex.x;
+		break;
+	case ColorLegend::Top:
+		e = pe_.maxVertex;
+		b = pe_.minVertex; b.z = e.z; 
+		axis_.setTicOrientation(0,0,+1);
+		axis_.setNumberAnchor(BottomCenter);
+		diff = pe_.maxVertex.z - pe_.minVertex.z;
+		break;
+	case ColorLegend::Bottom:
+		b = pe_.minVertex;
+		e = pe_.maxVertex; e.z = b.z;
+		axis_.setTicOrientation(0,0,-1);
+		axis_.setNumberAnchor(TopCenter);
+		diff = pe_.maxVertex.z - pe_.minVertex.z;
+		break;
+	default:
+		break;
+	}
+	
+	axis_.setPosition(b,e);
+	diff /= 10;
+	
+	axis_.setTicLength(diff, 0.6*diff);
+
+	Triple c;
+	c.x = pe_.minVertex.x + ((pe_.maxVertex-pe_.minVertex) / 2).x;
+	c.z = pe_.maxVertex.z;
+	c.z += (pe_.maxVertex.z-pe_.minVertex.z)/20;
+	c.y = pe_.maxVertex.y;
+
+	caption_.setPosition(c, BottomCenter);	
+}
+
+void ColorLegend::draw()
+{
+	if (colors.empty())
+		return;
+
+	setGeometryInternal();
+
+	saveGLState();
+  	
+	Triple one = pe_.minVertex;
+	Triple two = pe_.maxVertex; 
+	
+	double h = (orientation_ == ColorLegend::BottomTop)
+	         ? (two-one).z / colors.size()
+					 : (two-one).x / colors.size(); 
+
+	//glEnable(GL_DEPTH_TEST);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+	GLStateBewarer(GL_POLYGON_OFFSET_FILL,true);
+//	glPolygonOffset(0.0, 0.0);
+
+	glColor4d(0, 0, 0, 1);
+	glBegin(GL_LINE_LOOP);
+		glVertex3d(one.x, one.y, one.z);
+		glVertex3d(one.x, one.y, two.z);
+		glVertex3d(two.x, one.y, two.z);
+		glVertex3d(two.x, one.y, one.z);
+	glEnd();
+
+
+	unsigned size = colors.size();
+	RGBA rgb;
+	
+	if (orientation_ == ColorLegend::BottomTop)
+	{
+		for (unsigned i=1; i<=size; ++i) 
+		{
+			rgb = colors[i-1];
+			glColor4d(rgb.r,rgb.g,rgb.b,rgb.a);
+	 		glBegin( GL_POLYGON );
+				glVertex3d( one.x, one.y, one.z+(i-1)*h );
+				glVertex3d( one.x, one.y, one.z+i*h );
+				glVertex3d( two.x, one.y, one.z+i*h );
+				glVertex3d( two.x, one.y, one.z+(i-1)*h );
+			glEnd();
+		}
+	}
+	else
+	{
+		for (unsigned i=1; i<=size; ++i) 
+		{
+			rgb = colors[i-1];
+			glColor4d(rgb.r,rgb.g,rgb.b,rgb.a);
+	 		glBegin( GL_POLYGON );
+				glVertex3d( one.x+(i-1)*h, one.y, one.z );
+				glVertex3d( one.x+i*h, one.y, one.z );
+				glVertex3d( one.x+i*h, one.y, two.z );
+				glVertex3d( one.x+(i-1)*h, one.y, two.z );
+			glEnd();
+		}
+	}
+			
+	restoreGLState();
+	
+	if (showaxis_)
+		axis_.draw();
+	
+	caption_.draw();
+}
diff --git a/src/qwt3d_coordsys.cpp b/src/qwt3d_coordsys.cpp
new file mode 100644
index 0000000..c7c7047
--- /dev/null
+++ b/src/qwt3d_coordsys.cpp
@@ -0,0 +1,633 @@
+#include "qwt3d_coordsys.h"
+
+using namespace std;
+using namespace Qwt3D;
+
+
+CoordinateSystem::CoordinateSystem(Triple first, Triple second, COORDSTYLE st)
+{
+	autodecoration_ = true;
+	axes = std::vector<Axis>(12);
+  setStyle(st);
+	setLineSmooth(true);
+	init(first,second);
+
+	setAxesColor(RGBA(0,0,0,1));
+	setGridLinesColor(RGBA(0.2,0.2,0.2,1));
+	setNumberFont("Courier", 12);
+	setNumberColor(RGBA(0,0,0));
+	setLabelFont("Courier", 14, QFont::Bold);
+	setGridLines(false, false);
+}
+
+CoordinateSystem::~CoordinateSystem()
+{
+	destroy();
+}
+
+void CoordinateSystem::destroy()
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].setLabelString("");
+
+	detachAll();
+}
+
+void CoordinateSystem::init(Triple first, Triple second)
+{
+	destroy();
+	
+  for (unsigned i=0; i!=axes.size(); ++i)
+    axes[i].setScale(LINEARSCALE);
+		
+	Triple dv = second - first;
+	
+	setPosition(first, second);
+	
+	double majl =  dv.length() / 100; // 1 %
+	setTicLength(majl, 0.6 * majl);
+
+	axes[X1].setPosition(first, first+Triple(dv.x,    0,     0));												// front bottom x
+	axes[Y1].setPosition(first, first+Triple(   0, dv.y,     0));												// bottom left  y
+	axes[Z1].setPosition (first+Triple(   0, dv.y, 0), first+Triple(   0, dv.y, dv.z));	// back left z
+	axes[X1].setTicOrientation(0,-1,0);
+	axes[Y1].setTicOrientation(-1,0,0);
+	axes[Z1].setTicOrientation(-1,0,0);
+	
+	axes[X1].setLimits(first.x, second.x);
+	axes[X2].setLimits(first.x, second.x);
+	axes[X3].setLimits(first.x, second.x);
+	axes[X4].setLimits(first.x, second.x);
+	
+	axes[Y1].setLimits(first.y, second.y);
+	axes[Y2].setLimits(first.y, second.y);
+	axes[Y3].setLimits(first.y, second.y);
+	axes[Y4].setLimits(first.y, second.y);
+	
+	axes[Z1].setLimits(first.z, second.z);
+	axes[Z2].setLimits(first.z, second.z);
+	axes[Z3].setLimits(first.z, second.z);
+	axes[Z4].setLimits(first.z, second.z);
+
+	// remaining x axes 
+	axes[X2].setPosition(first+Triple( 0,    0, dv.z), first+Triple( dv.x,    0, dv.z));	// front top x
+	axes[X3].setPosition(first+Triple( 0, dv.y, dv.z), second);		  											// back top x
+	axes[X4].setPosition(first+Triple( 0, dv.y,    0), first+Triple( dv.x, dv.y,    0));	// back bottom x
+	axes[X2].setTicOrientation(0,-1,0);
+	axes[X3].setTicOrientation(0,1,0);
+	axes[X4].setTicOrientation(0,1,0);
+	
+	// remaining y axes 
+	axes[Y2].setPosition(first+Triple(dv.x, 0,    0), first+Triple(dv.x, dv.y,  0)); // bottom right y
+	axes[Y3].setPosition(first+Triple(dv.x, 0, dv.z), second);											 // top right y
+	axes[Y4].setPosition(first+Triple(0,    0, dv.z), first+Triple(0,  dv.y, dv.z)); // top left y
+	axes[Y2].setTicOrientation(1,0,0);
+	axes[Y3].setTicOrientation(1,0,0);
+	axes[Y4].setTicOrientation (-1,0,0);
+
+	// remaining z axes 
+	axes[Z2].setPosition(first, first+Triple(   0,    0,  dv.z));												// front left z
+	axes[Z4].setPosition(first+Triple(dv.x, dv.y, 0), second );                         // back right z
+	axes[Z3].setPosition(first+Triple(dv.x,    0, 0), first+Triple(dv.x,    0, dv.z));	// front right z
+	axes[Z2].setTicOrientation(-1,0,0);
+	axes[Z4].setTicOrientation(1,0,0);
+	axes[Z3].setTicOrientation(1,0,0);
+	
+	setStyle(style_);
+}
+
+void CoordinateSystem::draw()
+{	
+//	saveGLState();
+	
+	GLStateBewarer sb(GL_LINE_SMOOTH, true);
+	
+	if (!lineSmooth())
+		sb.turnOff();
+		
+
+	if (autoDecoration())
+		chooseAxes();
+	
+	Drawable::draw();
+
+	if( style_ == NOCOORD)
+		return;
+
+  if (majorgridlines_ || minorgridlines_)
+    recalculateAxesTics();
+  if (majorgridlines_)
+    drawMajorGridLines();
+	if (minorgridlines_)
+		drawMinorGridLines();
+	
+	//	restoreGLState();
+}
+
+
+//! build convex hull (6 axes: 2 x, 2 y, 2 z) and choose one of them at a time for scales, labels etc.  
+void CoordinateSystem::chooseAxes()
+{
+	vector<Triple> beg(axes.size());
+	vector<Triple> end(axes.size());
+	vector<Tuple> src(2*axes.size());
+
+	unsigned i;
+	// collect axes viewport coordinates and initialize
+	for (i=0; i!=axes.size(); ++i)
+	{
+		if (style() != NOCOORD)
+			attach(&axes[i]);
+		
+		beg[i] = World2ViewPort(axes[i].begin());
+		end[i] = World2ViewPort(axes[i].end());
+		src[i] = Tuple(beg[i].x, beg[i].y);
+		src[axes.size()+i] = Tuple(end[i].x, end[i].y);
+
+		axes[i].setScaling(false);
+		axes[i].setNumbers(false);
+		axes[i].setLabel(false);
+	}
+
+	vector<unsigned> idx;
+	convexhull2d(idx,src);
+
+	int rem_x = -1;
+	int rem_y = -1;
+	int rem_z = -1;
+
+
+	bool left;
+
+	int choice_x = -1; 
+	int	choice_y = -1;
+	int choice_z = -1;
+
+  int other_x = -1;
+  int other_y = -1;
+  int other_z = -1;
+
+	//traverse convex hull
+	for (unsigned k=0; k!=idx.size(); ++k)
+	{
+		Triple one, two;
+		
+		if (idx[k] >= axes.size()) // is end point
+			one = end[idx[k]-axes.size()];
+		else                       // is begin point  
+			one = beg[idx[k]];
+
+		unsigned int next = idx[(k+1) % idx.size()];  // next point in cv (considered as ring buffer of points)
+
+		if (next >= axes.size()) 
+			two = end[next-axes.size()];
+		else
+			two = beg[next];
+		
+		for (i=0; i!=axes.size(); ++i)
+		{			
+			if (
+					(one == beg[i] && two == end[i])
+					||
+					(two == beg[i] && one == end[i])
+				 )
+			{
+				if (i==X1 || i==X2 || i==X3 || i==X4)  // x Achsen
+				{
+					if (rem_x>=0) // schon zweite Achse der konvexen Huelle ?
+					{
+						// untere der beiden x Achsen
+						double y = min(min(end[rem_x].y,end[i].y),min(beg[rem_x].y,beg[i].y));
+						choice_x = (y == beg[i].y || y == end[i].y) ? i : rem_x;
+												
+						other_x = (choice_x == (int)i) ? rem_x : (int)i;
+						left = (beg[choice_x].x < beg[other_x].x || end[choice_x].x < end[other_x].x) 
+							? true
+							: false;
+						
+						autoDecorateExposedAxis(axes[choice_x], left);
+
+						rem_x = -1;
+					}
+					else
+					{
+						rem_x = i;
+					}
+				}
+				else if (i==Y1 || i==Y2 || i==Y3 || i==Y4)
+				{
+					if (rem_y>=0)
+					{
+						// untere der beiden y Achsen
+						double y = min(min(end[rem_y].y,end[i].y),min(beg[rem_y].y,beg[i].y));
+						choice_y = (y == beg[i].y || y == end[i].y) ? i : rem_y;
+						
+						other_y = (choice_y == (int)i) ? rem_y : (int)i;
+						left = (beg[choice_y].x < beg[other_y].x || end[choice_y].x < end[other_y].x) 
+							? true
+							: false;
+						autoDecorateExposedAxis(axes[choice_y], left);
+
+						rem_y = -1;
+					}
+					else
+					{
+						rem_y = i;
+					}
+				}
+				else if (i==Z1 || i==Z2 || i==Z3 || i==Z4)
+				{
+					if (rem_z>=0)
+					{
+						// hintere der beiden z Achsen
+						double z = max(max(end[rem_z].z,end[i].z),max(beg[rem_z].z,beg[i].z));
+						choice_z = (z == beg[i].z || z == end[i].z) ? i : rem_z;
+
+						other_z = (choice_z == (int)i) ? rem_z : (int)i;
+												
+						rem_z = -1;
+
+					}
+					else
+					{
+						rem_z = i;
+					}
+				}
+			}
+		} // for axes
+	} // for idx
+
+	// fit z axis in - the onthewall axis if the decorated axes build a continous line, the opposite else 
+	if (choice_x>=0 && choice_y>=0 && choice_z>=0)
+	{
+		left = (beg[choice_z].x < beg[other_z].x || end[choice_z].x < end[other_z].x) 
+			? true
+			: false;
+		
+
+		if (
+					axes[choice_z].begin() == axes[choice_x].begin() 
+			||	axes[choice_z].begin() == axes[choice_x].end()
+			||	axes[choice_z].begin() == axes[choice_y].begin() 
+			||	axes[choice_z].begin() == axes[choice_y].end()
+			||	axes[choice_z].end() == axes[choice_x].begin() 
+			||	axes[choice_z].end() == axes[choice_x].end()
+			||	axes[choice_z].end() == axes[choice_y].begin() 
+			||	axes[choice_z].end() == axes[choice_y].end()
+			
+			)
+		{
+			autoDecorateExposedAxis(axes[choice_z], left);
+		}
+
+		else
+		{
+			autoDecorateExposedAxis(axes[other_z], !left);
+			choice_z = other_z; // for FRAME
+		}
+	}
+	
+	if (style() == FRAME)
+	{
+		for (i=0; i!=axes.size(); ++i)
+		{
+			if ((int)i!=choice_x && (int)i!=choice_y && (int)i!=choice_z)
+				detach(&axes[i]);
+		}
+	}
+
+}
+
+
+void CoordinateSystem::autoDecorateExposedAxis(Axis& ax, bool left)
+{
+	Triple diff = World2ViewPort(ax.end()) - World2ViewPort(ax.begin());
+
+	diff = Triple(diff.x,diff.y,0); // projection
+	
+	double s = diff.length();
+	
+	if (!s)
+		return;
+
+	ax.setScaling(true);
+	ax.setNumbers(true);
+	ax.setLabel(true);
+
+	const double SQRT_2 = 0.7071067;
+	double sina = fabs(diff.y / s);
+
+
+	if (left) // leftmost (compared with antagonist in CV)  axis -> draw decorations on the left side
+	{
+		if ( diff.x >= 0 && diff.y >= 0 && sina < SQRT_2)          // 0..Pi/4 
+		{
+			ax.setNumberAnchor(BottomCenter);
+		}
+		else if ( diff.x >= 0 && diff.y >= 0  && !left)            // octant 2
+		{
+			ax.setNumberAnchor(CenterRight);
+		}
+		else if ( diff.x <= 0 && diff.y >= 0  && sina >= SQRT_2)    // octant 3
+		{
+			ax.setNumberAnchor(CenterRight);
+		}
+		else if ( diff.x <= 0 && diff.y >= 0 )                      // octant 4
+		{
+			ax.setNumberAnchor(TopCenter);
+		}
+		else if ( diff.x <= 0 && diff.y <= 0  && sina <= SQRT_2)    // octant 5
+		{
+			ax.setNumberAnchor(BottomCenter);
+		}
+		else if ( diff.x <= 0 && diff.y <= 0)                      // octant 6
+		{
+			ax.setNumberAnchor(CenterRight);
+		}
+		else if ( diff.x >= 0 && diff.y <= 0  && sina >= SQRT_2)    // octant 7
+		{
+			ax.setNumberAnchor(CenterRight);
+		}
+		else if ( diff.x >= 0 && diff.y <= 0)                      // octant 8
+		{
+			ax.setNumberAnchor(TopCenter);
+		}
+	}	
+	else // rightmost axis
+	{
+		if ( diff.x >= 0 && diff.y >= 0 && sina <= SQRT_2)
+		{
+			ax.setNumberAnchor(TopCenter);
+		}
+		else if ( diff.x >= 0 && diff.y >= 0  && !left) 
+		{
+			ax.setNumberAnchor(CenterLeft);
+		}
+		else if ( diff.x <= 0 && diff.y >= 0  && sina >= SQRT_2) 
+		{
+			ax.setNumberAnchor(CenterLeft);
+		}
+		else if ( diff.x <= 0 && diff.y >= 0) 
+		{
+			ax.setNumberAnchor(BottomCenter);
+		}
+		else if ( diff.x <= 0 && diff.y <= 0  && sina <= SQRT_2) 
+		{
+			ax.setNumberAnchor(TopCenter);
+		}
+		else if ( diff.x <= 0 && diff.y <= 0) 
+		{
+			ax.setNumberAnchor(CenterLeft);
+		}
+		else if ( diff.x >= 0 && diff.y <= 0  && sina >= SQRT_2) 
+		{
+			ax.setNumberAnchor(CenterLeft);
+		}
+		else if ( diff.x >= 0 && diff.y <= 0) 
+		{
+			ax.setNumberAnchor(BottomCenter);
+		}
+	}
+}
+
+
+void CoordinateSystem::setPosition(Triple first, Triple second)
+{
+	first_ = first;
+	second_ = second;
+}
+
+void CoordinateSystem::setTicLength(double major, double minor)
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].setTicLength(major, minor);
+}
+
+void CoordinateSystem::adjustNumbers(int val)
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].adjustNumbers(val);
+}
+
+void CoordinateSystem::adjustLabels(int val)
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].adjustLabel(val);
+}
+
+void CoordinateSystem::setAutoScale(bool val)
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].setAutoScale(val);
+}
+
+void CoordinateSystem::setAxesColor(RGBA val)
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].setColor(val);
+}
+
+void CoordinateSystem::recalculateAxesTics()
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].recalculateTics();
+}
+
+void CoordinateSystem::setNumberFont(QString const& family, int pointSize, int weight, bool italic)
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].setNumberFont(family,pointSize,weight,italic);
+}
+
+void CoordinateSystem::setNumberFont(QFont const& font)
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].setNumberFont(font);
+}
+
+void CoordinateSystem::setNumberColor(RGBA val)
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].setNumberColor( val);
+}
+
+void CoordinateSystem::setStandardScale()
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+    axes[i].setScale(LINEARSCALE);
+}
+
+void CoordinateSystem::setLabelFont(QFont const& font)
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].setLabelFont(font);
+}
+
+
+void CoordinateSystem::setLabelFont(QString const& family, int pointSize, int weight, bool italic)
+{
+	setLabelFont(QFont(family,pointSize,weight,italic));
+}
+
+void CoordinateSystem::setLabelColor(RGBA val)
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].setLabelColor(val);
+}
+
+void CoordinateSystem::setLineWidth(double val, double majfac, double minfac)
+{
+	for (unsigned i=0; i!=axes.size(); ++i)
+		axes[i].setLineWidth(val, majfac, minfac);
+}
+
+void CoordinateSystem::setStyle(COORDSTYLE s, AXIS frame_1, AXIS frame_2, AXIS frame_3) 
+{ 
+	style_ = s;
+
+	switch (s)
+	{
+		case NOCOORD:
+			{
+				for (unsigned i=0; i!=axes.size(); ++i)
+					detach (&axes[i]);
+			}
+			break;
+		case BOX:
+			{
+				for (unsigned i=0; i!=axes.size(); ++i)
+					attach (&axes[i]);
+			}
+			break;
+		case FRAME:
+			{
+				for (unsigned i=0; i!=axes.size(); ++i)
+					detach (&axes[i]);
+				if (!autoDecoration())
+				{
+					attach(&axes[frame_1]);
+					attach(&axes[frame_2]);
+					attach(&axes[frame_3]);
+				}
+			}
+			break;
+		default:
+			break;
+	}
+}
+
+/**
+The axis used for tic calculation is chosen randomly from the respective pair.
+For most cases an identical tic distribution is therefore recommended.
+\param majors  Draw grid between major tics
+\param minors  Draw grid between minor tics
+\param sides   Side(s), where the grid should be drawn
+*/
+void CoordinateSystem::setGridLines(bool majors, bool minors, int sides) 
+{
+	sides_ = sides;
+  majorgridlines_ = majors; 
+	minorgridlines_ = minors;
+} 
+
+void CoordinateSystem::drawMajorGridLines()
+{
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glColor4d(gridlinecolor_.r,gridlinecolor_.g,gridlinecolor_.b,gridlinecolor_.a);		
+	setDeviceLineWidth(axes[X1].majLineWidth());
+
+  glBegin( GL_LINES );
+  if (sides_ & Qwt3D::FLOOR)  
+  {
+		drawMajorGridLines(axes[X1],axes[X4]);
+		drawMajorGridLines(axes[Y1],axes[Y2]);
+  }
+  if (sides_ & Qwt3D::CEIL)  
+  {
+		drawMajorGridLines(axes[X2],axes[X3]);
+		drawMajorGridLines(axes[Y3],axes[Y4]);
+  }
+  if (sides_ & Qwt3D::LEFT)  
+  {
+		drawMajorGridLines(axes[Y1],axes[Y4]);
+		drawMajorGridLines(axes[Z1],axes[Z2]);
+  }
+  if (sides_ & Qwt3D::RIGHT)  
+  {
+		drawMajorGridLines(axes[Y2],axes[Y3]);
+		drawMajorGridLines(axes[Z3],axes[Z4]);
+  }
+  if (sides_ & Qwt3D::FRONT)  
+  {
+		drawMajorGridLines(axes[X1],axes[X2]);
+		drawMajorGridLines(axes[Z2],axes[Z3]);
+  }
+  if (sides_ & Qwt3D::BACK) 
+  {
+		drawMajorGridLines(axes[X3],axes[X4]);
+		drawMajorGridLines(axes[Z4],axes[Z1]);
+  }
+  glEnd();
+}
+
+void CoordinateSystem::drawMinorGridLines()
+{
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glColor4d(gridlinecolor_.r,gridlinecolor_.g,gridlinecolor_.b,gridlinecolor_.a);		
+	setDeviceLineWidth(axes[X1].minLineWidth());
+
+  glBegin( GL_LINES );
+  if (sides_ & Qwt3D::FLOOR)  
+  {
+		drawMinorGridLines(axes[X1],axes[X4]);
+		drawMinorGridLines(axes[Y1],axes[Y2]);
+  }
+  if (sides_ & Qwt3D::CEIL)  
+  {
+		drawMinorGridLines(axes[X2],axes[X3]);
+		drawMinorGridLines(axes[Y3],axes[Y4]);
+  }
+  if (sides_ & Qwt3D::LEFT)  
+  {
+		drawMinorGridLines(axes[Y1],axes[Y4]);
+		drawMinorGridLines(axes[Z1],axes[Z2]);
+  }
+  if (sides_ & Qwt3D::RIGHT)  
+  {
+		drawMinorGridLines(axes[Y2],axes[Y3]);
+		drawMinorGridLines(axes[Z3],axes[Z4]);
+  }
+  if (sides_ & Qwt3D::FRONT)  
+  {
+		drawMinorGridLines(axes[X1],axes[X2]);
+		drawMinorGridLines(axes[Z2],axes[Z3]);
+  }
+  if (sides_ & Qwt3D::BACK)  
+  {
+		drawMinorGridLines(axes[X3],axes[X4]);
+		drawMinorGridLines(axes[Z4],axes[Z1]);
+  }
+  glEnd();
+}
+
+void CoordinateSystem::drawMajorGridLines(Axis& a0, Axis& a1)
+{
+  Triple d = a1.begin()-a0.begin();
+
+  for (unsigned int i=0; i!=a0.majorPositions().size(); ++i)
+	{
+		glVertex3d( a0.majorPositions()[i].x, a0.majorPositions()[i].y, a0.majorPositions()[i].z ); 
+		glVertex3d( a0.majorPositions()[i].x + d.x, a0.majorPositions()[i].y + d.y, a0.majorPositions()[i].z +d.z); 
+	}
+}
+
+void CoordinateSystem::drawMinorGridLines(Axis& a0, Axis& a1)
+{
+  Triple d = a1.begin()-a0.begin();
+
+  for (unsigned int i=0; i!=a0.minorPositions().size(); ++i)
+	{
+		glVertex3d( a0.minorPositions()[i].x, a0.minorPositions()[i].y, a0.minorPositions()[i].z ); 
+		glVertex3d( a0.minorPositions()[i].x + d.x, a0.minorPositions()[i].y + d.y, a0.minorPositions()[i].z +d.z); 
+	}
+}
diff --git a/src/qwt3d_dataviews.cpp b/src/qwt3d_dataviews.cpp
new file mode 100644
index 0000000..8e995dc
--- /dev/null
+++ b/src/qwt3d_dataviews.cpp
@@ -0,0 +1,10 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4305 )
+#pragma warning ( disable : 4786 )
+#endif
+
+#include "qwt3d_plot.h"
+
+using namespace std;
+using namespace Qwt3D;
+
diff --git a/src/qwt3d_drawable.cpp b/src/qwt3d_drawable.cpp
new file mode 100644
index 0000000..9705103
--- /dev/null
+++ b/src/qwt3d_drawable.cpp
@@ -0,0 +1,140 @@
+#include "qwt3d_drawable.h"
+
+using namespace Qwt3D;
+
+Drawable::~Drawable()
+{
+  detachAll();
+}
+
+void Drawable::saveGLState()
+{
+	glGetBooleanv(GL_LINE_SMOOTH, &ls);
+	glGetBooleanv(GL_POLYGON_SMOOTH, &pols);
+	glGetFloatv(GL_LINE_WIDTH, &lw);
+	glGetIntegerv(GL_BLEND_SRC, &blsrc);
+	glGetIntegerv(GL_BLEND_DST, &bldst);
+	glGetDoublev(GL_CURRENT_COLOR, col);
+	glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &pattern);
+	glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &factor);
+	glGetBooleanv(GL_LINE_STIPPLE, &sallowed);
+	glGetBooleanv(GL_TEXTURE_2D, &tex2d);
+	glGetIntegerv(GL_POLYGON_MODE, polmode);
+	glGetIntegerv(GL_MATRIX_MODE, &matrixmode);
+	glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &poloffs[0]);
+	glGetFloatv(GL_POLYGON_OFFSET_UNITS, &poloffs[1]);
+	glGetBooleanv(GL_POLYGON_OFFSET_FILL, &poloffsfill);
+}
+
+void Drawable::restoreGLState()
+{
+	Enable(GL_LINE_SMOOTH, ls);
+	Enable(GL_POLYGON_SMOOTH, pols);
+	
+	setDeviceLineWidth(lw);
+	glBlendFunc(blsrc, bldst);
+	glColor4dv(col);
+
+	glLineStipple(factor,pattern);
+	Enable(GL_LINE_STIPPLE,sallowed);
+	Enable(GL_TEXTURE_2D,tex2d);
+	glPolygonMode(polmode[0], polmode[1]);
+	glMatrixMode(matrixmode);
+	glPolygonOffset(poloffs[0], poloffs[1]);
+	setDevicePolygonOffset(poloffs[0], poloffs[1]);
+
+	Enable(GL_POLYGON_OFFSET_FILL, poloffsfill);
+}
+
+void Drawable::Enable(GLenum what, GLboolean val)
+{
+	if (val)
+		glEnable(what);
+  else
+		glDisable(what);
+}
+
+void Drawable::attach(Drawable* dr)
+{
+	if ( dlist.end() == std::find( dlist.begin(), dlist.end(), dr ) )
+		if (dr)
+		{
+			dlist.push_back(dr);
+		}
+}
+
+void Drawable::detach(Drawable* dr)
+{
+	std::list<Drawable*>::iterator it = std::find(dlist.begin(), dlist.end(), dr);
+	
+	if ( it != dlist.end() )
+	{
+		dlist.erase(it);
+	}
+}
+void Drawable::detachAll()
+{
+	dlist.clear();
+}
+
+
+//! simplified glut routine (glUnProject): windows coordinates_p --> object coordinates_p 
+/**
+	Don't rely on (use) this in display lists !
+*/
+Triple Drawable::ViewPort2World(Triple win, bool* err)
+{
+  Triple obj;
+	
+	getMatrices(modelMatrix, projMatrix, viewport);
+	int res = gluUnProject(win.x, win.y, win.z, modelMatrix, projMatrix, viewport, &obj.x, &obj.y, &obj.z);
+
+	if (err)
+		*err = (res) ? false : true;
+	return obj;
+}
+
+//! simplified glut routine (glProject): object coordinates_p --> windows coordinates_p 
+/**
+	Don't rely on (use) this in display lists !
+*/
+Triple Drawable::World2ViewPort(Triple obj,	bool* err)
+{
+  Triple win;
+	
+	getMatrices(modelMatrix, projMatrix, viewport);
+	int res = gluProject(obj.x, obj.y, obj.z, modelMatrix, projMatrix, viewport, &win.x, &win.y, &win.z);
+
+	if (err)
+		*err = (res) ? false : true;
+	return win;
+}
+
+/**
+	Don't rely on (use) this in display lists !
+*/
+Triple Drawable::relativePosition(Triple rel)
+{
+	return ViewPort2World(Triple((rel.x-viewport[0])*viewport[2],(rel.y-viewport[1])*viewport[3],rel.z));
+}
+
+void Drawable::draw()
+{
+	saveGLState();
+
+	for (std::list<Drawable*>::iterator it = dlist.begin(); it!=dlist.end(); ++it)
+	{
+		(*it)->draw();
+	}
+	restoreGLState();
+}
+
+void Drawable::setColor(double r, double g, double b, double a)
+{
+	color = RGBA(r,g,b,a);
+}	
+
+void Drawable::setColor(RGBA rgba)
+{
+	color = rgba;
+}	
diff --git a/src/qwt3d_enrichment_std.cpp b/src/qwt3d_enrichment_std.cpp
new file mode 100644
index 0000000..03857e9
--- /dev/null
+++ b/src/qwt3d_enrichment_std.cpp
@@ -0,0 +1,347 @@
+#include <math.h>
+#include "qwt3d_color.h"
+#include "qwt3d_plot.h"
+#include "qwt3d_enrichment_std.h"
+
+using namespace Qwt3D;
+
+
+/////////////////////////////////////////////////////////////////
+//
+//   CrossHair
+//
+/////////////////////////////////////////////////////////////////
+
+CrossHair::CrossHair()
+{
+  configure(0, 1, false, false);
+}
+
+CrossHair::CrossHair(double rad, double linewidth, bool smooth, bool boxed)
+{
+  configure(rad, linewidth, smooth, boxed);
+}
+
+void CrossHair::configure(double rad, double linewidth, bool smooth, bool boxed)
+{
+  plot = 0;
+  radius_ = rad;
+  linewidth_ = linewidth;
+  smooth_ = smooth;
+  boxed_ = boxed;
+}
+
+void CrossHair::drawBegin()
+{
+  setDeviceLineWidth( linewidth_ );
+  oldstate_ = glIsEnabled(GL_LINE_SMOOTH);
+  if (smooth_)
+    glEnable(GL_LINE_SMOOTH);
+  else
+    glDisable(GL_LINE_SMOOTH);
+	glBegin( GL_LINES );
+}
+
+void CrossHair::drawEnd()
+{
+  glEnd();
+
+  if (oldstate_)
+    glEnable(GL_LINE_SMOOTH);
+  else
+    glDisable(GL_LINE_SMOOTH);
+}
+
+void CrossHair::draw(Qwt3D::Triple const& pos)
+{
+	RGBA rgba = (*plot->dataColor())(pos);
+	glColor4d(rgba.r,rgba.g,rgba.b,rgba.a);
+
+  double diag = (plot->hull().maxVertex-plot->hull().minVertex).length() * radius_;
+
+  glVertex3d( pos.x - diag, pos.y, pos.z); 
+	glVertex3d( pos.x + diag, pos.y, pos.z); 
+	
+  glVertex3d( pos.x, pos.y - diag, pos.z); 
+	glVertex3d( pos.x, pos.y + diag, pos.z); 
+  
+  glVertex3d( pos.x, pos.y, pos.z - diag); 
+	glVertex3d( pos.x, pos.y, pos.z + diag); 
+
+  // hull
+  
+  if (!boxed_)
+    return;
+
+  glVertex3d( pos.x - diag, pos.y - diag, pos.z + diag); 
+	glVertex3d( pos.x + diag, pos.y - diag, pos.z + diag); 
+  glVertex3d( pos.x - diag, pos.y - diag, pos.z - diag); 
+	glVertex3d( pos.x + diag, pos.y - diag, pos.z - diag); 
+  
+  glVertex3d( pos.x - diag, pos.y + diag, pos.z + diag); 
+	glVertex3d( pos.x + diag, pos.y + diag, pos.z + diag); 
+  glVertex3d( pos.x - diag, pos.y + diag, pos.z - diag); 
+	glVertex3d( pos.x + diag, pos.y + diag, pos.z - diag); 
+
+  glVertex3d( pos.x - diag, pos.y - diag, pos.z + diag); 
+	glVertex3d( pos.x - diag, pos.y + diag, pos.z + diag); 
+  glVertex3d( pos.x - diag, pos.y - diag, pos.z - diag); 
+	glVertex3d( pos.x - diag, pos.y + diag, pos.z - diag); 
+  
+  glVertex3d( pos.x + diag, pos.y - diag, pos.z + diag); 
+	glVertex3d( pos.x + diag, pos.y + diag, pos.z + diag); 
+  glVertex3d( pos.x + diag, pos.y - diag, pos.z - diag); 
+	glVertex3d( pos.x + diag, pos.y + diag, pos.z - diag); 
+
+  glVertex3d( pos.x - diag, pos.y - diag, pos.z - diag); 
+	glVertex3d( pos.x - diag, pos.y - diag, pos.z + diag); 
+  glVertex3d( pos.x + diag, pos.y - diag, pos.z - diag); 
+	glVertex3d( pos.x + diag, pos.y - diag, pos.z + diag); 
+  
+  glVertex3d( pos.x - diag, pos.y + diag, pos.z - diag); 
+	glVertex3d( pos.x - diag, pos.y + diag, pos.z + diag); 
+  glVertex3d( pos.x + diag, pos.y + diag, pos.z - diag); 
+	glVertex3d( pos.x + diag, pos.y + diag, pos.z + diag); 
+}
+
+/////////////////////////////////////////////////////////////////
+//
+//   Dot
+//
+/////////////////////////////////////////////////////////////////
+
+Dot::Dot()
+{
+  configure(1, false);
+}
+
+Dot::Dot(double pointsize, bool smooth)
+{
+  configure(pointsize, smooth);
+}
+
+void Dot::configure(double pointsize, bool smooth)
+{
+  plot = 0;
+  pointsize_ = pointsize;
+  smooth_ = smooth;
+}
+
+void Dot::drawBegin()
+{
+  setDevicePointSize( pointsize_ );
+  oldstate_ = glIsEnabled(GL_POINT_SMOOTH);
+  if (smooth_)
+    glEnable(GL_POINT_SMOOTH);
+  else
+    glDisable(GL_POINT_SMOOTH);
+
+  //glPointSize(10);
+	glBegin( GL_POINTS );
+}
+
+void Dot::drawEnd()
+{
+  glEnd();
+
+  if (oldstate_)
+    glEnable(GL_POINT_SMOOTH);
+  else
+    glDisable(GL_POINT_SMOOTH);
+}
+
+void Dot::draw(Qwt3D::Triple const& pos)
+{
+	RGBA rgba = (*plot->dataColor())(pos);
+  glColor4d(rgba.r,rgba.g,rgba.b,rgba.a);
+  glVertex3d( pos.x, pos.y, pos.z);   
+}
+
+
+/////////////////////////////////////////////////////////////////
+//
+//   Cone
+//
+/////////////////////////////////////////////////////////////////
+
+Cone::Cone()
+{
+	hat      = gluNewQuadric();
+	disk     = gluNewQuadric();
+
+  configure(0, 3);
+}
+
+Cone::Cone(double rad, unsigned quality)
+{
+	hat      = gluNewQuadric();
+	disk     = gluNewQuadric();
+
+  configure(rad, quality);
+}
+
+Cone::~Cone()
+{
+	gluDeleteQuadric(hat);
+	gluDeleteQuadric(disk);
+}
+
+void Cone::configure(double rad, unsigned quality)
+{
+  plot = 0;
+  radius_ = rad;
+  quality_ = quality;
+  oldstate_ = GL_FALSE;
+
+	gluQuadricDrawStyle(hat,GLU_FILL);
+	gluQuadricNormals(hat,GLU_SMOOTH);
+	gluQuadricOrientation(hat,GLU_OUTSIDE);
+	gluQuadricDrawStyle(disk,GLU_FILL);
+	gluQuadricNormals(disk,GLU_SMOOTH);
+	gluQuadricOrientation(disk,GLU_OUTSIDE);
+}
+
+void Cone::draw(Qwt3D::Triple const& pos)
+{  
+	RGBA rgba = (*plot->dataColor())(pos);
+  glColor4d(rgba.r,rgba.g,rgba.b,rgba.a);
+
+  GLint mode;
+	glGetIntegerv(GL_MATRIX_MODE, &mode);
+	glMatrixMode( GL_MODELVIEW );
+  glPushMatrix();
+
+  glTranslatef(pos.x, pos.y, pos.z);
+
+  gluCylinder(hat, 0.0, radius_, radius_*2, quality_, 1);
+  glTranslatef(0, 0, radius_*2);
+	gluDisk(disk, 0.0, radius_, quality_, 1);
+
+  glPopMatrix();
+	glMatrixMode(mode);
+}
+
+
+/////////////////////////////////////////////////////////////////
+//
+//   Arrow
+//
+/////////////////////////////////////////////////////////////////
+
+Arrow::Arrow()
+{	
+	hat      = gluNewQuadric();
+	disk     = gluNewQuadric();
+	base    = gluNewQuadric();
+	bottom   = gluNewQuadric();
+
+	gluQuadricDrawStyle(hat,GLU_FILL);
+	gluQuadricNormals(hat,GLU_SMOOTH);
+	gluQuadricOrientation(hat,GLU_OUTSIDE);
+	gluQuadricDrawStyle(disk,GLU_FILL);
+	gluQuadricNormals(disk,GLU_SMOOTH);
+	gluQuadricOrientation(disk,GLU_OUTSIDE);
+	gluQuadricDrawStyle(base,GLU_FILL);
+	gluQuadricNormals(base,GLU_SMOOTH);
+	gluQuadricOrientation(base,GLU_OUTSIDE);
+	gluQuadricDrawStyle(bottom,GLU_FILL);
+	gluQuadricNormals(bottom,GLU_SMOOTH);
+	gluQuadricOrientation(bottom,GLU_OUTSIDE);
+
+	configure(3, 0.4, 0.06, 0.02);
+}
+
+Arrow::~Arrow()
+{
+	gluDeleteQuadric(hat);
+	gluDeleteQuadric(disk);
+	gluDeleteQuadric(base);
+	gluDeleteQuadric(bottom);
+}
+
+/**
+\param segs number of faces for the fields arrows (see the gallery for examples)
+\param relconelength see picture
+\param relconerad see picture
+\param relstemrad see picture
+\image html arrowanatomy.png 
+*/
+void Arrow::configure(int segs, double relconelength, double relconerad, double relstemrad)
+{
+	plot = 0;
+  segments_ = segs;
+  oldstate_ = GL_FALSE;
+	rel_cone_length = relconelength;
+	rel_cone_radius = relconerad;
+	rel_stem_radius = relstemrad;	
+}
+
+void Arrow::draw(Qwt3D::Triple const& pos)
+{	
+	Triple end = top_;
+	Triple beg = pos;
+	Triple vdiff = end-beg;
+	double length = vdiff.length();
+	glColor4d(rgba_.r,rgba_.g,rgba_.b,rgba_.a);
+
+	double radius[2];
+	radius[0] = rel_cone_radius * length;
+	radius[1] = rel_stem_radius * length;
+	
+	GLint mode;
+	glGetIntegerv(GL_MATRIX_MODE, &mode);
+
+	glMatrixMode( GL_MODELVIEW );
+  glPushMatrix();
+
+
+	Triple axis;
+	double phi = calcRotation(axis, FreeVector(beg,end));
+	
+	glTranslatef(beg.x, beg.y, beg.z);
+  glRotatef(phi, axis.x, axis.y, axis.z);
+
+	double baseheight = (1-rel_cone_length) * length;
+	
+	glTranslatef(0, 0, baseheight);
+
+	gluCylinder(hat, radius[0], 0.0, rel_cone_length * length, segments_,1);
+	gluDisk(disk,radius[1],radius[0], segments_,1);
+	
+	glTranslatef(0, 0, -baseheight);
+	
+	gluCylinder(base, radius[1],radius[1], baseheight,segments_,1);
+	gluDisk(disk,0,radius[1],segments_,1);
+
+  glPopMatrix();
+	glMatrixMode(mode);
+}
+
+
+//! transform a vector on the z axis with length |beg-end|, to get them in coincidence with the vector(beg,end)
+/**
+	\return Angle in degree to rotate
+	\param axis   The axis to rotate around
+	\param beg    result vector base point
+	\param end    result vector top point
+*/ 
+double Arrow::calcRotation(Triple& axis, FreeVector const& vec)
+{
+	
+	Triple end = vec.top;
+	Triple beg = vec.base;
+
+	Triple firstbeg(0.0,0.0,0.0);
+	Triple firstend(0.0,0.0,(end-beg).length());
+	
+	Triple first = firstend - firstbeg;
+	first.normalize();
+
+	Triple second = end-beg;
+	second.normalize();
+
+	axis = normalizedcross(first,second);
+	double cosphi = dotProduct(first,second);
+	
+	return 180 * acos(cosphi) / Qwt3D::PI;
+}
diff --git a/src/qwt3d_function.cpp b/src/qwt3d_function.cpp
new file mode 100644
index 0000000..3271aea
--- /dev/null
+++ b/src/qwt3d_function.cpp
@@ -0,0 +1,101 @@
+#include "qwt3d_surfaceplot.h"
+#include "qwt3d_function.h"
+
+using namespace Qwt3D;
+
+Function::Function()
+:GridMapping()
+{
+}
+
+Function::Function(SurfacePlot& pw)
+:GridMapping()
+{
+  plotwidget_p = &pw;
+}
+
+Function::Function(SurfacePlot* pw)
+:GridMapping()
+{
+  plotwidget_p = pw;
+}
+
+void Function::assign(SurfacePlot& plotWidget)
+{
+	if (&plotWidget != plotwidget_p)
+		plotwidget_p = &plotWidget;
+}
+
+void Function::assign(SurfacePlot* plotWidget)
+{
+	if (plotWidget != plotwidget_p)
+		plotwidget_p = plotWidget;
+}
+
+void Function::	setMinZ(double val)
+{
+	range_p.minVertex.z = val;
+}
+
+void Function::	setMaxZ(double val)
+{
+	range_p.maxVertex.z = val;
+}
+
+bool Function::create()
+{
+	if ((umesh_p<=2) || (vmesh_p<=2) || !plotwidget_p)
+		return false;
+	
+	/* allocate some space for the mesh */
+ 	double** data         = new double* [umesh_p] ;
+
+	unsigned i,j;
+	for ( i = 0; i < umesh_p; i++) 
+	{
+		data[i]         = new double [vmesh_p];
+	}
+	
+	/* get the data */
+
+	double dx = (maxu_p - minu_p) / (umesh_p - 1);
+	double dy = (maxv_p - minv_p) / (vmesh_p - 1);
+	
+	for (i = 0; i < umesh_p; ++i) 
+	{
+		for (j = 0; j < vmesh_p; ++j) 
+		{
+			data[i][j] = operator()(minu_p + i*dx, minv_p + j*dy);
+			
+			if (data[i][j] > range_p.maxVertex.z)
+				data[i][j] = range_p.maxVertex.z;
+			else if (data[i][j] < range_p.minVertex.z)
+				data[i][j] = range_p.minVertex.z;
+		}
+	}
+
+	Q_ASSERT(plotwidget_p);
+	if (!plotwidget_p)
+	{
+		fprintf(stderr,"Function: no valid Plot3D Widget assigned");
+	}
+	else
+	{
+		((SurfacePlot*)plotwidget_p)->loadFromData(data, umesh_p, vmesh_p, minu_p, maxu_p, minv_p, maxv_p);
+	}
+
+	for ( i = 0; i < umesh_p; i++) 
+	{
+		delete [] data[i];
+	}
+
+	delete [] data;
+
+	return true;
+}
+
+bool Function::create(SurfacePlot& pl)
+{
+  assign(pl);
+  return create();
+}
diff --git a/src/qwt3d_gridmapping.cpp b/src/qwt3d_gridmapping.cpp
new file mode 100644
index 0000000..019ba1c
--- /dev/null
+++ b/src/qwt3d_gridmapping.cpp
@@ -0,0 +1,32 @@
+#include "qwt3d_gridmapping.h"
+#include "qwt3d_surfaceplot.h"
+
+using namespace Qwt3D;
+
+GridMapping::GridMapping()
+{
+	plotwidget_p = 0;
+	setMesh(0,0);
+	setDomain(0,0,0,0);
+  restrictRange(ParallelEpiped(Triple(-DBL_MAX,-DBL_MAX,-DBL_MAX),Triple(DBL_MAX,DBL_MAX,DBL_MAX)));
+}
+
+void GridMapping::setMesh(unsigned int columns,unsigned int rows)
+{
+	umesh_p = columns;
+	vmesh_p = rows;
+}
+
+void GridMapping::setDomain(double minu, double maxu, double minv, double maxv)
+{
+	minu_p = minu;
+	maxu_p = maxu;
+	minv_p = minv;
+	maxv_p = maxv;
+}
+
+void GridMapping::restrictRange(Qwt3D::ParallelEpiped const& p)
+{
+	range_p = p;
+}
+
diff --git a/src/qwt3d_gridplot.cpp b/src/qwt3d_gridplot.cpp
new file mode 100644
index 0000000..561a3a3
--- /dev/null
+++ b/src/qwt3d_gridplot.cpp
@@ -0,0 +1,596 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4305 )
+#pragma warning ( disable : 4786 )
+#endif
+
+#include "qwt3d_surfaceplot.h"
+#include "qwt3d_enrichment_std.h"
+
+using namespace std;
+using namespace Qwt3D;
+
+
+
+void SurfacePlot::createDataG()
+{
+  createFloorData();
+  
+  if (plotStyle() == NOPLOT)
+		return;
+
+	int i, j;
+	RGBA col;
+	int step = resolution();
+
+  if (plotStyle() == Qwt3D::POINTS)
+  {
+    createPoints();
+    return;
+  }
+  else if (plotStyle() == Qwt3D::USER)
+  {
+    if (userplotstyle_p)
+      createEnrichment(*userplotstyle_p);
+    return;
+  }
+
+	setDeviceLineWidth(meshLineWidth());
+  
+  GLStateBewarer sb(GL_POLYGON_OFFSET_FILL,true);
+	setDevicePolygonOffset(polygonOffset(),1.0);
+
+	GLStateBewarer sb2(GL_LINE_SMOOTH, smoothDataMesh());
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+
+  int lastcol =  actualDataG_->columns();
+  int lastrow =  actualDataG_->rows(); 
+ 
+	if (plotStyle() != WIREFRAME)
+	{
+		glPolygonMode(GL_FRONT_AND_BACK, GL_QUADS);
+		
+		bool hl = (plotStyle() == HIDDENLINE);
+		if (hl)
+		{
+			col = backgroundRGBAColor();
+			glColor4d(col.r, col.g, col.b, col.a);
+		}
+
+		for (i = 0; i < lastcol - step; i += step) 
+		{
+		  glBegin(GL_TRIANGLE_STRIP);
+				setColorFromVertexG(i, 0, hl);
+				glNormal3dv(actualDataG_->normals[i][0]);
+				glVertex3dv(actualDataG_->vertices[i][0]);
+					
+				setColorFromVertexG(i+step, 0, hl);
+				glNormal3dv(actualDataG_->normals[i+step][0]);
+				glVertex3dv(actualDataG_->vertices[i+step][0]);
+
+				for (j = 0; j < lastrow - step; j += step) 
+				{				
+					setColorFromVertexG(i,j+step, hl);
+					glNormal3dv(actualDataG_->normals[i][j+step]);
+					glVertex3dv(actualDataG_->vertices[i][j+step]);
+
+					setColorFromVertexG(i+step, j+step, hl);
+					glNormal3dv(actualDataG_->normals[i+step][j+step]);
+					glVertex3dv(actualDataG_->vertices[i+step][j+step]);
+				}
+			glEnd();
+		}
+  }
+
+	if (plotStyle() == FILLEDMESH || plotStyle() == WIREFRAME || plotStyle() == HIDDENLINE)
+	{
+		glColor4d(meshColor().r, meshColor().g, meshColor().b, meshColor().a);		
+
+		if (step < actualDataG_->columns() && step < actualDataG_->rows())
+		{
+			glBegin(GL_LINE_LOOP);
+				for (i = 0; i < actualDataG_->columns() - step; i += step) 
+					glVertex3dv(actualDataG_->vertices[i][0]);		
+				for (j = 0; j < actualDataG_->rows() - step; j += step) 
+					glVertex3dv(actualDataG_->vertices[i][j]);						
+				for (; i >= 0; i -= step) 
+					glVertex3dv(actualDataG_->vertices[i][j]);			
+				for (; j >= 0; j -= step) 
+					glVertex3dv(actualDataG_->vertices[0][j]);			
+			glEnd();
+		}
+
+		// weaving
+		for (i = step; i < actualDataG_->columns() - step; i += step) 
+		{		
+			glBegin(GL_LINE_STRIP);
+				for (j = 0; j < actualDataG_->rows(); j += step) 
+					glVertex3dv(actualDataG_->vertices[i][j]);			
+			glEnd();
+		}
+		for (j = step; j < actualDataG_->rows() - step; j += step) 
+		{		
+			glBegin(GL_LINE_STRIP);
+				for (i = 0; i < actualDataG_->columns(); i += step) 
+					glVertex3dv(actualDataG_->vertices[i][j]);			
+			glEnd();
+		}
+	}
+}
+
+void SurfacePlot::setColorFromVertexG(int ix, int iy, bool skip)
+{
+	if (skip)
+		return;
+
+	RGBA col = (*datacolor_p)(
+		actualDataG_->vertices[ix][iy][0],
+		actualDataG_->vertices[ix][iy][1],
+		actualDataG_->vertices[ix][iy][2]);
+		
+	glColor4d(col.r, col.g, col.b, col.a);
+}
+
+
+void SurfacePlot::createNormalsG()
+{
+	if (!normals() || actualDataG_->empty())
+		return;
+
+  Arrow arrow;
+  arrow.setQuality(normalQuality());
+
+	Triple basev, topv, norm;	
+	
+	int step = resolution();
+
+	double diag = (actualDataG_->hull().maxVertex-actualDataG_->hull().minVertex).length() * normalLength();
+
+  arrow.assign(*this);
+  arrow.drawBegin();
+	for (int i = 0; i <= actualDataG_->columns() - step; i += step) 
+	{
+		for (int j = 0; j <= actualDataG_->rows() - step; j += step) 
+		{
+			basev = Triple(actualDataG_->vertices[i][j][0],actualDataG_->vertices[i][j][1],actualDataG_->vertices[i][j][2]);
+			topv = Triple(actualDataG_->vertices[i][j][0]+actualDataG_->normals[i][j][0],
+							 actualDataG_->vertices[i][j][1]+actualDataG_->normals[i][j][1],
+							 actualDataG_->vertices[i][j][2]+actualDataG_->normals[i][j][2]);	
+			
+			norm = topv-basev;
+			norm.normalize();
+			norm	*= diag;
+
+      arrow.setTop(basev+norm);
+      arrow.setColor((*datacolor_p)(basev.x,basev.y,basev.z));
+      arrow.draw(basev);
+		}
+	}
+  arrow.drawEnd();
+}
+
+void SurfacePlot::readIn(GridData& gdata, Triple** data, unsigned int columns, unsigned int rows)
+{
+	gdata.setSize(columns,rows);
+	
+  ParallelEpiped range(Triple(DBL_MAX,DBL_MAX,DBL_MAX),Triple(-DBL_MAX,-DBL_MAX,-DBL_MAX));
+
+	/* fill out the vertex array for the mesh. */
+	for (unsigned i = 0; i != columns; ++i) 
+	{
+		for (unsigned j = 0; j != rows; ++j) 
+		{
+			gdata.vertices[i][j][0] = data[i][j].x; 
+			gdata.vertices[i][j][1] = data[i][j].y;
+			gdata.vertices[i][j][2] = data[i][j].z;
+
+			if (data[i][j].x > range.maxVertex.x)
+				range.maxVertex.x = data[i][j].x;
+			if (data[i][j].y > range.maxVertex.y)
+				range.maxVertex.y = data[i][j].y;
+			if (data[i][j].z > range.maxVertex.z)
+				range.maxVertex.z = data[i][j].z;
+			if (data[i][j].x < range.minVertex.x)
+				range.minVertex.x = data[i][j].x;
+			if (data[i][j].y < range.minVertex.y)
+				range.minVertex.y = data[i][j].y;
+			if (data[i][j].z < range.minVertex.z)
+				range.minVertex.z = data[i][j].z;
+ 		}
+	}
+  gdata.setHull(range);
+}
+
+
+void SurfacePlot::readIn(GridData& gdata, double** data, unsigned int columns, unsigned int rows
+            , double minx, double maxx, double miny, double maxy)
+{
+  gdata.setPeriodic(false,false);
+	gdata.setSize(columns,rows);
+	
+	double dx = (maxx - minx) / (gdata.columns() - 1);
+	double dy = (maxy - miny) / (gdata.rows() - 1);
+
+	double tmin = DBL_MAX;
+	double tmax = -DBL_MAX;
+
+	/* fill out the vertex array for the mesh. */
+	for (unsigned i = 0; i != columns; ++i) 
+	{
+		for (unsigned j = 0; j != rows; ++j) 
+		{
+			gdata.vertices[i][j][0] = minx + i*dx;
+			gdata.vertices[i][j][1] = miny + j*dy;
+			gdata.vertices[i][j][2] = data[i][j];
+
+			if (data[i][j] > tmax)
+				tmax = data[i][j];
+			if (data[i][j] < tmin)
+				tmin = data[i][j];
+ 		}
+	}
+	ParallelEpiped hull = 
+  ParallelEpiped(
+										Triple(	
+														gdata.vertices[0][0][0], 
+														gdata.vertices[0][0][1], 
+														tmin
+													), 
+										Triple(
+														gdata.vertices[gdata.columns()-1][gdata.rows()-1][0], 
+														gdata.vertices[gdata.columns()-1][gdata.rows()-1][1], 
+														tmax
+													)
+									);
+
+	gdata.setHull(hull);
+}
+
+
+void SurfacePlot::calcNormals(GridData& gdata)
+{
+	
+  unsigned int rows = gdata.rows();
+  unsigned int columns = gdata.columns();
+  
+  // normals
+	  
+	Triple u, v, n;  // for cross product
+
+	for (unsigned i = 0; i != columns; ++i) 
+	{
+		for (unsigned j = 0; j != rows; ++j) 
+		{
+			n = Triple(0,0,0);
+      
+      
+      if (i<columns-1 && j<rows-1) 
+      {
+        /*	get two vectors to cross */      
+        u = Triple(
+									  gdata.vertices[i+1][j][0] - gdata.vertices[i][j][0],
+									  gdata.vertices[i+1][j][1] - gdata.vertices[i][j][1],
+									  gdata.vertices[i+1][j][2] - gdata.vertices[i][j][2]
+								  );
+
+        v = Triple(
+									  gdata.vertices[i][j+1][0] - gdata.vertices[i][j][0],
+									  gdata.vertices[i][j+1][1] - gdata.vertices[i][j][1],
+									  gdata.vertices[i][j+1][2] - gdata.vertices[i][j][2]
+								  );
+        /* get the normalized cross product */ 
+        n += normalizedcross(u,v); // right hand system here !
+      }
+
+      if (i>0 && j<rows-1) 
+      {
+        u = Triple(
+									  gdata.vertices[i][j+1][0] - gdata.vertices[i][j][0],
+									  gdata.vertices[i][j+1][1] - gdata.vertices[i][j][1],
+									  gdata.vertices[i][j+1][2] - gdata.vertices[i][j][2]
+								  );
+			  v = Triple(
+									  gdata.vertices[i-1][j][0] - gdata.vertices[i][j][0],
+									  gdata.vertices[i-1][j][1] - gdata.vertices[i][j][1],
+									  gdata.vertices[i-1][j][2] - gdata.vertices[i][j][2]
+								  );
+        n += normalizedcross(u,v); 
+      }
+
+      if (i>0 && j>0) 
+      {
+        u = Triple(
+									  gdata.vertices[i-1][j][0] - gdata.vertices[i][j][0],
+									  gdata.vertices[i-1][j][1] - gdata.vertices[i][j][1],
+									  gdata.vertices[i-1][j][2] - gdata.vertices[i][j][2]
+								  );
+
+        v = Triple(
+									  gdata.vertices[i][j-1][0] - gdata.vertices[i][j][0],
+									  gdata.vertices[i][j-1][1] - gdata.vertices[i][j][1],
+									  gdata.vertices[i][j-1][2] - gdata.vertices[i][j][2]
+								  );
+        n += normalizedcross(u,v); 
+      }
+
+      if (i<columns-1 && j>0) 
+      {
+        u = Triple(
+									  gdata.vertices[i][j-1][0] - gdata.vertices[i][j][0],
+									  gdata.vertices[i][j-1][1] - gdata.vertices[i][j][1],
+									  gdata.vertices[i][j-1][2] - gdata.vertices[i][j][2]
+								  );
+
+        v = Triple(
+									  gdata.vertices[i+1][j][0] - gdata.vertices[i][j][0],
+									  gdata.vertices[i+1][j][1] - gdata.vertices[i][j][1],
+									  gdata.vertices[i+1][j][2] - gdata.vertices[i][j][2]
+								  );
+        n += normalizedcross(u,v);
+      }
+      n.normalize();
+
+			gdata.normals[i][j][0] = n.x;
+			gdata.normals[i][j][1] = n.y;
+			gdata.normals[i][j][2] = n.z;
+		}    
+	} 
+}
+
+
+void SurfacePlot::sewPeriodic(GridData& gdata)
+{
+  // sewing 
+   
+  Triple n;
+  
+  unsigned int columns = gdata.columns();
+  unsigned int rows = gdata.rows();
+  
+  if (gdata.uperiodic())
+  {
+    for (unsigned i = 0; i != columns; ++i) 
+    {
+      n = Triple(
+									gdata.normals[i][0][0] + gdata.normals[i][rows-1][0],
+									gdata.normals[i][0][1] + gdata.normals[i][rows-1][1],
+									gdata.normals[i][0][2] + gdata.normals[i][rows-1][2]
+								);
+
+      n.normalize();        
+			gdata.normals[i][0][0] = gdata.normals[i][rows-1][0] = n.x;
+			gdata.normals[i][0][1] = gdata.normals[i][rows-1][1] = n.y;
+			gdata.normals[i][0][2] = gdata.normals[i][rows-1][2] = n.z;
+    }
+  }
+  if (gdata.vperiodic())
+  {
+    for (unsigned j = 0; j != rows; ++j) 
+    {
+      n = Triple(
+									gdata.normals[0][j][0] + gdata.normals[columns-1][j][0],
+									gdata.normals[0][j][1] + gdata.normals[columns-1][j][1],
+									gdata.normals[0][j][2] + gdata.normals[columns-1][j][2]
+								);
+
+      n.normalize();        
+			gdata.normals[0][j][0] = gdata.normals[columns-1][j][0] = n.x;
+			gdata.normals[0][j][1] = gdata.normals[columns-1][j][1] = n.y;
+			gdata.normals[0][j][2] = gdata.normals[columns-1][j][2] = n.z;
+    }
+  }
+}
+
+/*!
+	Convert user grid data to internal vertex structure.
+	See also NativeReader::read() and Function::create()
+*/
+bool SurfacePlot::loadFromData(Triple** data, unsigned int columns, unsigned int rows, bool uperiodic, bool vperiodic)
+{
+  actualDataC_->clear();
+  actualData_p = actualDataG_;
+
+  readIn(*actualDataG_, data, columns, rows);
+  calcNormals(*actualDataG_);
+  actualDataG_->setPeriodic(uperiodic,vperiodic);
+	sewPeriodic(*actualDataG_);
+
+ 	updateData();
+	updateNormals();
+	createCoordinateSystem();
+
+	return true;
+}	
+
+/*! 
+	Convert user grid data to internal vertex structure.
+	See also NativeReader::read() and Function::create()
+*/
+bool SurfacePlot::loadFromData(double** data, unsigned int columns, unsigned int rows
+																				, double minx, double maxx, double miny, double maxy)
+{	
+  actualDataC_->clear();
+  actualData_p = actualDataG_;
+  
+  actualDataG_->setPeriodic(false,false);
+	actualDataG_->setSize(columns,rows);
+	readIn(*actualDataG_,data,columns,rows,minx,maxx,miny,maxy);
+  calcNormals(*actualDataG_);  
+	
+	updateData();
+	updateNormals();
+	createCoordinateSystem();
+
+	return true;
+}	
+
+
+void SurfacePlot::createFloorDataG()
+{
+	switch (floorStyle())
+	{
+	case FLOORDATA:
+		Data2FloorG();
+		break;
+	case FLOORISO:
+		Isolines2FloorG();
+		break;
+	default:
+		break;
+	}
+}
+
+void SurfacePlot::Data2FloorG()
+{
+	if (actualData_p->empty())
+		return;
+	
+	int step = resolution();
+
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glPolygonMode(GL_FRONT_AND_BACK, GL_QUADS);
+	
+	double zshift = actualData_p->hull().minVertex.z;
+	for (int i = 0; i < actualDataG_->columns() - step; i += step) 
+	{
+		glBegin(GL_TRIANGLE_STRIP);
+  		setColorFromVertexG(i, 0);
+			glVertex3d(actualDataG_->vertices[i][0][0], actualDataG_->vertices[i][0][1], zshift);
+			
+			setColorFromVertexG(i+step, 0);
+			glVertex3d(actualDataG_->vertices[i+step][0][0],actualDataG_->vertices[i+step][0][1], zshift);
+			for (int j = 0; j < actualDataG_->rows() - step; j += step) 
+			{
+				setColorFromVertexG(i, j+step);
+				glVertex3d(actualDataG_->vertices[i][j+step][0],actualDataG_->vertices[i][j+step][1], zshift);
+				
+				setColorFromVertexG(i+step, j+step);
+				glVertex3d(actualDataG_->vertices[i+step][j+step][0],actualDataG_->vertices[i+step][j+step][1], zshift);				
+			}
+		glEnd();
+	}
+}
+
+void SurfacePlot::Isolines2FloorG()
+{
+	if (isolines() <= 0 || actualData_p->empty())
+		return;
+
+	double count = (actualData_p->hull().maxVertex.z - actualData_p->hull().minVertex.z) / isolines();		
+
+	RGBA col;
+
+  int step = resolution();
+
+	double zshift = actualData_p->hull().minVertex.z;
+	
+	int cols = actualDataG_->columns();
+	int rows = actualDataG_->rows();
+	
+	Triple t[4];
+	vector<Triple> intersection;
+	
+	double lambda = 0;
+	
+	GLStateBewarer sb2(GL_LINE_SMOOTH, false);
+
+	for (int k = 0; k != isolines(); ++k) 
+	{
+		double val = zshift + k * count;		
+				
+		for (int i = 0; i < cols-step; i += step) 
+		{
+			for (int j = 0; j < rows-step; j += step) 
+			{
+				t[0] =  Triple(	actualDataG_->vertices[i][j][0],
+												actualDataG_->vertices[i][j][1],
+												actualDataG_->vertices[i][j][2]);
+
+				col = (*datacolor_p)(t[0].x,t[0].y,t[0].z);
+  			glColor4d(col.r, col.g, col.b, col.a);
+//  			glColor4d(0,0,0,1);
+				
+				t[1] =  Triple(	actualDataG_->vertices[i+step][j][0],
+												actualDataG_->vertices[i+step][j][1],
+												actualDataG_->vertices[i+step][j][2]);
+				t[2] =  Triple(	actualDataG_->vertices[i+step][j+step][0],
+												actualDataG_->vertices[i+step][j+step][1],
+												actualDataG_->vertices[i+step][j+step][2]);
+				t[3] =  Triple(	actualDataG_->vertices[i][j+step][0],
+												actualDataG_->vertices[i][j+step][1],
+												actualDataG_->vertices[i][j+step][2]);
+
+				double diff = 0;
+				for (int m = 0; m!=4; ++m)
+				{
+					int mm = (m+1)%4;
+					if ((val>=t[m].z && val<=t[mm].z) || (val>=t[mm].z && val<=t[m].z))
+					{
+						diff = t[mm].z - t[m].z;
+						
+						if (isPracticallyZero(diff)) // degenerated
+						{
+							intersection.push_back(t[m]);
+							intersection.push_back(t[mm]);
+							continue;
+						}
+						
+						lambda =  (val - t[m].z) / diff;
+						intersection.push_back(Triple(t[m].x + lambda * (t[mm].x-t[m].x), t[m].y + lambda * (t[mm].y-t[m].y), val));
+					}
+				}
+				
+				if (!intersection.empty())
+				{
+					if (intersection.size()>2)
+					{
+						glBegin(GL_LINE_STRIP);
+						for (unsigned dd = 0; dd!=intersection.size(); ++dd)
+						{
+							glVertex3d(intersection[dd].x, intersection[dd].y, zshift);
+						}
+						glEnd();
+						glBegin(GL_POINTS);
+							glVertex3d(intersection[0].x,intersection[0].y,zshift);
+						glEnd();
+					}
+					else if (intersection.size() == 2)
+					{
+						glBegin(GL_LINES);
+							glVertex3d(intersection[0].x,intersection[0].y,zshift);
+							glVertex3d(intersection[1].x,intersection[1].y,zshift);
+							
+							// small pixel gap problem (see OpenGL spec.)
+							glVertex3d(intersection[1].x,intersection[1].y,zshift);
+							glVertex3d(intersection[0].x,intersection[0].y,zshift);
+						glEnd();
+					}
+					
+					intersection.clear();
+				}
+			}
+		}
+	}
+}
+
+
+
+/*
+void SurfacePlot::calcLowResolution()
+{
+  if (!actualDataG_)
+    return;
+
+  int res = resolution();
+  if (res == 1)
+  {
+    lowresData_p = *actualDataG_;
+    return;
+  }
+  
+  GridData const& src = *actualDataG_;
+  result.clear();
+  
+  
+}*/
+
diff --git a/src/qwt3d_io.cpp b/src/qwt3d_io.cpp
new file mode 100644
index 0000000..f2e2080
--- /dev/null
+++ b/src/qwt3d_io.cpp
@@ -0,0 +1,365 @@
+#include <time.h>
+
+#include "qwt3d_plot.h"
+#include "qwt3d_io_gl2ps.h"
+#include "qwt3d_io_reader.h"
+#if QT_VERSION < 0x040000
+#else
+  #include <QImageWriter>
+#endif
+
+using namespace Qwt3D;
+
+IO::Entry::Entry() : iofunc(0) 
+{
+}
+
+IO::Entry::~Entry() 
+{
+  delete iofunc;
+}
+
+IO::Entry::Entry(IO::Entry const& e)
+{
+  if (this==&e)
+    return;
+
+  fmt = e.fmt;
+  iofunc = e.iofunc->clone();
+}
+
+void IO::Entry::operator=(IO::Entry const& e)
+{
+  if (this==&e)
+    return;
+
+  delete iofunc;
+  fmt = e.fmt;
+  iofunc = e.iofunc->clone();
+}
+
+IO::Entry::Entry(QString const& s, Functor const& f)
+  : fmt(s) 
+{ 
+  iofunc = f.clone();
+}
+
+IO::Entry::Entry(QString const& s, Function f)
+  : fmt(s) 
+{ 
+  Wrapper  w(f);
+  iofunc = w.clone();
+}
+
+
+IO::FormatCompare::FormatCompare(IO::Entry const& e) 
+{
+  e_ = e;
+}
+
+bool IO::FormatCompare::operator() (IO::Entry const& e)
+{
+  return ( e.fmt == e_.fmt);
+}
+
+IO::FormatCompare2::FormatCompare2(QString s) 
+{
+  s_ = s;
+}
+
+bool IO::FormatCompare2::operator() (IO::Entry const& e)
+{
+  return( e.fmt == s_);
+}
+
+
+
+
+bool IO::add_unique(Container& l, Entry const& e)
+{
+  FormatCompare comp(e);
+  l.erase(std::remove_if(l.begin(), l.end(), comp), l.end());
+  l.push_back(e);
+
+  return true;
+}
+
+IO::IT IO::find(Container& l, QString const& fmt)
+{
+  FormatCompare2 comp(fmt);
+  return std::find_if(l.begin(), l.end(), comp); 
+}
+
+IO::Container& IO::rlist()
+{
+  static Container rl = Container();
+  static bool rfirst = true;
+  bool f = false;
+  f = rfirst;
+  if (rfirst)
+  {
+    rfirst = false;
+    setupHandler();
+  }
+  return rl;
+}
+
+IO::Container& IO::wlist()
+{
+  static Container wl = Container();
+  static bool wfirst = true;
+  bool f = false;
+  f = wfirst;
+  if (wfirst)
+  {
+    wfirst = false;
+    setupHandler();
+  }
+  return wl;
+}
+
+/*! 
+  Registers a new IO::Function for data input.\n
+  Every call overwrites a formerly registered handler for the same format string
+  (case sensitive).
+*/
+bool IO::defineInputHandler(QString const& format, IO::Function func)
+{
+  return add_unique(rlist(), Entry(format, func));
+}
+
+/*! 
+  Registers a new Functor for data input.\n
+  Every call overwrites a formerly registered handler for the same format string
+  (case sensitive).
+*/
+bool IO::defineInputHandler(QString const& format, IO::Functor const& func)
+{
+  return add_unique(rlist(), Entry(format, func));
+}
+
+/*! 
+  Registers a new IO::Function for data output.  
+  Every call overwrites a formerly registered handler for the same format string
+  (case sensitive).
+ */
+bool IO::defineOutputHandler(QString const& format, IO::Function func)
+{
+  return add_unique(wlist(), Entry(format, func));
+}
+
+/*! 
+  Registers a new Functor for data output.\n
+  Every call overwrites a formerly registered handler for the same format string
+  (case sensitive).
+*/
+bool IO::defineOutputHandler(QString const& format, IO::Functor const& func)
+{
+  return add_unique(wlist(), Entry(format, func));
+}
+
+/*!
+  Applies a reading IO::Function or IO::Functor.
+  \param plot Plot with the content that should be loaded
+  \param fname File name 
+  \param format Input format
+  \return The return value from the called Function/Functor. 
+  The function returns false, if no registered handler could be found.
+*/
+bool IO::load(Plot3D* plot, QString const& fname, QString const& format)
+{
+  IT it = IO::find(rlist(), format);
+
+  if (it == rlist().end())
+    return false;
+
+  return (*it->iofunc)(plot, fname);
+}
+
+/*!
+  Applies a writing IO::Function or IO::Functor.
+  \param plot Plot with the content that should be saved
+  \param fname File name
+  \param format Output format
+  \return The return value from the called Function/Functor.
+  The function returns false, if no registered handler could be found.
+*/
+bool IO::save(Plot3D* plot, QString const& fname, QString const& format)
+{
+  IT it = IO::find(wlist(), format);
+
+  if (it == wlist().end())
+    return false;
+
+  return (*it->iofunc)(plot, fname);
+}
+
+/*!
+  Returns a list of currently registered input formats. 
+*/
+QStringList IO::inputFormatList()
+{
+  QStringList list;
+  for ( IT it = rlist().begin(); it!=rlist().end(); ++it )
+    list.append(it->fmt);
+  
+  return list;
+}
+
+/*!
+  Returns a list of currently registered output formats. 
+*/
+QStringList IO::outputFormatList()
+{
+  QStringList list;  
+  for ( IT it = wlist().begin(); it!=wlist().end(); ++it )
+    list.append(it->fmt);
+  
+  return list;
+}
+
+/*! 
+  Returns the input functor in charge for format and 0 if non-existent. 
+*/
+IO::Functor* IO::inputHandler(QString const& format)
+{
+  IO::IT it = IO::find(rlist(), format);
+  
+  if (it==rlist().end())
+    return 0;
+
+  return it->iofunc;
+}
+
+/*! 
+  Returns the output functor in charge for format and 0 if non-existent. 
+*/
+IO::Functor* IO::outputHandler(QString const& format)
+{
+  IO::IT it = IO::find(wlist(), format);
+  
+  if (it==wlist().end())
+    return 0;
+
+  return it->iofunc;
+}
+
+bool PixmapWriter::operator()(Plot3D* plot, QString const& fname)
+{
+  QImage im = plot->grabFrameBuffer(true);
+  
+#if QT_VERSION < 0x040000
+  QImageIO iio;
+  iio.setImage(im);
+#else
+  QImageWriter iio;
+#endif
+  iio.setFormat(QWT3DLOCAL8BIT(fmt_));
+  iio.setQuality(quality_);
+  iio.setFileName(fname);
+#if QT_VERSION < 0x040000
+  return iio.write();
+#else
+  return iio.write(im);
+#endif
+}
+
+//! Calls Qt's QImageIO::setQuality() function.
+void PixmapWriter::setQuality(int val)
+{
+  quality_ = val;  
+}
+
+void IO::setupHandler()
+{
+#if QT_VERSION < 0x040000
+  QStringList list = QImage::outputFormatList();
+  QStringList::Iterator it = list.begin();
+#else
+  QList<QByteArray> list = QImageWriter::supportedImageFormats();
+  QList<QByteArray>::Iterator it = list.begin();
+#endif
+  PixmapWriter qtw;
+  while( it != list.end() ) 
+  {
+    qtw.fmt_ = *it;
+    defineOutputHandler(*it, qtw);
+    ++it;
+  }
+  VectorWriter vecfunc; 
+  vecfunc.setCompressed(false);
+  vecfunc.setFormat("EPS");
+  defineOutputHandler("EPS", vecfunc);
+  vecfunc.setFormat("PS");
+  defineOutputHandler("PS", vecfunc);
+  
+#ifdef GL2PS_HAVE_ZLIB
+  vecfunc.setCompressed(true);
+  vecfunc.setFormat("EPS_GZ");
+  defineOutputHandler("EPS_GZ", vecfunc);
+  vecfunc.setFormat("PS_GZ");
+  defineOutputHandler("PS_GZ", vecfunc);
+#endif
+  vecfunc.setFormat("PDF");
+  defineOutputHandler("PDF", vecfunc);
+  vecfunc.setFormat("SVG");
+  defineOutputHandler("SVG", vecfunc);
+  vecfunc.setFormat("PGF");
+  defineOutputHandler("PGF", vecfunc);
+#ifdef GL2PS_HAVE_ZLIB
+  vecfunc.setFormat("SVG_GZ");
+  defineOutputHandler("SVG_GZ", vecfunc);
+#endif
+
+  defineInputHandler("mes", NativeReader());
+  defineInputHandler("MES", NativeReader());
+}
+
+/*!
+	\deprecated  Use Plot3D::save or IO::save instead.
+	
+  Writes vector data supported by gl2ps. The corresponding format types are "EPS","PS", "PDF", "SVG", or "PGF".
+  If zlib has been configured this will be extended by "EPS_GZ", "PS_GZ" and "SVG_GZ". 
+	\b Beware: BSPSORT turns out to behave very slowly and memory consuming, especially in cases where
+	many polygons appear. It is still more exact than SIMPLESORT.
+*/
+bool Plot3D::saveVector(QString const& fileName, QString const& format, VectorWriter::TEXTMODE textmode, VectorWriter::SORTMODE sortmode)
+{
+  if (format == "EPS" || format == "EPS_GZ" || format == "PS" 
+       || format == "PS_GZ" || format == "PDF" || format == "SVG"
+       || format == "SVG_GZ" || format == "PGF")
+  {  
+    VectorWriter* gl2ps = (VectorWriter*)IO::outputHandler(format);
+    if (gl2ps)
+    {
+      gl2ps->setSortMode(sortmode);
+      gl2ps->setTextMode(textmode);
+    }
+    return IO::save(this, fileName, format);
+  }
+  return false;
+}	
+/*!
+	\deprecated  Use Plot3D::save or IO::save instead.
+  
+  Saves the framebuffer to the file fileName using one of the image file formats supported by Qt.
+*/
+bool Plot3D::savePixmap(QString const& fileName, QString const& format)
+{
+  if (format == "EPS" || format == "EPS_GZ" || format == "PS" 
+      || format == "PS_GZ" || format == "PDF" || format == "SVG"
+      || format == "SVG_GZ" || format == "PGF")
+    return false;
+  
+  return IO::save(this, fileName, format);
+}
+
+/*! 
+  Saves content in one of the registered output formats. To modify the 
+  behaviour for more complex output handling use IO::outputHandler.
+*/
+bool Plot3D::save(QString const& fileName, QString const& format)
+{
+  return IO::save(this, fileName, format);
+}
+
diff --git a/src/qwt3d_io_gl2ps.cpp b/src/qwt3d_io_gl2ps.cpp
new file mode 100644
index 0000000..22e2e0d
--- /dev/null
+++ b/src/qwt3d_io_gl2ps.cpp
@@ -0,0 +1,409 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4786 )
+#endif
+
+#include <time.h>
+#include <locale.h>
+
+#include "qwt3d_openglhelper.h"
+#include "../3rdparty/gl2ps/gl2ps.h"
+#include "qwt3d_io_gl2ps.h"
+#include "qwt3d_plot.h"
+
+using namespace Qwt3D;
+
+//! Provides a new VectorWriter object. 
+IO::Functor* VectorWriter::clone() const
+{
+  return new VectorWriter(*this);
+}
+  
+VectorWriter::VectorWriter() 
+    : gl2ps_format_(GL2PS_EPS), 
+    formaterror_(false),
+#ifdef GL2PS_HAVE_ZLIB
+    compressed_(true),
+#else
+    compressed_(false),
+#endif
+    sortmode_(SIMPLESORT),
+    landscape_(VectorWriter::AUTO),
+    textmode_(VectorWriter::PIXEL),
+    texfname_("")
+  {}
+
+  
+/*!
+  Sets the mode for text output:\n
+  \param val The underlying format for the generated output:\n
+  PIXEL - poor quality but exact positioning\n
+  NATIVE - high quality but inexact positioning\n
+  TEX - high quality and exact positioning, arbitrary TeX strings as content for
+  the saved labels are possible. The disadvantage is the need for an additionally TeX run
+  to get the final output.\n
+  \param fname Optional, used only in conjunction with TeX output; file name
+  for the generated TeX file. If not set, a file called "OUTPUT.FOR.tex" 
+  will be generated, where "OUTPUT.FOR" describes the file name argument for IO::save().\n\n
+  (04/05/27: On Linux platforms, pdflatex seems a file named 'dump_0.pdf.tex' mistakenly to 
+  identify as PDF file.)
+*/
+void VectorWriter::setTextMode(TEXTMODE val, QString fname)
+{
+  textmode_ = val;
+  texfname_ = (fname.isEmpty()) ? QString("") : fname;
+}
+
+
+#ifdef GL2PS_HAVE_ZLIB
+//! Turns compressed output on or off (no effect if zlib support has not been set)
+void VectorWriter::setCompressed(bool val)
+{
+  compressed_ = val;
+}
+#else
+//! Turns compressed output on or off (no effect if zlib support has not been set)
+void VectorWriter::setCompressed(bool)
+{
+  compressed_ = false;
+}
+#endif
+
+
+/*! 
+Set output format, must be one of "EPS_GZ", "PS_GZ", "SVG_GZ", "EPS", 
+"PS", "PDF", "SVG", or "PGF" (case sensitive)
+*/
+bool VectorWriter::setFormat(QString const& format)
+{
+	if (format == QString("EPS"))
+	{
+		gl2ps_format_ = GL2PS_EPS;
+	}
+	else if (format == QString("PS"))
+	{
+		gl2ps_format_ = GL2PS_PS;
+	}
+	else if (format == QString("PDF"))
+	{
+		gl2ps_format_ = GL2PS_PDF;
+	}
+#ifdef GL2PS_HAVE_ZLIB
+	else if (format == QString("EPS_GZ"))
+	{
+		gl2ps_format_ = GL2PS_EPS;
+	}
+	else if (format == QString("PS_GZ"))
+	{
+      gl2ps_format_ = GL2PS_PS;
+  }
+#endif
+  else if (format == QString("SVG"))
+  {
+    gl2ps_format_ = GL2PS_SVG;
+  }
+#ifdef GL2PS_HAVE_ZLIB
+  else if (format == QString("SVG_GZ"))
+  {
+    gl2ps_format_ = GL2PS_SVG;
+  }
+#endif
+  else if (format == QString("PGF"))
+  {
+    gl2ps_format_ = GL2PS_PGF;
+  }
+  else
+  {
+      formaterror_ = true;
+			return false;
+	}
+  formaterror_ = false;
+  return true;
+}
+
+//! Performs actual output
+bool VectorWriter::operator()(Plot3D* plot, QString const& fname)
+{
+  if (formaterror_)
+    return false;
+  
+  char* tmploc = setlocale(LC_ALL, "C");
+
+  plot->makeCurrent();
+ 	
+
+	GLint bufsize = 0, state = GL2PS_OVERFLOW;
+	GLint viewport[4];
+
+	glGetIntegerv(GL_VIEWPORT, viewport);
+
+	GLint options = GL2PS_SIMPLE_LINE_OFFSET | GL2PS_SILENT | GL2PS_DRAW_BACKGROUND |
+										 GL2PS_OCCLUSION_CULL | GL2PS_BEST_ROOT;
+
+
+  if (compressed_)
+    options |= GL2PS_COMPRESS;
+
+  switch (landscape_) 
+  {
+    case VectorWriter::AUTO:
+  	  if (viewport[2] - viewport[0] > viewport[3] - viewport[0])
+        options |= GL2PS_LANDSCAPE;
+      break;
+    case VectorWriter::ON:
+      options |= GL2PS_LANDSCAPE;
+  	  break;
+    default:
+      break;
+  }
+  
+  int sortmode = GL2PS_SIMPLE_SORT;
+  switch (sortmode_) 
+  {
+    case VectorWriter::NOSORT:
+      sortmode = GL2PS_NO_SORT;
+      break;
+    case VectorWriter::SIMPLESORT:
+      sortmode = GL2PS_SIMPLE_SORT;
+  	  break;
+    case VectorWriter::BSPSORT:
+      sortmode = GL2PS_BSP_SORT;
+  	  break;
+    default:
+      break;
+  }
+  
+  switch (textmode_) 
+  {
+    case NATIVE:
+      Label::useDeviceFonts(true);
+  	  break;
+    case PIXEL:
+      Label::useDeviceFonts(false);
+  	  break;
+    case TEX:
+		  options |= GL2PS_NO_PIXMAP | GL2PS_NO_TEXT;
+  	  break;
+    default:
+      break;
+  }
+  
+	QString version = QString::number(QWT3D_MAJOR_VERSION) + "."
+		+ QString::number(QWT3D_MINOR_VERSION) + "."
+		+ QString::number(QWT3D_PATCH_VERSION); 
+	    
+	QString producer = QString("QwtPlot3D ") + version + 
+		", (C) 2002";
+
+  // calculate actual year
+  time_t now;
+  struct tm *newtime;
+  time(&now);
+  newtime = gmtime(&now);
+	if (newtime && newtime->tm_year + 1900 > 2002)
+	  producer += "-" + QString::number(newtime->tm_year+1900); 
+
+  // the SVG format does not like some of the characters in a mail address
+  producer += " Micha Bieber, mailto: krischnamurti at users.sourceforge.net";
+
+	FILE *fp = fopen(QWT3DLOCAL8BIT(fname), "wb");	
+	if (!fp)
+  {
+    Label::useDeviceFonts(false);
+    setlocale(LC_ALL, tmploc);
+    return false;
+  }
+  while( state == GL2PS_OVERFLOW )
+	{ 
+		bufsize += 2*1024*1024;
+		gl2psBeginPage ( QWT3DLOCAL8BIT(fname), QWT3DLOCAL8BIT(producer), viewport,
+										 gl2ps_format_, sortmode,
+										 options, GL_RGBA, 0, NULL, 0, 0, 0, bufsize,
+										 fp, QWT3DLOCAL8BIT(fname) );
+		
+	  plot->updateData();
+	  plot->updateGL(); 
+		state = gl2psEndPage();
+	}
+	fclose(fp);
+
+  // extra TeX file
+  if (textmode_ == TEX)
+  {
+    QString fn = (texfname_.isEmpty()) 
+      ? fname + ".tex"
+      : texfname_;
+
+    fp = fopen(QWT3DLOCAL8BIT(fn), "wb");	
+    if (!fp)
+    {
+      Label::useDeviceFonts(false);
+      setlocale(LC_ALL, tmploc);
+      return false;
+    }    
+    Label::useDeviceFonts(true);
+		options &= ~GL2PS_NO_PIXMAP & ~GL2PS_NO_TEXT;
+    state = GL2PS_OVERFLOW;
+    while( state == GL2PS_OVERFLOW )
+    { 
+      bufsize += 2*1024*1024;
+      gl2psBeginPage ( QWT3DLOCAL8BIT(fname), QWT3DLOCAL8BIT(producer), viewport,
+        GL2PS_TEX, sortmode,
+        options, GL_RGBA, 0, NULL, 0, 0, 0, bufsize,
+        fp, QWT3DLOCAL8BIT(fn) );
+      
+      plot->updateData();
+      plot->updateGL(); 
+      state = gl2psEndPage();
+    }
+    fclose(fp);
+  }
+
+
+  Label::useDeviceFonts(false);
+
+  setlocale(LC_ALL, tmploc);
+  return true;
+}	    
+
+
+// moved
+
+GLint Qwt3D::setDeviceLineWidth(GLfloat val)
+{
+	if (val<0) 
+		val=0;
+
+	GLint ret = gl2psLineWidth(val);
+
+	GLfloat lw[2];
+	glGetFloatv(GL_LINE_WIDTH_RANGE, lw);
+	
+	if (val < lw[0])
+		val = lw[0];
+	else if (val > lw[1])
+		val = lw[1];
+
+	glLineWidth(val);
+	return ret;
+}
+
+GLint Qwt3D::setDevicePointSize(GLfloat val)
+{
+	if (val<0) 
+		val=0;
+
+	GLint ret = gl2psPointSize(val);
+
+	GLfloat lw[2];
+	glGetFloatv(GL_POINT_SIZE_RANGE, lw);
+	
+	if (val < lw[0])
+		val = lw[0];
+	else if (val > lw[1])
+		val = lw[1];
+
+	glPointSize(val);
+	return ret;
+}
+
+GLint Qwt3D::drawDevicePixels(GLsizei width, GLsizei height,
+                       GLenum format, GLenum type,
+                       const void *pixels)
+{
+  glDrawPixels(width, height, format, type, pixels);
+
+  if(format != GL_RGBA || type != GL_UNSIGNED_BYTE)
+		return GL2PS_ERROR;
+	
+	GLfloat* convertedpixel = (GLfloat*)malloc(3 * width * height * sizeof(GLfloat));
+	if (!convertedpixel)
+		return GL2PS_ERROR;
+	
+	GLubyte* px = (GLubyte*)pixels; 
+	for (int i=0; i!=3*width*height; i+=3)
+	{
+		int pxi = (4*i)/3;
+		convertedpixel[i] = px[pxi] / float(255);
+		convertedpixel[i+1] = px[pxi+1] / float(255);
+		convertedpixel[i+2] = px[pxi+2] / float(255);
+	}
+	GLint ret = gl2psDrawPixels(width, height, 0, 0, GL_RGB, GL_FLOAT, convertedpixel);
+	free(convertedpixel);
+	return ret;
+}
+
+GLint Qwt3D::drawDeviceText(const char* str, const char* fontname, int fontsize, Triple pos, RGBA /*rgba*/, ANCHOR align, double gap)
+{
+	double vp[3];
+
+	World2ViewPort(vp[0], vp[1], vp[2], pos.x, pos.y, pos.z);
+	Triple start(vp[0],vp[1],vp[2]);
+
+	GLdouble fcol[4];
+	glGetDoublev(GL_CURRENT_COLOR, fcol);
+	GLdouble bcol[4];
+	glGetDoublev(GL_COLOR_CLEAR_VALUE, bcol);
+	
+//	glColor4d(color.r, color.g, color.b, color.a);
+//		glClearColor(color.r, color.g, color.b, color.a);
+
+	GLint ret = GL2PS_SUCCESS;
+
+	GLint a = GL2PS_TEXT_BL;
+	switch(align)
+	{
+		case Center:
+			a = GL2PS_TEXT_C;
+			break;
+		case CenterLeft:
+			a = GL2PS_TEXT_CL;
+			start += Triple(gap,0,0);
+			break;
+		case CenterRight:
+			a = GL2PS_TEXT_CR;
+			start += Triple(-gap,0,0);
+			break;
+		case BottomCenter:
+			a = GL2PS_TEXT_B;
+			start += Triple(0,gap,0);
+			break;
+		case BottomLeft:
+			a = GL2PS_TEXT_BL;
+			start += Triple(gap,gap,0);
+			break;
+		case BottomRight:
+			a = GL2PS_TEXT_BR;
+			start += Triple(-gap,gap,0);
+			break;
+		case TopCenter:
+			a = GL2PS_TEXT_T;
+			start += Triple(0,-gap,0);
+			break;
+		case TopLeft:
+			a = GL2PS_TEXT_TL;
+			start += Triple(gap,-gap,0);
+			break;
+		case TopRight:
+			a = GL2PS_TEXT_TR;
+			start += Triple(-gap,-gap,0);
+			break;
+		default:
+			break;
+	}
+	
+	ViewPort2World(vp[0], vp[1], vp[2], start.x, start.y, start.z);
+	Triple adjpos(vp[0],vp[1],vp[2]);
+	
+	glRasterPos3d(adjpos.x, adjpos.y, adjpos.z);
+	ret = gl2psTextOpt(str, fontname, (int)fontsize, a, 0);
+	glColor4dv(fcol);
+	glClearColor(bcol[0], bcol[1], bcol[2], bcol[3]);
+  return ret;
+}
+
+void Qwt3D::setDevicePolygonOffset(GLfloat factor, GLfloat units)
+{
+	glPolygonOffset(factor, units);
+	gl2psEnable(GL2PS_POLYGON_OFFSET_FILL);
+}
+
diff --git a/src/qwt3d_io_reader.cpp b/src/qwt3d_io_reader.cpp
new file mode 100644
index 0000000..52f6ecd
--- /dev/null
+++ b/src/qwt3d_io_reader.cpp
@@ -0,0 +1,225 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4786 )
+#endif
+
+#include <float.h>
+#include <stdio.h>
+#include <qtextstream.h>
+
+#include "qwt3d_surfaceplot.h"
+#include "qwt3d_io_reader.h"
+
+using namespace std;
+using namespace Qwt3D;
+
+const char* NativeReader::magicstring = "jk:11051895-17021986";
+
+namespace
+{
+	FILE* open(QString fname)
+	{
+		FILE* file = fopen(QWT3DLOCAL8BIT(fname), "r");
+		if (!file) 
+		{
+			fprintf(stderr, "NativeReader::read: cannot open data file \"%s\"\n", QWT3DLOCAL8BIT(fname));
+		}
+		return file;
+	}
+
+  int read_char (FILE * fp, bool skipcomments = true)
+  {
+    int c;
+  
+    if ((c = fgetc (fp)) == EOF)
+      return (c);
+    if (skipcomments)
+		{
+			if (c == '#')
+			{
+				do
+				{
+					if ((c = fgetc (fp)) == EOF)
+						return (c);
+				}
+				while (c != '\n' && c != '\r');
+			}
+		}
+    return (c);
+  }
+
+  char* read_field (FILE * fp, bool skipcomments = true)
+  {
+    static char buf[71];
+    int c, i;
+  
+    do
+    {
+      if ((c = read_char (fp,skipcomments)) == EOF)
+        return (NULL);
+    }
+    while (isspace (c));
+    for (i = 0; i < 70 && !isspace (c); ++i)
+    {
+      buf[i] = c;
+      if ((c = read_char (fp,skipcomments)) == EOF)
+        break;
+    }
+    buf[i] = '\0';
+    return (buf);
+  }
+
+
+  //! set to data begin
+  bool extract_info(FILE* fp, unsigned int& xmesh, unsigned int& ymesh, double& xmin, double& xmax, double& ymin, double& ymax)
+  {
+    char* p;
+  
+    // find out the size
+    if ((p = read_field (fp)) == 0)
+      return false;
+    xmesh = (unsigned int)atoi(p);
+
+    if ((p = read_field (fp)) == 0)
+      return false;
+    ymesh = (unsigned int)atoi (p);
+
+    if (xmesh < 1 || ymesh < 1)
+      return false;
+    
+		// ... and the limits
+    if ((p = read_field (fp)) == 0)
+      return false;
+    xmin = atof (p);
+
+    if ((p = read_field (fp)) == 0)
+      return false;
+    xmax = atof (p);
+    
+		if ((p = read_field (fp)) == 0)
+      return false;
+    ymin = atof (p);
+
+    if ((p = read_field (fp)) == 0)
+      return false;
+    ymax = atof (p);
+
+    if (xmin > xmax || ymin > ymax)
+      return false;
+
+    return true;
+  }
+
+  //! find out what the magic string is and compare
+	bool check_magic(FILE* fp, const char* val)
+	{
+    char* p;
+    if ((p = read_field (fp,false)) == 0)
+        return false;
+  
+    if (strcmp (p, val ) != 0)
+        return false;	
+		return true;
+	}
+
+	//! find out what the type is
+	bool check_type(FILE* fp, const char* val)
+	{
+    char* p;
+    if ((p = read_field (fp)) == 0)
+        return false;
+  
+    if (strcmp (p, val ) != 0)
+        return false;	
+		return true;
+	}
+
+	double** allocateData(int columns, int rows)
+	{
+ 		double** data         = new double* [columns] ;
+ 
+		for ( int i = 0; i < columns; ++i) 
+		{
+			data[i]         = new double [rows];
+		}
+		return data;
+	}
+
+	void deleteData(double**data, int columns)
+	{
+		for ( int i = 0; i < columns; i++) 
+		{
+			delete [] data[i];
+		}
+		delete [] data;
+	}
+}
+
+NativeReader::NativeReader()
+: minz_(-DBL_MAX), maxz_(DBL_MAX) 
+{
+}
+
+bool NativeReader::collectInfo(FILE*& file, QString const& fname, unsigned& xmesh, unsigned& ymesh, 
+															 double& minx, double& maxx, double& miny, double& maxy)
+{
+	if (fname.isEmpty())
+		return false;
+	
+	file = open(fname);
+	
+	if (!file)
+		return false;
+	
+	
+	if (
+				(!check_magic(file, magicstring))
+			||(!check_type(file, "MESH"))
+			||(!extract_info(file, xmesh, ymesh, minx, maxx, miny, maxy))
+		 )
+	{
+		fclose(file);
+		return false;
+	}
+ 
+	return true;
+}
+
+
+bool NativeReader::operator()(Plot3D* plot, QString const& fname)
+{
+	
+	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", QWT3DLOCAL8BIT(fname));
+				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;
+}
diff --git a/src/qwt3d_label.cpp b/src/qwt3d_label.cpp
new file mode 100644
index 0000000..9cde0e7
--- /dev/null
+++ b/src/qwt3d_label.cpp
@@ -0,0 +1,287 @@
+#include <qbitmap.h>
+#include "qwt3d_label.h"
+
+using namespace Qwt3D;
+
+bool Label::devicefonts_ = false;
+
+Label::Label()
+{
+	init();
+}
+
+Label::Label(const QString & family, int pointSize, int weight, bool italic)
+{
+	init(family, pointSize, weight, italic);
+}
+
+
+void Label::init(const QString & family, int pointSize, int weight, bool italic)
+{
+	init();
+	font_ = QFont(family, pointSize, weight, italic );
+}
+
+void Label::init()
+{
+	beg_ = Triple(0.0, 0.0, 0.0);
+	end_ = beg_;
+	pos_ = beg_;
+	setColor(0,0,0);
+	pm_ = QPixmap(0, 0);
+	font_ = QFont();
+	anchor_ = BottomLeft;
+	gap_ = 0;
+	flagforupdate_ = true;
+}
+
+void Label::useDeviceFonts(bool val)
+{
+	devicefonts_ = val;
+}
+
+void Label::setFont(const QString & family, int pointSize, int weight, bool italic)
+{
+	font_ = QFont(family, pointSize, weight, italic );
+	flagforupdate_ = true;
+}
+
+void Label::setString(QString const& s)
+{
+  text_ = s;
+	flagforupdate_ = true;
+}
+
+void Label::setColor(double r, double g, double b, double a)
+{
+  Drawable::setColor(r,g,b,a);
+  flagforupdate_ = true;
+}	
+
+void Label::setColor(Qwt3D::RGBA rgba)
+{
+  Drawable::setColor(rgba);
+  flagforupdate_ = true;
+}
+
+/**
+example:
+
+\verbatim
+
+   Anchor TopCenter (*)  resp. BottomRight(X) 
+
+   +----*----+
+   |  Pixmap |
+   +---------X
+
+\endverbatim
+*/
+void Label::setPosition(Triple pos, ANCHOR a)
+{
+	anchor_ = a;
+	pos_ = pos;
+}
+
+void Label::setRelPosition(Tuple rpos, ANCHOR a)
+{
+	double ot = 0.99;
+
+	getMatrices(modelMatrix, projMatrix, viewport);
+	beg_ = relativePosition(Triple(rpos.x, rpos.y, ot));
+	setPosition(beg_, a);	
+}
+
+void Label::update()
+{
+	QPainter p;
+	QFontMetrics fm(font_);
+
+  QFontInfo info(font_);
+
+  QRect r = 	QRect(QPoint(0,0),fm.size(Qwt3D::SingleLine, text_));//fm.boundingRect(text_)  misbehaviour under linux;
+  
+#if QT_VERSION < 0x040000
+ 		r.moveBy(0, -r.top());
+#else
+ 		r.translate(0, -r.top());
+#endif
+	
+	pm_ = QPixmap(r.width(), r.bottom());
+
+	if (pm_.isNull()) // else crash under linux
+	{
+		r = 	QRect(QPoint(0,0),fm.size(Qwt3D::SingleLine, QString(" "))); // draw empty space else //todo
+#if QT_VERSION < 0x040000
+ 		r.moveBy(0, -r.top());
+#else
+ 		r.translate(0, -r.top());
+#endif
+		pm_ = QPixmap(r.width(), r.bottom());		
+	}
+	
+	QBitmap bm(pm_.width(),pm_.height());
+#if QT_VERSION >= 0x040000 && defined(Q_WS_X11)
+  bm.fill(Qt::white);
+  p.begin( &bm );
+    p.setPen(Qt::black);
+    p.setFont(font_);
+    p.drawText(0,r.height() - fm.descent() -1 , text_);
+  p.end();
+
+  pm_.setMask(bm);
+  
+  // avoids uninitialized areas in some cases
+  pm_.fill(Qt::white);
+  p.begin( &pm_ );
+    p.setFont( font_ );
+    p.setPen( Qt::SolidLine );
+    p.setPen( GL2Qt(color.r, color.g, color.b) );
+
+    p.drawText(0,r.height() - fm.descent() -1 , text_);
+  p.end();
+
+  buf_ = pm_.toImage();
+#else
+  bm.fill(Qt::color0);
+	p.begin( &bm );
+		p.setPen(Qt::color1);
+		p.setFont(font_);
+		p.drawText(0,r.height() - fm.descent() -1 , text_);
+	p.end();
+
+	pm_.setMask(bm);
+  
+  // avoids uninitialized areas in some cases
+#if QT_VERSION < 0x040000
+	pm_.fill();
+#endif
+	p.begin( &pm_ );
+	  p.setFont( font_ );
+	  p.setPen( Qt::SolidLine );
+	  p.setPen( GL2Qt(color.r, color.g, color.b) );
+
+	  p.drawText(0,r.height() - fm.descent() -1 , text_);
+	p.end();     
+#endif	       
+
+#if QT_VERSION < 0x040000
+  buf_ = pm_.convertToImage();
+#else
+  buf_ = pm_.toImage();
+#endif
+	
+	tex_ = QGLWidget::convertToGLFormat( buf_ );	  // flipped 32bit RGBA ?		
+}
+
+/**
+Adds an additional shift to the anchor point. This happens in a more or less intelligent manner
+depending on the nature of the anchor:
+\verbatim
+anchor type         shift
+
+left aligned         -->
+right aligned        <--
+top aligned          top-down            
+bottom aligned       bottom-up
+\endverbatim
+The unit is user space dependend (one pixel on screen - play around to get satisfying results)
+*/
+void Label::adjust(int gap)
+{
+	gap_ = gap;
+}
+
+void Label::convert2screen()
+{
+	Triple start = World2ViewPort(pos_);
+	
+	switch (anchor_)
+	{
+		case BottomLeft :
+			beg_ = pos_;
+			break;
+		case BottomRight:
+			beg_ = ViewPort2World(start - Triple(width() + gap_, 0, 0));
+			break;
+		case BottomCenter:
+			beg_ = ViewPort2World(start - Triple(width() / 2, -gap_, 0));
+			break;
+		case TopRight:
+			beg_ = ViewPort2World(start - Triple(width() + gap_, height(), 0));
+			break;
+		case TopLeft:
+			beg_ = ViewPort2World(start - Triple(-gap_, height(), 0));
+			break;
+		case TopCenter:
+			beg_ = ViewPort2World(start - Triple(width() / 2, height() + gap_, 0));
+			break;
+		case CenterLeft:
+			beg_ = ViewPort2World(start - Triple(-gap_, height() / 2, 0));
+			break;
+		case CenterRight:
+			beg_ = ViewPort2World(start - Triple(width() + gap_, height() / 2, 0));
+			break;
+		case Center:
+			beg_ = ViewPort2World(start - Triple(width() / 2, height() / 2, 0));
+			break;
+		default:
+			break;
+	}
+	start = World2ViewPort(beg_);
+	end_ = ViewPort2World(start + Triple(width(), height(), 0));	
+}
+
+void Label::draw()
+{
+	if (flagforupdate_)
+	{
+		update();
+		flagforupdate_ = false;
+	}
+
+	if (buf_.isNull())
+		return;
+		
+	GLboolean b;
+	GLint func;
+	GLdouble v;
+	glGetBooleanv(GL_ALPHA_TEST, &b);
+	glGetIntegerv(GL_ALPHA_TEST_FUNC, &func);
+	glGetDoublev(GL_ALPHA_TEST_REF, &v);
+	
+	glEnable (GL_ALPHA_TEST);
+  glAlphaFunc (GL_NOTEQUAL, 0.0);
+	
+	convert2screen();
+	glRasterPos3d(beg_.x, beg_.y, beg_.z);
+ 
+	
+	int w = tex_.width();
+	int h = tex_.height();
+ 
+	if (devicefonts_)
+	{		
+		drawDeviceText(QWT3DLOCAL8BIT(text_), "Courier", font_.pointSize(), pos_, color, anchor_, gap_);
+	}
+	else
+	{
+		drawDevicePixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, tex_.bits());
+//    glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, tex_.bits());	
+	}
+
+
+	glAlphaFunc(func,v);
+	Enable(GL_ALPHA_TEST, b);
+}
+
+
+double Label::width() const 
+{ 
+	return pm_.width(); 
+}
+
+double Label::height() const 
+{ 
+	return pm_.height(); 
+}	
diff --git a/src/qwt3d_lighting.cpp b/src/qwt3d_lighting.cpp
new file mode 100644
index 0000000..658ed50
--- /dev/null
+++ b/src/qwt3d_lighting.cpp
@@ -0,0 +1,192 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4305 )
+#pragma warning ( disable : 4786 )
+#endif
+
+#include <float.h>
+#include "qwt3d_plot.h"
+
+using namespace Qwt3D;
+
+namespace {
+inline GLenum lightEnum(unsigned idx)
+{
+  switch(idx) {
+  case 0:
+  	return GL_LIGHT0;
+  case 1:
+  	return GL_LIGHT1;
+  case 2:
+  	return GL_LIGHT2;
+  case 3:
+  	return GL_LIGHT3;
+  case 4:
+  	return GL_LIGHT4;
+  case 5:
+  	return GL_LIGHT5;
+  case 6:
+  	return GL_LIGHT6;
+  case 7:
+  	return GL_LIGHT7;
+  default:
+  	return GL_LIGHT0;
+  }
+}
+
+}
+
+void Plot3D::enableLighting(bool val)
+{
+  if (lighting_enabled_ == val)
+    return;
+  
+  lighting_enabled_ = val;
+  makeCurrent();
+  if (val)
+    glEnable(GL_LIGHTING);
+  else
+    glDisable(GL_LIGHTING);
+
+  if (!initializedGL())
+    return;
+  updateGL();
+}
+
+void Plot3D::disableLighting(bool val)
+{
+  enableLighting(!val);
+}
+
+bool Plot3D::lightingEnabled() const
+{
+  return lighting_enabled_;
+}
+
+/** 
+  \param light light number [0..7]
+  \see setLight 
+*/
+void Plot3D::illuminate(unsigned light)
+{
+  if (light>7)
+    return;  
+  lights_[light].unlit = false;  
+}
+/**
+  \param light light number [0..7]
+  \see setLight  
+*/
+void Plot3D::blowout(unsigned light)
+{
+  if (light>7)
+    return;
+  lights_[light].unlit = false;  
+}
+
+/** 
+  Sets GL material properties
+*/
+void Plot3D::setMaterialComponent(GLenum property, double r, double g, double b, double a)
+{
+  GLfloat rgba[4] = {(GLfloat)r, (GLfloat)g, (GLfloat)b, (GLfloat)a};
+  makeCurrent();
+  glMaterialfv(GL_FRONT_AND_BACK, property, rgba);  
+}    
+
+/** 
+  This function is for convenience. It sets GL material properties with the equal r,g,b values 
+  and a blending alpha with value 1.0 
+*/
+void Plot3D::setMaterialComponent(GLenum property, double intensity)
+{
+  setMaterialComponent(property,intensity,intensity,intensity,1.0);
+}    
+
+/** 
+  Sets GL shininess
+*/
+void Plot3D::setShininess(double exponent)
+{
+  makeCurrent();
+  glMaterialf(GL_FRONT, GL_SHININESS, exponent);
+}
+
+/** 
+  Sets GL light properties for light 'light'
+*/
+void Plot3D::setLightComponent(GLenum property, double r, double g, double b, double a, unsigned light)
+{
+  GLfloat rgba[4] = {(GLfloat)r, (GLfloat)g, (GLfloat)b, (GLfloat)a};
+  makeCurrent();
+  glLightfv(lightEnum(light), property, rgba);
+}    
+
+/** 
+  This function is for convenience. It sets GL light properties with the equal r,g,b values 
+  and a blending alpha with value 1.0 
+*/
+void Plot3D::setLightComponent(GLenum property, double intensity, unsigned light)
+{
+  setLightComponent(property,intensity,intensity,intensity,1.0, lightEnum(light));
+}    
+
+/**
+  Set the rotation angle of the light source. If you look along the respective axis towards ascending values,
+	the rotation is performed in mathematical \e negative sense 
+	\param xVal angle in \e degree to rotate around the X axis
+	\param yVal angle in \e degree to rotate around the Y axis
+	\param zVal angle in \e degree to rotate around the Z axis
+  \param light light number
+*/
+void Plot3D::setLightRotation( double xVal, double yVal, double zVal, unsigned light )
+{
+	if (light>7)
+    return; 
+  lights_[light].rot.x = xVal;
+  lights_[light].rot.y = yVal;
+  lights_[light].rot.z = zVal;
+}
+
+/**
+  Set the shift in light source (world) coordinates.
+	\param xVal shift along (world) X axis
+	\param yVal shift along (world) Y axis
+	\param zVal shift along (world) Z axis
+  \param light light number
+	\see setViewportShift()
+*/
+void Plot3D::setLightShift( double xVal, double yVal, double zVal, unsigned light )
+{
+	if (light>7)
+    return; 
+  lights_[light].shift.x = xVal;
+  lights_[light].shift.y = yVal;
+  lights_[light].shift.z = zVal;
+}
+
+void Plot3D::applyLight(unsigned light)
+{
+	if (lights_[light].unlit)
+    return;
+
+  glEnable(lightEnum(light));
+  glLoadIdentity();
+  
+  glRotatef( lights_[light].rot.x-90, 1.0, 0.0, 0.0 ); 
+  glRotatef( lights_[light].rot.y   , 0.0, 1.0, 0.0 ); 
+  glRotatef( lights_[light].rot.z   , 0.0, 0.0, 1.0 );
+  GLfloat lightPos[4] = { lights_[light].shift.x, lights_[light].shift.y, lights_[light].shift.z, 1.0};
+  GLenum le = lightEnum(light);
+  glLightfv(le, GL_POSITION, lightPos);  
+}
+
+void Plot3D::applyLights()
+{
+  glMatrixMode( GL_MODELVIEW );
+	glPushMatrix();
+  for (unsigned i=0; i<8; ++i)
+  {
+    applyLight(i);
+  }
+  glPopMatrix();
+}
diff --git a/src/qwt3d_meshplot.cpp b/src/qwt3d_meshplot.cpp
new file mode 100644
index 0000000..44bb7b6
--- /dev/null
+++ b/src/qwt3d_meshplot.cpp
@@ -0,0 +1,320 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4305 )
+#pragma warning ( disable : 4786 )
+#endif
+
+#include "qwt3d_surfaceplot.h"
+#include "qwt3d_enrichment_std.h"
+
+using namespace std;
+using namespace Qwt3D;
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+//     cell specific
+//
+
+
+void SurfacePlot::createDataC()
+{		
+	createFloorDataC();
+  
+  if (plotStyle() == NOPLOT)
+    return;
+
+  if (plotStyle() == Qwt3D::POINTS)
+  {
+    createPoints();
+    return;
+  }
+  else if (plotStyle() == Qwt3D::USER)
+  {
+    if (userplotstyle_p)
+      createEnrichment(*userplotstyle_p);
+    return;
+  }
+
+	setDeviceLineWidth(meshLineWidth());
+  GLStateBewarer sb(GL_POLYGON_OFFSET_FILL,true);
+	setDevicePolygonOffset(polygonOffset(),1.0);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	int idx = 0;
+	if (plotStyle() != WIREFRAME)
+	{
+		glPolygonMode(GL_FRONT_AND_BACK, GL_QUADS);
+
+		bool hl = (plotStyle() == HIDDENLINE);
+		if (hl)
+		{
+			RGBA col = backgroundRGBAColor();
+			glColor4d(col.r, col.g, col.b, col.a);
+		}
+		
+		for (unsigned i=0; i!=actualDataC_->cells.size(); ++i)
+		{
+			glBegin(GL_POLYGON);
+			for (unsigned j=0; j!=actualDataC_->cells[i].size(); ++j)
+			{
+				idx = actualDataC_->cells[i][j];
+				setColorFromVertexC(idx, hl);
+				glVertex3d( actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y, actualDataC_->nodes[idx].z );
+				glNormal3d( actualDataC_->normals[idx].x, actualDataC_->normals[idx].y, actualDataC_->normals[idx].z );
+			}
+			glEnd();
+		}
+	}
+
+	if (plotStyle() == FILLEDMESH || plotStyle() == WIREFRAME || plotStyle() == HIDDENLINE)
+	{
+		glColor4d(meshColor().r, meshColor().g, meshColor().b, meshColor().a);
+		{
+			for (unsigned i=0; i!=actualDataC_->cells.size(); ++i)
+			{
+				glBegin(GL_LINE_LOOP);
+				for (unsigned j=0; j!=actualDataC_->cells[i].size(); ++j)
+				{
+					idx = actualDataC_->cells[i][j];
+					glVertex3d( actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y, actualDataC_->nodes[idx].z );
+				}
+				glEnd();
+			}
+		}
+	}
+}
+
+// ci = cell index
+// cv = vertex index in cell ci
+void SurfacePlot::setColorFromVertexC(int node, bool skip)
+{
+	if (skip)
+		return;
+
+	RGBA col = (*datacolor_p)(
+		actualDataC_->nodes[node].x, actualDataC_->nodes[node].y, actualDataC_->nodes[node].z);
+		
+	glColor4d(col.r, col.g, col.b, col.a);
+}
+
+void SurfacePlot::createFloorDataC()
+{
+	switch (floorStyle())
+	{
+	case FLOORDATA:
+		Data2FloorC();
+		break;
+	case FLOORISO:
+		Isolines2FloorC();
+		break;
+	default:
+		break;
+	}
+}
+
+void SurfacePlot::Data2FloorC()
+{	
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+	
+	double zshift = actualDataC_->hull().minVertex.z;
+	int idx;
+
+	for (unsigned i = 0; i!=actualDataC_->cells.size(); ++i)
+	{
+		glBegin(GL_POLYGON);
+		for (unsigned j=0; j!=actualDataC_->cells[i].size(); ++j)
+		{
+			idx = actualDataC_->cells[i][j];
+			setColorFromVertexC(idx);
+			glVertex3d( actualDataC_->nodes[idx].x, actualDataC_->nodes[idx].y, zshift );
+		}
+		glEnd();
+	}
+}
+
+void SurfacePlot::Isolines2FloorC()
+{
+	if (isolines() <= 0 || actualData_p->empty())
+		return;
+
+	double step = (actualData_p->hull().maxVertex.z - actualData_p->hull().minVertex.z) / isolines();		
+
+	RGBA col;
+
+	double zshift = actualData_p->hull().minVertex.z;
+		
+	TripleField nodes;
+	TripleField intersection;
+	
+	double lambda = 0;
+	
+	GLStateBewarer sb2(GL_LINE_SMOOTH, false);
+
+	for (int k = 0; k != isolines(); ++k) 
+	{
+		double val = zshift + k * step;		
+				
+		for (unsigned i=0; i!=actualDataC_->cells.size(); ++i)
+		{
+			nodes.clear();
+			unsigned cellnodes = actualDataC_->cells[i].size();
+			for (unsigned j=0; j!=cellnodes; ++j)
+			{
+				nodes.push_back(actualDataC_->nodes[actualDataC_->cells[i][j]]);
+			}
+			
+			double diff = 0;
+			for (unsigned m = 0; m!=cellnodes; ++m)
+			{
+				unsigned mm = (m+1)%cellnodes;
+				if ((val>=nodes[m].z && val<=nodes[mm].z) || (val>=nodes[mm].z && val<=nodes[m].z))
+				{
+					diff = nodes[mm].z - nodes[m].z;
+					
+					if (isPracticallyZero(diff)) // degenerated
+					{
+						intersection.push_back(nodes[m]);
+						intersection.push_back(nodes[mm]);
+						continue;
+					}
+					
+					lambda =  (val - nodes[m].z) / diff;
+					intersection.push_back(Triple(nodes[m].x + lambda * (nodes[mm].x-nodes[m].x), nodes[m].y + lambda * (nodes[mm].y-nodes[m].y), val));
+				}
+			}
+
+			if (!intersection.empty())
+			{
+				col = (*datacolor_p)(nodes[0].x,nodes[0].y,nodes[0].z);
+  			glColor4d(col.r, col.g, col.b, col.a);
+				if (intersection.size()>2)
+				{
+					glBegin(GL_LINE_STRIP);
+					for (unsigned dd = 0; dd!=intersection.size(); ++dd)
+					{
+						glVertex3d(intersection[dd].x, intersection[dd].y, zshift);
+					}
+					glEnd();
+					glBegin(GL_POINTS);
+						glVertex3d(intersection[0].x,intersection[0].y,zshift);
+					glEnd();
+				}
+				else if (intersection.size() == 2)
+				{
+					glBegin(GL_LINES);
+						glVertex3d(intersection[0].x,intersection[0].y,zshift);
+						glVertex3d(intersection[1].x,intersection[1].y,zshift);
+						
+						// small pixel gap problem (see OpenGL spec.)
+						glVertex3d(intersection[1].x,intersection[1].y,zshift);
+						glVertex3d(intersection[0].x,intersection[0].y,zshift);
+					glEnd();
+				}
+				
+				intersection.clear();
+			}
+		}
+	}
+}
+
+void SurfacePlot::createNormalsC()
+{
+	if (!normals() || actualData_p->empty())
+		return;
+
+	if (actualDataC_->nodes.size() != actualDataC_->normals.size())
+		return;
+  Arrow arrow;
+  arrow.setQuality(normalQuality());
+
+	Triple basev, topv, norm;	
+		
+	double diag = (actualData_p->hull().maxVertex-actualData_p->hull().minVertex).length() * normalLength();
+
+  RGBA col;
+  arrow.assign(*this);
+  arrow.drawBegin();
+	for (unsigned i = 0; i != actualDataC_->normals.size(); ++i) 
+	{
+		basev = actualDataC_->nodes[i];
+		topv = basev + actualDataC_->normals[i];
+		
+			norm = topv-basev;
+			norm.normalize();
+			norm	*= diag;
+
+      arrow.setTop(basev+norm);
+      arrow.setColor((*datacolor_p)(basev.x,basev.y,basev.z));
+      arrow.draw(basev);
+	}
+  arrow.drawEnd();
+}
+
+/*! 
+	Convert user (non-rectangular) mesh based data to internal structure.
+	See also Qwt3D::TripleField and Qwt3D::CellField
+*/
+bool SurfacePlot::loadFromData(TripleField const& data, CellField const& poly)
+{	
+	actualDataG_->clear();
+  actualData_p = actualDataC_;
+		
+	actualDataC_->nodes = data;
+	actualDataC_->cells = poly;
+	actualDataC_->normals = TripleField(actualDataC_->nodes.size());
+
+	unsigned i;
+
+//  normals for the moment
+	Triple n, u, v;
+	for ( i = 0; i < poly.size(); ++i) 
+	{
+		if (poly[i].size() < 3)
+			n = Triple(0,0,0);
+		else
+		{
+			for (unsigned j = 0; j < poly[i].size(); ++j) 
+			{
+				unsigned jj = (j+1) % poly[i].size(); 
+				unsigned pjj = (j) ? j-1 : poly[i].size()-1;
+				u = actualDataC_->nodes[poly[i][jj]]-actualDataC_->nodes[poly[i][j]];		
+				v = actualDataC_->nodes[poly[i][pjj]]-actualDataC_->nodes[poly[i][j]];
+				n = normalizedcross(u,v);
+				actualDataC_->normals[poly[i][j]] += n;
+			}
+		}
+	}
+	for ( i = 0; i != actualDataC_->normals.size(); ++i) 
+	{
+		actualDataC_->normals[i].normalize();
+	}  
+	
+	ParallelEpiped hull(Triple(DBL_MAX,DBL_MAX,DBL_MAX),Triple(-DBL_MAX,-DBL_MAX,-DBL_MAX));
+
+	for (i = 0; i!=data.size(); ++i)
+	{
+		if (data[i].x < hull.minVertex.x)
+			hull.minVertex.x = data[i].x;
+		if (data[i].y < hull.minVertex.y)
+			hull.minVertex.y = data[i].y;
+		if (data[i].z < hull.minVertex.z)
+			hull.minVertex.z = data[i].z;
+		
+		if (data[i].x > hull.maxVertex.x)
+			hull.maxVertex.x = data[i].x;
+		if (data[i].y > hull.maxVertex.y)
+			hull.maxVertex.y = data[i].y;
+		if (data[i].z > hull.maxVertex.z)
+			hull.maxVertex.z = data[i].z;
+	}
+
+	actualDataC_->setHull(hull);
+
+	updateData();
+	updateNormals();
+	createCoordinateSystem();
+
+	return true;
+}	
+
+
diff --git a/src/qwt3d_mousekeyboard.cpp b/src/qwt3d_mousekeyboard.cpp
new file mode 100644
index 0000000..7f33d42
--- /dev/null
+++ b/src/qwt3d_mousekeyboard.cpp
@@ -0,0 +1,387 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4305 )
+#pragma warning ( disable : 4786 )
+#endif
+
+#include "qwt3d_plot.h"
+
+using namespace std;
+using namespace Qwt3D;
+
+
+/**
+	Standard mouse button Function. Prepares the call to mouseMoveEvent
+	\see mouseMoveEvent()
+*/
+void Plot3D::mousePressEvent( QMouseEvent *e )
+{
+	lastMouseMovePosition_ = e->pos();
+	mpressed_ = true;
+}
+
+/**
+	Standard mouse button Function. Completes the call to mouseMoveEvent
+	\see mouseMoveEvent()
+*/
+void Plot3D::mouseReleaseEvent( QMouseEvent* )
+{
+	mpressed_ = false;
+}
+
+/**
+	Standard mouse button Function
+	\see assignMouse()
+*/
+void Plot3D::mouseMoveEvent( QMouseEvent *e )
+{
+	if (!mpressed_ || !mouseEnabled())
+  {
+    e->ignore();
+		return;
+  }
+	
+#if QT_VERSION < 0x040000
+	MouseState bstate = e->state();
+#else
+  MouseState bstate(e->buttons(),e->modifiers());
+#endif
+
+	QPoint diff = e->pos() - lastMouseMovePosition_;
+
+	setRotationMouse(bstate, 3, diff);	
+	setScaleMouse(bstate, 5, diff);	
+	setShiftMouse(bstate, 2, diff);	
+		
+	lastMouseMovePosition_ = e->pos();
+}
+
+void Plot3D::setRotationMouse(MouseState bstate, double accel, QPoint diff)
+{
+	// Rotation
+	double w = max(1,width());
+	double h = max(1,height());
+		
+	double relx = accel*360 * diff.x() / w; 
+	double relyz = accel*360 * diff.y() / h; 
+	
+	double new_xrot = xRotation();
+	double new_yrot = yRotation();
+	double new_zrot = zRotation();
+	
+	if ( bstate == xrot_mstate_ )
+		new_xrot = round(xRotation() + relyz) % 360; 
+	if ( bstate == yrot_mstate_ )
+		new_yrot = round(yRotation() + relx) % 360; 
+	if ( bstate == zrot_mstate_ )
+		new_zrot = round(zRotation() + relx) % 360; 
+		
+	setRotation(new_xrot, new_yrot, new_zrot); 
+}
+
+void Plot3D::setScaleMouse(MouseState bstate, double accel, QPoint diff)
+{
+	// Scale
+		double w = max(1,width());
+		double h = max(1,height());
+
+		double relx = diff.x() * accel / w; relx = exp(relx) - 1;
+		double relyz = diff.y() * accel / h; relyz = exp(relyz) - 1; 
+
+		double new_xscale = xScale();
+		double new_yscale = yScale();
+		double new_zscale = zScale();
+
+		if ( bstate == xscale_mstate_)
+			new_xscale = max(0.0,xScale() + relx);
+		if ( bstate == yscale_mstate_)
+			new_yscale = max(0.0,yScale() - relyz);
+		if ( bstate == zscale_mstate_)
+			new_zscale = max(0.0,zScale() - relyz);
+
+		setScale(new_xscale, new_yscale, new_zscale); 
+
+		if ( bstate == zoom_mstate_)
+			setZoom(max(0.0,zoom() - relyz));
+}
+
+void Plot3D::setShiftMouse(MouseState bstate, double accel, QPoint diff)
+{
+	// Shift
+	double w = max(1,width());
+	double h = max(1,height());
+
+	double relx = diff.x() * accel / w; 
+	double relyz = diff.y() * accel / h;
+
+	double new_xshift = xViewportShift();
+	double new_yshift = yViewportShift();
+
+	if ( bstate == xshift_mstate_)
+		new_xshift = xViewportShift() + relx;
+	if ( bstate == yshift_mstate_)
+		new_yshift = yViewportShift() - relyz;
+
+	setViewportShift(new_xshift, new_yshift); 
+}
+
+/**
+	Standard wheel Function - zoom (wheel only) or z-scale (shift+wheel)
+*/
+void Plot3D::wheelEvent( QWheelEvent *e )
+{
+	if (!mouseEnabled())
+		return;
+	
+	double accel = 0.05;
+	
+	double step =  accel * e->delta() / WHEEL_DELTA ;
+	step = exp(step)-1;
+
+#if QT_VERSION < 0x040000
+	if ( e->state() & Qt::ShiftButton )
+#else
+	if ( e->modifiers() & Qt::ShiftModifier )
+#endif
+		setScale(xScale(),yScale(), max(0.0,zScale() + step));
+	else
+		setZoom(max(0.0,zoom() + step ));
+}
+
+/**
+	Sets the key/mousebutton combination for data/coordinatesystem moves inside the widget\n\n
+	default behaviour:\n
+
+	\verbatim
+	rotate around x axis: Qt::LeftButton 
+	rotate around y axis: Qt::LeftButton | Qt::ShiftButton
+	rotate around z axis: Qt::LeftButton 
+	scale x:              Qt::LeftButton | Qt::AltButton 
+	scale y:              Qt::LeftButton | Qt::AltButton 
+	scale z:              Qt::LeftButton | Qt::AltButton | Qt::ShiftButton
+	zoom:                 Qt::LeftButton | Qt::AltButton | Qt::ControlButton
+	shifting along x:     Qt::LeftButton | Qt::ControlButton 
+	shifting along y:     Qt::LeftButton | Qt::ControlButton
+	\endverbatim
+
+	mouseMoveEvent() evaluates this function - if overridden, their usefulness becomes somehow limited
+*/
+void Plot3D::assignMouse(MouseState xrot, MouseState yrot, MouseState zrot,
+											 MouseState xscale, MouseState yscale, MouseState zscale,
+											 MouseState zoom, MouseState xshift, MouseState yshift)
+{
+	xrot_mstate_   = 	xrot;  
+  yrot_mstate_   =  yrot;  
+  zrot_mstate_   =  zrot;  
+  xscale_mstate_ =  xscale;
+  yscale_mstate_ =  yscale;
+  zscale_mstate_ =  zscale;
+  zoom_mstate_   =  zoom;  
+  xshift_mstate_ =  xshift;
+  yshift_mstate_ =  yshift;
+}
+
+/** 
+The function has no effect if you derive from Plot3D and overrides the mouse Function too careless.
+In this case check first against mouseEnabled() in your version of mouseMoveEvent() and wheelEvent().
+A more fine grained input control can be achieved by combining assignMouse() with enableMouse(). 
+*/
+void Plot3D::enableMouse(bool val) {mouse_input_enabled_ = val;}
+
+/** 
+\see enableMouse()
+*/
+void Plot3D::disableMouse(bool val) {mouse_input_enabled_ = !val;}
+bool Plot3D::mouseEnabled() const {return mouse_input_enabled_;}
+
+
+
+
+void Plot3D::keyPressEvent( QKeyEvent *e )
+{
+	if (!keyboardEnabled())
+  {
+    e->ignore();
+    return;
+  }	
+
+#if QT_VERSION < 0x040000
+  int bstate = e->state() & Qt::KeyButtonMask; // filter kbd modifier only
+  KeyboardState keyseq = bstate + e->key();
+#else
+  KeyboardState keyseq(e->key(), e->modifiers());
+#endif
+
+	setRotationKeyboard(keyseq, kbd_rot_speed_);	
+	setScaleKeyboard(keyseq, kbd_scale_speed_);	
+	setShiftKeyboard(keyseq, kbd_shift_speed_);	
+}
+
+void Plot3D::setRotationKeyboard(KeyboardState kseq, double speed)
+{
+	// Rotation
+	double w = max(1,width());
+	double h = max(1,height());
+		
+	double relx = speed*360 / w; 
+	double relyz = speed*360 / h; 
+	
+	double new_xrot = xRotation();
+	double new_yrot = yRotation();
+	double new_zrot = zRotation();
+	
+	if ( kseq == xrot_kstate_[0] )
+		new_xrot = round(xRotation() + relyz) % 360; 
+	if ( kseq == xrot_kstate_[1] )
+		new_xrot = round(xRotation() - relyz) % 360; 
+	if ( kseq == yrot_kstate_[0] )
+		new_yrot = round(yRotation() + relx) % 360; 
+	if ( kseq == yrot_kstate_[1] )
+		new_yrot = round(yRotation() - relx) % 360; 
+	if ( kseq == zrot_kstate_[0] )
+		new_zrot = round(zRotation() + relx) % 360; 
+	if ( kseq == zrot_kstate_[1] )
+		new_zrot = round(zRotation() - relx) % 360; 
+		
+	setRotation(new_xrot, new_yrot, new_zrot); 
+}
+
+void Plot3D::setScaleKeyboard(KeyboardState kseq, double speed)
+{
+	// Scale
+		double w = max(1,width());
+		double h = max(1,height());
+
+		double relx = speed / w; relx = exp(relx) - 1;
+		double relyz = speed / h; relyz = exp(relyz) - 1; 
+
+		double new_xscale = xScale();
+		double new_yscale = yScale();
+		double new_zscale = zScale();
+
+		if ( kseq == xscale_kstate_[0])
+			new_xscale = max(0.0,xScale() + relx);
+		if ( kseq == xscale_kstate_[1])
+			new_xscale = max(0.0,xScale() - relx);
+		if ( kseq == yscale_kstate_[0])
+			new_yscale = max(0.0,yScale() - relyz);
+		if ( kseq == yscale_kstate_[1])
+			new_yscale = max(0.0,yScale() + relyz);
+		if ( kseq == zscale_kstate_[0])
+			new_zscale = max(0.0,zScale() - relyz);
+		if ( kseq == zscale_kstate_[1])
+			new_zscale = max(0.0,zScale() + relyz);
+
+		setScale(new_xscale, new_yscale, new_zscale); 
+
+		if ( kseq == zoom_kstate_[0])
+			setZoom(max(0.0,zoom() - relyz));
+		if ( kseq == zoom_kstate_[1])
+			setZoom(max(0.0,zoom() + relyz));
+}
+
+void Plot3D::setShiftKeyboard(KeyboardState kseq, double speed)
+{
+	// Shift
+	double w = max(1,width());
+	double h = max(1,height());
+
+	double relx = speed / w; 
+	double relyz = speed / h;
+
+	double new_xshift = xViewportShift();
+	double new_yshift = yViewportShift();
+
+	if ( kseq == xshift_kstate_[0])
+		new_xshift = xViewportShift() + relx;
+	if ( kseq == xshift_kstate_[1])
+		new_xshift = xViewportShift() - relx;
+	if ( kseq == yshift_kstate_[0])
+		new_yshift = yViewportShift() - relyz;
+	if ( kseq == yshift_kstate_[1])
+		new_yshift = yViewportShift() + relyz;
+
+	setViewportShift(new_xshift, new_yshift); 
+}
+
+/**
+	Sets the keybutton combination for data/coordinatesystem moves inside the widget\n\n
+	default behaviour:\n
+
+	\verbatim
+	rotate around x axis: [Key_Down, Key_Up] 
+	rotate around y axis: SHIFT+[Key_Right, Key_Left]
+	rotate around z axis: [Key_Right, Key_Left] 
+	scale x:              ALT+[Key_Right, Key_Left] 
+	scale y:              ALT+[Key_Up, Key_Down] 
+	scale z:              ALT+SHIFT[Key_Down, Key_Up] 
+	zoom:                 ALT+CTRL+[Key_Down, Key_Up]
+	shifting along x:     CTRL+[Key_Right, Key_Left] 
+	shifting along z:     CTRL+[Key_Down, Key_Up]
+	\endverbatim
+*/
+void Plot3D::assignKeyboard(
+       KeyboardState xrot_n, KeyboardState xrot_p
+      ,KeyboardState yrot_n, KeyboardState yrot_p
+      ,KeyboardState zrot_n, KeyboardState zrot_p
+			,KeyboardState xscale_n, KeyboardState xscale_p 
+      ,KeyboardState yscale_n, KeyboardState yscale_p
+      ,KeyboardState zscale_n, KeyboardState zscale_p
+			,KeyboardState zoom_n, KeyboardState zoom_p
+      ,KeyboardState xshift_n, KeyboardState xshift_p
+      ,KeyboardState yshift_n, KeyboardState yshift_p
+      )
+{
+	xrot_kstate_[0]   =  xrot_n;  
+  yrot_kstate_[0]   =  yrot_n;  
+  zrot_kstate_[0]   =  zrot_n;  
+	xrot_kstate_[1]   =  xrot_p;  
+  yrot_kstate_[1]   =  yrot_p;  
+  zrot_kstate_[1]   =  zrot_p;  
+  
+  xscale_kstate_[0] =  xscale_n;
+  yscale_kstate_[0] =  yscale_n;
+  zscale_kstate_[0] =  zscale_n;
+  xscale_kstate_[1] =  xscale_p;
+  yscale_kstate_[1] =  yscale_p;
+  zscale_kstate_[1] =  zscale_p;
+
+  zoom_kstate_[0]   =  zoom_n;  
+  xshift_kstate_[0] =  xshift_n;
+  yshift_kstate_[0] =  yshift_n;
+  zoom_kstate_[1]   =  zoom_p;  
+  xshift_kstate_[1] =  xshift_p;
+  yshift_kstate_[1] =  yshift_p;
+}
+
+/** 
+The function has no effect if you derive from Plot3D and overrides the keyboard Functions too careless.
+In this case check first against keyboardEnabled() in your version of keyPressEvent()
+A more fine grained input control can be achieved by combining assignKeyboard() with enableKeyboard(). 
+*/
+void Plot3D::enableKeyboard(bool val) {kbd_input_enabled_ = val;}
+
+/** 
+\see enableKeyboard()
+*/
+void Plot3D::disableKeyboard(bool val) {kbd_input_enabled_ = !val;}
+bool Plot3D::keyboardEnabled() const {return kbd_input_enabled_;}
+
+/**
+Values < 0 are ignored. Default is (3,5,5)
+*/
+void Plot3D::setKeySpeed(double rot, double scale, double shift)
+{
+  if (rot > 0)
+    kbd_rot_speed_ = rot;
+  if (scale > 0)
+    kbd_scale_speed_ = scale;
+  if (shift > 0)
+    kbd_shift_speed_ = shift;
+}
+
+void Plot3D::keySpeed(double& rot, double& scale, double& shift) const
+{
+  rot = kbd_rot_speed_;
+  scale = kbd_scale_speed_;
+  shift = kbd_shift_speed_;
+}
diff --git a/src/qwt3d_movements.cpp b/src/qwt3d_movements.cpp
new file mode 100644
index 0000000..e8bb48b
--- /dev/null
+++ b/src/qwt3d_movements.cpp
@@ -0,0 +1,106 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4305 )
+#pragma warning ( disable : 4786 )
+#endif
+
+#include <float.h>
+#include "qwt3d_plot.h"
+
+using namespace Qwt3D;
+
+
+/**
+  Set the rotation angle of the object. If you look along the respective axis towards ascending values,
+	the rotation is performed in mathematical \e negative sense 
+	\param xVal angle in \e degree to rotate around the X axis
+	\param yVal angle in \e degree to rotate around the Y axis
+	\param zVal angle in \e degree to rotate around the Z axis
+*/
+void Plot3D::setRotation( double xVal, double yVal, double zVal )
+{
+  if (xRot_ == xVal && yRot_ == yVal && zRot_ == zVal)
+		return;
+	
+	xRot_ = xVal;
+	yRot_ = yVal;
+	zRot_ = zVal;
+  
+	updateGL();
+	emit rotationChanged(xVal, yVal, zVal);
+}
+
+/**
+  Set the shift in object (world) coordinates.
+	\param xVal shift along (world) X axis
+	\param yVal shift along (world) Y axis
+	\param zVal shift along (world) Z axis
+	\see setViewportShift()
+*/
+void Plot3D::setShift( double xVal, double yVal, double zVal )
+{
+  if (xShift_ == xVal && yShift_ == yVal && zShift_ == zVal)
+		return;
+	
+	xShift_ = xVal;
+	yShift_ = yVal;
+	zShift_ = zVal;
+	updateGL();
+	emit shiftChanged(xVal, yVal, zVal);
+}
+
+/**
+  Performs shifting along screen axes. 
+  The shift moves points inside a sphere, 
+  which encloses the unscaled and unzoomed data
+	by multiples of the spheres diameter
+	
+	\param xVal shift along (view) X axis
+	\param yVal shift along (view) Y axis
+	\see setShift()
+*/
+void Plot3D::setViewportShift( double xVal, double yVal )
+{
+  if (xVPShift_ == xVal && yVPShift_ == yVal)
+		return;
+	
+  xVPShift_ = xVal;
+	yVPShift_ = yVal;
+		
+	updateGL();
+	emit vieportShiftChanged(xVPShift_, yVPShift_);
+}
+
+/**
+  Set the scale in object (world) coordinates.
+	\param xVal scaling for X values
+	\param yVal scaling for Y values
+	\param zVal scaling for Z values 
+
+	A respective value of 1 represents no scaling;
+*/
+void Plot3D::setScale( double xVal, double yVal, double zVal )
+{
+  if (xScale_ == xVal && yScale_ == yVal && zScale_ == zVal)
+		return;
+	
+	xScale_ = (xVal < DBL_EPSILON ) ? DBL_EPSILON : xVal;
+	yScale_ = (yVal < DBL_EPSILON ) ? DBL_EPSILON : yVal;
+	zScale_ = (zVal < DBL_EPSILON ) ? DBL_EPSILON : zVal;
+
+	updateGL();
+	emit scaleChanged(xVal, yVal, zVal);
+}
+
+/**
+  Set the (zoom in addition to scale).
+	\param val zoom value (value == 1 indicates no zooming)
+*/
+void Plot3D::setZoom( double val )
+{
+  if (zoom_ == val)
+		return;
+
+	zoom_ = (val < DBL_EPSILON ) ? DBL_EPSILON : val;
+ 	updateGL();
+	emit zoomChanged(val);
+}
diff --git a/src/qwt3d_parametricsurface.cpp b/src/qwt3d_parametricsurface.cpp
new file mode 100644
index 0000000..c53260b
--- /dev/null
+++ b/src/qwt3d_parametricsurface.cpp
@@ -0,0 +1,104 @@
+#include "qwt3d_parametricsurface.h"
+#include "qwt3d_surfaceplot.h"
+
+using namespace Qwt3D;
+
+ParametricSurface::ParametricSurface()
+:GridMapping()
+{
+}
+
+ParametricSurface::ParametricSurface(SurfacePlot& pw)
+:GridMapping()
+{
+	plotwidget_p = &pw;
+  uperiodic_ = false;
+  vperiodic_ = false;
+}
+
+ParametricSurface::ParametricSurface(SurfacePlot* pw)
+:GridMapping()
+{
+	plotwidget_p = pw;
+  uperiodic_ = false;
+  vperiodic_ = false;
+}
+
+void ParametricSurface::setPeriodic(bool u, bool v)
+{
+  uperiodic_ = u;
+  vperiodic_ = v;
+}
+
+void ParametricSurface::assign(SurfacePlot& plotWidget)
+{
+	if (&plotWidget != plotwidget_p)
+		plotwidget_p = &plotWidget;
+}
+
+void ParametricSurface::assign(SurfacePlot* plotWidget)
+{
+	if (plotWidget != plotwidget_p)
+		plotwidget_p = plotWidget;
+}
+
+/**
+For plotWidget != 0 the function permanently assigns her argument (In fact, assign(plotWidget) is called)
+*/
+bool ParametricSurface::create()
+{
+	if ((umesh_p<=2) || (vmesh_p<=2) || !plotwidget_p)
+		return false;
+	
+	/* allocate some space for the mesh */
+ 	Triple** data         = new Triple* [umesh_p] ;
+
+	unsigned i,j;
+	for ( i = 0; i < umesh_p; i++) 
+	{
+		data[i]         = new Triple [vmesh_p];
+	}
+	
+	/* get the data */
+
+	double du = (maxu_p - minu_p) / (umesh_p - 1);
+	double dv = (maxv_p - minv_p) / (vmesh_p - 1);
+	
+  for (i = 0; i < umesh_p; ++i) 
+	{
+		for (j = 0; j < vmesh_p; ++j) 
+		{
+			data[i][j] = operator()(minu_p + i*du, minv_p + j*dv);
+			
+			if (data[i][j].x > range_p.maxVertex.x)
+				data[i][j].x = range_p.maxVertex.x;
+			else if (data[i][j].y > range_p.maxVertex.y)
+				data[i][j].y = range_p.maxVertex.y;
+			else if (data[i][j].z > range_p.maxVertex.z)
+				data[i][j].z = range_p.maxVertex.z;
+			else if (data[i][j].x < range_p.minVertex.x)
+				data[i][j].x = range_p.minVertex.x;
+			else if (data[i][j].y < range_p.minVertex.y)
+				data[i][j].y = range_p.minVertex.y;
+			else if (data[i][j].z < range_p.minVertex.z)
+				data[i][j].z = range_p.minVertex.z;
+		}
+	}
+
+	((SurfacePlot*)plotwidget_p)->loadFromData(data, umesh_p, vmesh_p, uperiodic_, vperiodic_);
+
+	for ( i = 0; i < umesh_p; i++) 
+	{
+		delete [] data[i];
+	}
+
+	delete [] data;
+
+	return true;
+}
+
+bool ParametricSurface::create(SurfacePlot& pl)
+{
+  assign(pl);
+  return create();
+}
diff --git a/src/qwt3d_plot.cpp b/src/qwt3d_plot.cpp
new file mode 100644
index 0000000..46ead68
--- /dev/null
+++ b/src/qwt3d_plot.cpp
@@ -0,0 +1,498 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4305 )
+#pragma warning ( disable : 4786 )
+#endif
+
+#include "qwt3d_plot.h"
+#include "qwt3d_enrichment.h"
+
+
+using namespace Qwt3D;
+	
+/*!
+  This should be the first call in your derived classes constructors.  
+*/
+#if QT_VERSION < 0x040000
+Plot3D::Plot3D( QWidget* parent, const char* name )
+    : QGLWidget( parent, name )
+#else
+Plot3D::Plot3D( QWidget * parent, const QGLWidget * shareWidget)
+    : QGLWidget( parent, shareWidget) 
+#endif
+{  
+  initializedGL_ = false;
+  renderpixmaprequest_ = false;
+  xRot_ = yRot_ = zRot_ = 0.0;		// default object rotation
+  
+	xShift_ = yShift_ = zShift_ = xVPShift_ = yVPShift_ = 0.0;
+	xScale_ = yScale_ = zScale_ = 1.0;
+	zoom_ = 1;
+	ortho_ = true;
+	plotstyle_ = FILLEDMESH;
+  userplotstyle_p = 0;
+	shading_ = GOURAUD;
+	floorstyle_ = NOFLOOR;
+	isolines_ = 10;
+	displaylegend_ = false;
+	smoothdatamesh_p = false;
+  actualData_p = 0;
+
+	lastMouseMovePosition_ = QPoint(0,0);
+	mpressed_ = false;
+	mouse_input_enabled_ = true;
+
+	setPolygonOffset(0.5);
+	setMeshColor(RGBA(0.0,0.0,0.0));
+	setMeshLineWidth(1);
+	setBackgroundColor(RGBA(1.0,1.0,1.0,1.0));
+
+	displaylists_p = std::vector<GLuint>(DisplayListSize);
+	for (unsigned k=0; k!=displaylists_p.size(); ++k)
+	{
+		displaylists_p[k] = 0;
+	}
+
+	datacolor_p = new StandardColor(this, 100);
+	title_.setFont("Courier", 16, QFont::Bold);
+	title_.setString("");
+
+	setTitlePosition(0.95);
+	
+  kbd_input_enabled_ = true;
+
+#if QT_VERSION < 0x040000
+  setFocusPolicy(QWidget::StrongFocus);
+  assignMouse(Qt::LeftButton, 
+							Qt::LeftButton | Qt::ShiftButton,
+							Qt::LeftButton, 
+							Qt::LeftButton | Qt::AltButton, 
+							Qt::LeftButton | Qt::AltButton, 
+							Qt::LeftButton | Qt::AltButton | Qt::ShiftButton,
+							Qt::LeftButton | Qt::AltButton | Qt::ControlButton,
+							Qt::LeftButton | Qt::ControlButton, 
+							Qt::LeftButton | Qt::ControlButton);
+
+
+  assignKeyboard(Qt::Key_Down, Qt::Key_Up,
+    Qt::ShiftButton + Qt::Key_Right, Qt::ShiftButton + Qt::Key_Left,
+    Qt::Key_Right, Qt::Key_Left,
+    Qt::AltButton + Qt::Key_Right, Qt::AltButton + Qt::Key_Left,
+    Qt::AltButton + Qt::Key_Down, Qt::AltButton + Qt::Key_Up,
+    Qt::AltButton + Qt::ShiftButton + Qt::Key_Down, Qt::AltButton + Qt::ShiftButton + Qt::Key_Up,
+    Qt::AltButton + Qt::ControlButton + Qt::Key_Down, Qt::AltButton + Qt::ControlButton + Qt::Key_Up,
+    Qt::ControlButton + Qt::Key_Right, Qt::ControlButton + Qt::Key_Left,
+    Qt::ControlButton + Qt::Key_Down, Qt::ControlButton + Qt::Key_Up
+   );
+#else
+  setFocusPolicy(Qt::StrongFocus);
+  assignMouse(Qt::LeftButton, 
+							MouseState(Qt::LeftButton, Qt::ShiftModifier),
+							Qt::LeftButton, 
+							MouseState(Qt::LeftButton, Qt::AltModifier), 
+							MouseState(Qt::LeftButton, Qt::AltModifier), 
+							MouseState(Qt::LeftButton, Qt::AltModifier | Qt::ShiftModifier),
+							MouseState(Qt::LeftButton, Qt::AltModifier | Qt::ControlModifier),
+							MouseState(Qt::LeftButton, Qt::ControlModifier), 
+							MouseState(Qt::LeftButton, Qt::ControlModifier)
+              );
+
+
+  assignKeyboard(Qt::Key_Down, Qt::Key_Up,
+    KeyboardState(Qt::Key_Right, Qt::ShiftModifier), KeyboardState(Qt::Key_Left, Qt::ShiftModifier),
+    Qt::Key_Right, Qt::Key_Left,
+    KeyboardState(Qt::Key_Right, Qt::AltModifier), KeyboardState(Qt::Key_Left, Qt::AltModifier),
+    KeyboardState(Qt::Key_Down, Qt::AltModifier), KeyboardState(Qt::Key_Up, Qt::AltModifier),
+    KeyboardState(Qt::Key_Down, Qt::AltModifier|Qt::ShiftModifier), KeyboardState(Qt::Key_Up, Qt::AltModifier|Qt::ShiftModifier),
+    KeyboardState(Qt::Key_Down, Qt::AltModifier|Qt::ControlModifier), KeyboardState(Qt::Key_Up, Qt::AltModifier|Qt::ControlModifier),
+    KeyboardState(Qt::Key_Right, Qt::ControlModifier), KeyboardState(Qt::Key_Left, Qt::ControlModifier),
+    KeyboardState(Qt::Key_Down, Qt::ControlModifier), KeyboardState(Qt::Key_Up, Qt::ControlModifier)
+   );
+#endif
+  setKeySpeed(3,5,5);
+
+	legend_.setLimits(0, 100);
+	legend_.setMajors(10);
+	legend_.setMinors(2);
+	legend_.setOrientation(ColorLegend::BottomTop, ColorLegend::Left);
+
+  lighting_enabled_ = false;
+  disableLighting();
+  lights_ = std::vector<Light>(8);
+}
+
+/*!
+  Release allocated resources
+*/
+
+Plot3D::~Plot3D()
+{
+	makeCurrent();
+	SaveGlDeleteLists( displaylists_p[0], displaylists_p.size() );
+	datacolor_p->destroy();
+  delete userplotstyle_p;
+  for (ELIT it = elist_p.begin(); it!=elist_p.end(); ++it)
+    delete (*it);
+
+  elist_p.clear();
+}
+
+
+/*!
+  Set up the OpenGL rendering state
+*/
+void Plot3D::initializeGL()
+{
+  glEnable( GL_BLEND );
+  glEnable(GL_DEPTH_TEST);
+	glShadeModel(GL_SMOOTH);
+	
+  // Set up the lights
+
+  disableLighting();
+	
+  GLfloat whiteAmb[4] = {1.0, 1.0, 1.0, 1.0};
+    
+  setLightShift(0, 0, 3000);
+  glEnable(GL_COLOR_MATERIAL);
+
+	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
+  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, whiteAmb);
+
+  setMaterialComponent(GL_DIFFUSE, 1.0);
+  setMaterialComponent(GL_SPECULAR, 0.3);
+  setMaterialComponent(GL_SHININESS, 5.0);
+  setLightComponent(GL_DIFFUSE, 1.0);
+  setLightComponent(GL_SPECULAR, 1.0);
+
+  initializedGL_ = true;	
+  if (renderpixmaprequest_)
+  {
+    updateData();
+    renderpixmaprequest_ = false;
+  }
+}
+
+/*!
+  Paint the widgets content.
+*/
+void Plot3D::paintGL()
+{
+	glClearColor(bgcolor_.r, bgcolor_.g, bgcolor_.b, bgcolor_.a);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	
+  glMatrixMode( GL_MODELVIEW );
+	glPushMatrix();
+  applyLights();
+
+  glRotatef( -90, 1.0, 0.0, 0.0 ); 
+  glRotatef( 0.0, 0.0, 1.0, 0.0 ); 
+  glRotatef( 0.0, 0.0, 0.0, 1.0 );
+
+	if (displaylegend_)
+	{		
+		legend_.draw();
+	}
+	title_.setRelPosition(titlerel_, titleanchor_);
+	title_.draw();
+	
+	Triple beg = coordinates_p.first();
+	Triple end = coordinates_p.second();
+	
+	Triple center = beg + (end-beg) / 2;
+	double radius = (center-beg).length();
+	
+	glLoadIdentity();
+
+  glRotatef( xRot_-90, 1.0, 0.0, 0.0 ); 
+  glRotatef( yRot_, 0.0, 1.0, 0.0 ); 
+  glRotatef( zRot_, 0.0, 0.0, 1.0 );
+
+	glScalef( zoom_ * xScale_, zoom_ * yScale_, zoom_ * zScale_ );
+	
+	glTranslatef(xShift_-center.x, yShift_-center.y, zShift_-center.z);
+  
+  glMatrixMode( GL_PROJECTION );
+  glLoadIdentity();
+
+	if (beg != end)
+	{		
+		if (ortho_)
+    {	
+      glOrtho( -radius, +radius, -radius, +radius, 0, 40 * radius);
+    }
+    else
+    {	
+      glFrustum( -radius, +radius, -radius, +radius, 5 * radius, 400 * radius );
+    }
+  }
+	else
+	{
+		if (ortho_)
+			glOrtho( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 );
+		else
+			glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 );
+	}
+
+  glTranslatef( xVPShift_ * 2 * radius , yVPShift_ * 2 * radius , -7 * radius );
+  
+  if (lighting_enabled_)
+    glEnable(GL_NORMALIZE);
+
+  for (unsigned i=0; i!= displaylists_p.size(); ++i)
+	{
+		if (i!=LegendObject)
+			glCallList( displaylists_p[i] );
+	}
+  coordinates_p.draw();
+	
+  if (lighting_enabled_)
+    glDisable(GL_NORMALIZE);
+  
+  glMatrixMode( GL_MODELVIEW );
+  glPopMatrix();
+}
+
+
+/*!
+  Set up the OpenGL view port
+*/
+void Plot3D::resizeGL( int w, int h )
+{
+	glViewport( 0, 0, w, h );
+	paintGL();
+}
+
+/*!
+  Reimplemented from QGLWidget
+*/
+QPixmap Plot3D::renderPixmap(int w/* =0 */, int h/* =0 */, bool useContext/* =false */)
+{
+  renderpixmaprequest_ = true;
+  return QGLWidget::renderPixmap(w,h,useContext);
+}
+
+/*!
+	Create a coordinate system with generating corners beg and end 
+*/
+void Plot3D::createCoordinateSystem( Triple beg, Triple end )
+{
+	if (beg != coordinates_p.first() || end != coordinates_p.second())
+		coordinates_p.init(beg, end);
+}
+
+/*!
+	Create a coordinate system from data
+*/
+void Plot3D::createCoordinateSystem()
+{
+	calculateHull();
+  Triple beg = hull().minVertex; // Irix 6.5 compiler bug
+  Triple end = hull().maxVertex;
+  createCoordinateSystem(beg, end);
+}
+
+/*!
+  Show a color legend
+*/
+void Plot3D::showColorLegend( bool show )
+{
+ 	displaylegend_ = show;
+	if (show)
+    datacolor_p->createVector(legend_.colors);
+	updateGL();
+}
+
+void Plot3D::setMeshColor(RGBA rgba)
+{
+	meshcolor_ = rgba;
+}
+
+void Plot3D::setBackgroundColor(RGBA rgba)
+{
+	bgcolor_ = rgba;
+}
+
+
+/*!
+	assign a new coloring object for the data.
+*/
+void Plot3D::setDataColor( Color* col )
+{
+	Q_ASSERT(datacolor_p);
+
+	datacolor_p->destroy();
+	datacolor_p = col;
+}
+
+/*!
+  Set up ortogonal or perspective mode and updates widget
+*/
+void Plot3D::setOrtho( bool val )
+{
+	if (val == ortho_)
+		return;
+	ortho_ = val;
+	updateGL();
+	
+	emit projectionChanged(val);
+}
+
+/*!
+  Set style of coordinate system
+*/
+void Plot3D::setCoordinateStyle(COORDSTYLE st)
+{
+	coordinates_p.setStyle(st);
+	updateGL();
+}
+
+/*!
+  Set plotstyle for the standard plotting types. An argument of value Qwt3D::USER
+  is ignored.
+*/
+void Plot3D::setPlotStyle( PLOTSTYLE val )
+{
+  if (val == Qwt3D::USER)
+    return;
+  delete userplotstyle_p;
+  userplotstyle_p = 0;
+  plotstyle_ = val;
+}
+
+/*!
+  Set plotstyle to Qwt3D::USER and an associated enrichment object.
+*/
+Qwt3D::Enrichment* Plot3D::setPlotStyle( Qwt3D::Enrichment const& obj )
+{
+  if (&obj == userplotstyle_p)
+    return userplotstyle_p;
+  
+  delete userplotstyle_p;
+  userplotstyle_p = obj.clone();
+  plotstyle_ = Qwt3D::USER;
+  return userplotstyle_p;
+}
+
+/*!
+  Set shading style
+*/
+void Plot3D::setShading( SHADINGSTYLE val )
+{
+	if (val == shading_)
+		return;
+	
+	shading_ = val;
+	
+	switch (shading_)
+	{
+		case FLAT:
+			glShadeModel(GL_FLAT);
+			break;
+		case GOURAUD:
+			glShadeModel(GL_SMOOTH);
+			break;
+		default:
+			break;
+	}
+	updateGL();
+}
+
+/*!
+  Set number of isolines. The lines are equidistant between minimal and maximal Z value
+*/
+void Plot3D::setIsolines(int steps)
+{
+	if (steps < 0)
+		return;
+
+	isolines_ = steps;
+}
+
+/*!
+  Set Polygon offset. The function affects the OpenGL rendering process. 
+	Try different values for surfaces with polygons only and with mesh and polygons
+*/
+void Plot3D::setPolygonOffset( double val )
+{
+	polygonOffset_ = val;
+}
+
+void Plot3D::setMeshLineWidth( double val )
+{
+	Q_ASSERT(val>=0);
+
+	if (val < 0)
+		return;
+	
+	meshLineWidth_ = val;
+}
+
+
+/*!
+Set relative caption position (0.5,0.5) means, the anchor point lies in the center of the screen
+*/
+void Plot3D::setTitlePosition(double rely, double relx, Qwt3D::ANCHOR anchor)
+{
+	titlerel_.y = (rely<0 || rely>1) ? 0.5 : rely;
+	titlerel_.x = (relx<0 || relx>1) ? 0.5 : relx;
+
+	titleanchor_ = anchor;
+}
+
+/*!
+Set caption font
+*/
+void Plot3D::setTitleFont(const QString& family, int pointSize, int weight, bool italic)
+{ 
+	title_.setFont(family, pointSize, weight, italic);
+}
+
+Enrichment* Plot3D::addEnrichment(Enrichment const& e)
+{
+  if ( elist_p.end() == std::find( elist_p.begin(), elist_p.end(), &e ) )
+    elist_p.push_back(e.clone());
+  return elist_p.back();
+}
+
+bool Plot3D::degrade(Enrichment* e)
+{
+	ELIT it = std::find(elist_p.begin(), elist_p.end(), e);
+	
+	if ( it != elist_p.end() )
+	{
+		delete (*it);
+    elist_p.erase(it);
+    return true;
+	}
+  return false;
+}
+
+void Plot3D::createEnrichments()
+{
+  for (ELIT it = elist_p.begin(); it!=elist_p.end(); ++it)
+  {
+    this->createEnrichment(**it);
+  } 
+}
+
+/*!
+  Update OpenGL data representation
+*/
+void Plot3D::updateData()
+{
+	makeCurrent();
+  GLStateBewarer dt(GL_DEPTH_TEST, true);
+	GLStateBewarer ls(GL_LINE_SMOOTH, true);
+
+	calculateHull();	
+
+	SaveGlDeleteLists(displaylists_p[DataObject], 1); // nur Daten
+	
+	displaylists_p[DataObject] = glGenLists(1);
+	glNewList(displaylists_p[DataObject], GL_COMPILE);
+	
+  this->createEnrichments();
+	this->createData();
+		
+	glEndList();
+}
diff --git a/src/qwt3d_scale.cpp b/src/qwt3d_scale.cpp
new file mode 100644
index 0000000..5d0fc91
--- /dev/null
+++ b/src/qwt3d_scale.cpp
@@ -0,0 +1,304 @@
+#include "qwt3d_scale.h"
+
+using namespace Qwt3D;
+
+Scale::Scale() 
+: start_p(0.), stop_p(0.), 
+  majorintervals_p(0), minorintervals_p(0),
+  mstart_p(0.), mstop_p(0.) 
+{
+}
+
+/*! The function maps the double value at tic-position idx to a final
+representation. The default return value is simply the tic values QString 
+representation. Overwrite this function, if you plan to transform the value 
+in some way. See e.g. LogScale::ticLabel.
+\param idx the current major tic index
+\return The QString representation for the value corresponding to a valid index, 
+an empty QString else.
+*/
+QString Scale::ticLabel(unsigned int idx) const
+{
+  if (idx<majors_p.size())
+  {
+    return QString::number(majors_p[idx]);
+  }
+  return QString("");
+}
+
+//! Sets start and stop value for the scale;
+void Scale::setLimits(double start, double stop) 
+{
+  if (start < stop)
+  {
+    start_p = start;
+    stop_p = stop;
+    return;
+  }
+  start_p = stop;
+  stop_p = start;
+}
+
+//! Sets value of first major tic
+void Scale::setMajorLimits(double start, double stop) 
+{
+  if (start < stop)
+  {
+    mstart_p = start;
+    mstop_p = stop;
+    return;
+  }
+  mstart_p = stop;
+  mstop_p = start;
+} 
+
+/*!
+  \param a First major tic after applying autoscaling
+  \param b Last major tic after applying autoscaling
+  \param start Scale begin
+  \param stop Scale end
+  \param ivals Requested number of major intervals
+  \return Number of major intervals after autoscaling\n
+  
+  The default implementation sets a=start, b=stop and returns ivals.
+*/
+int Scale::autoscale(double& a, double& b, double start, double stop, int ivals)
+{
+  a = start;
+  b = stop;
+  return ivals;
+}
+
+/***************************
+*
+* linear scales
+*
+***************************/
+
+
+//! Applies LinearAutoScaler::execute()
+int LinearScale::autoscale(double& a, double& b, double start, double stop, int ivals)
+{
+  return autoscaler_p.execute(a, b, start, stop, ivals);
+}
+
+//! Creates the major and minor vector for the scale
+void LinearScale::calculate()
+{		
+  majors_p.clear();
+	minors_p.clear();
+  
+  double interval = mstop_p-mstart_p;
+
+	double runningval;
+  int i=0;
+
+  // majors
+
+  // first tic
+//  if (mstart_p<start_p || mstop_p>stop_p)
+//    return;  
+    
+  majors_p.push_back(mstart_p);
+  
+  // remaining tics
+  for (i = 1; i <= majorintervals_p; ++i) 
+	{
+		double t = double(i) / majorintervals_p;
+		runningval = mstart_p + t * interval;
+    if (runningval>stop_p)
+      break;
+    if (isPracticallyZero(mstart_p, -t*interval)) // prevent rounding errors near 0
+      runningval = 0.0;
+    majors_p.push_back(runningval);
+	}
+  majorintervals_p = majors_p.size();
+  if (majorintervals_p)
+    --majorintervals_p;
+
+
+	// minors
+
+  if (!majorintervals_p || !minorintervals_p) // no valid interval
+  {
+    minorintervals_p = 0;
+    return;
+  }
+  
+  // start_p      mstart_p
+  //  |_____________|_____ _ _ _
+
+  double step = (majors_p[1]-majors_p[0]) / minorintervals_p;
+  if (isPracticallyZero(step))
+    return;
+
+  runningval = mstart_p-step;
+	while (runningval>start_p)
+	{
+		minors_p.push_back(runningval);								
+		runningval -= step;
+	}
+
+  //       mstart_p            mstop_p
+  //  ________|_____ _ _ _ _ _ ___|__________
+
+  for (i=0; i!=majorintervals_p; ++i)
+  {
+    runningval = majors_p[i] + step;
+    for (int j=0; j!=minorintervals_p; ++j)
+    {
+		  minors_p.push_back(runningval);								
+		  runningval += step;
+	  }
+  }
+  
+  //    mstop_p       stop_p
+  // _ _ _|_____________|
+
+  runningval = mstop_p + step;
+  while (runningval<stop_p)
+  {
+	  minors_p.push_back(runningval);								
+	  runningval += step;
+  }
+}
+
+void LogScale::setupCounter(double& k, int& step)
+{
+  switch(minorintervals_p) 
+  {
+  case 9:
+  	k=9;
+    step=1;
+    break;
+  case 5:
+    k=8;
+    step=2;
+  	break;
+  case 3:
+    k=5;
+    step=3;
+  	break;
+  case 2:
+    k=5;
+    step=5;
+  	break;
+  default:
+    k=9;
+    step=1;
+  }
+}
+
+/*! Creates major and minor vectors for the scale.
+\warning If the interval is too small, the scale becomes empty
+or will contain only a single major tic. There is no automatism 
+(also not planned for now) for an 'intelligent' guess, what to do. 
+Better switch manually to linear to scales in such cases.
+*/
+void LogScale::calculate()
+{
+  majors_p.clear();
+	minors_p.clear();
+
+  if (start_p < DBL_MIN_10_EXP)
+    start_p = DBL_MIN_10_EXP;
+  if (stop_p > DBL_MAX_10_EXP)
+    stop_p = DBL_MAX_10_EXP;
+
+  double interval = stop_p-start_p;
+  if (interval<=0)
+    return;
+  
+  double runningval = floor(start_p);
+  while(runningval<=stop_p) 
+	{
+    if (runningval>=start_p)
+      majors_p.push_back(runningval);
+    ++runningval;
+	}
+  majorintervals_p = majors_p.size();
+  if (majorintervals_p)
+    --majorintervals_p;
+
+  if (majors_p.size()<1) // not even a single major tic
+  {
+    return;
+  }
+  
+  
+  // minors
+
+  // start_p      mstart_p
+  //  |_____________|_____ _ _ _
+
+  double k;
+  int step;
+  setupCounter(k,step);
+	runningval = log10(k)+(majors_p[0]-1);
+  while (runningval>start_p && k>1)
+	{
+		minors_p.push_back(runningval);								
+    k -=step;
+    runningval = log10(k)+(majors_p[0]-1);
+	}
+
+  //       mstart_p            mstop_p
+  //  ________|_____ _ _ _ _ _ ___|__________
+
+  for (int i=0; i!=majorintervals_p; ++i)
+  {
+    setupCounter(k,step);
+    runningval = log10(k)+(majors_p[i]);
+    while (k>1)
+	  {
+		  minors_p.push_back(runningval);
+      k-=step;
+      runningval = log10(k)+(majors_p[i]);
+	  }
+  }
+
+  //    mstop_p       stop_p
+  // _ _ _|_____________|
+
+  setupCounter(k,step);
+	runningval = log10(k)+(majors_p.back());
+  do 
+  {
+    k-=step; 
+    runningval = log10(k)+(majors_p.back());
+  } 
+  while(runningval>=stop_p);
+  while (k>1)
+	{
+		minors_p.push_back(runningval);								
+    k-=step;
+    runningval = log10(k)+(majors_p.back());
+	}
+}
+
+/*!
+Sets the minor intervals for the logarithmic scale. Only values of 9,5,3 or 2 
+are accepted as arguments. They will produce mantissa sets of {2,3,4,5,6,7,8,9}, 
+{2,4,6,8}, {2,5} or {5} respectively.
+*/
+void LogScale::setMinors(int val)
+{
+  if ((val == 2) || (val == 3) || (val == 5) || (val == 9))
+    minorintervals_p = val;
+}
+
+LogScale::LogScale()
+{
+  minorintervals_p = 9;
+}
+
+//! Returns a power of 10 associated to the major value at index idx.
+QString LogScale::ticLabel(unsigned int idx) const
+{
+  if (idx<majors_p.size())
+  {
+    double val = majors_p[idx];
+    return QString::number(pow(double(10), val));
+  }
+  return QString("");
+}
diff --git a/src/qwt3d_surfaceplot.cpp b/src/qwt3d_surfaceplot.cpp
new file mode 100644
index 0000000..b1f0601
--- /dev/null
+++ b/src/qwt3d_surfaceplot.cpp
@@ -0,0 +1,183 @@
+#include "qwt3d_surfaceplot.h"
+
+using namespace std;
+using namespace Qwt3D;
+
+/**
+Initializes with dataNormals()==false, NOFLOOR, resolution() == 1
+*/
+#if QT_VERSION < 0x040000
+SurfacePlot::SurfacePlot( QWidget* parent, const char* name )
+    : Plot3D( parent, name )
+#else
+SurfacePlot::SurfacePlot( QWidget * parent, const QGLWidget * shareWidget)
+    : Plot3D( parent, shareWidget) 
+#endif
+{
+	datanormals_p = false;
+	normalLength_p = 0.02;
+	normalQuality_p = 3;
+
+	resolution_p = 1;
+	actualDataG_ = new GridData();
+	actualDataC_ = new CellData();
+
+  actualData_p = actualDataG_;
+
+  floorstyle_ = NOFLOOR;
+}
+
+SurfacePlot::~SurfacePlot()
+{
+	delete actualDataG_;
+	delete actualDataC_;
+}
+
+void SurfacePlot::showNormals(bool b)
+{
+  datanormals_p = b;
+}
+
+/**
+Values < 0 or > 1 are ignored
+*/
+void SurfacePlot::setNormalLength(double val)
+{
+	if (val<0 || val>1)
+		return;
+	normalLength_p = val;
+}
+
+/**
+Values < 3 are ignored 
+*/
+void SurfacePlot::setNormalQuality(int val) 
+{
+	if (val<3)
+		return;
+	normalQuality_p = val;
+}
+
+/**
+	Calculates the smallest x-y-z parallelepiped enclosing the data.
+	It can be accessed by hull();
+*/
+void SurfacePlot::calculateHull()
+{
+	if (actualData_p->empty())
+		return;
+	setHull(actualData_p->hull());
+}
+
+/*!
+  Sets data resolution (res == 1 original resolution) and updates widget
+	If res < 1, the function does nothing
+*/
+void SurfacePlot::setResolution( int res )
+{
+  if (!actualData_p || actualData_p->datatype == Qwt3D::POLYGON)
+    return;
+  
+  if ((resolution_p == res) || res < 1)
+		return;
+	
+	resolution_p = res;
+	updateNormals();
+	updateData();
+	if (initializedGL())
+    updateGL();
+
+	emit resolutionChanged(res);
+}
+
+void SurfacePlot::updateNormals()
+{
+	SaveGlDeleteLists(displaylists_p[NormalObject], 1); 
+	
+	if (plotStyle() == NOPLOT && !normals() || !actualData_p)
+		return;
+
+	displaylists_p[NormalObject] = glGenLists(1);
+	glNewList(displaylists_p[NormalObject], GL_COMPILE);
+
+  if (actualData_p->datatype == Qwt3D::POLYGON)
+    createNormalsC();
+  else if (actualData_p->datatype == Qwt3D::GRID)
+    createNormalsG();
+		
+	glEndList();
+}
+
+void SurfacePlot::createData()
+{
+	if (!actualData_p)
+		return;
+  if (actualData_p->datatype == Qwt3D::POLYGON)
+    createDataC();
+  else if (actualData_p->datatype == Qwt3D::GRID)
+    createDataG();
+}
+
+
+void SurfacePlot::createFloorData()
+{
+	if (!actualData_p)
+    return;
+  if (actualData_p->datatype == Qwt3D::POLYGON)
+    createFloorDataC();
+  else if (actualData_p->datatype == Qwt3D::GRID)
+   createFloorDataG();  
+}
+
+/**
+	The returned value is not affected by resolution(). The pair gives (columns,rows) for grid data
+, (number of cells,1) for free formed data (datatype() == POLYGON) and (0,0) else
+*/
+pair<int,int> SurfacePlot::facets() const
+{
+	if (!hasData())
+		return pair<int,int>(0,0);
+
+  if (actualData_p->datatype == Qwt3D::POLYGON)
+  	return pair<int,int>(int(actualDataC_->cells.size()), 1);
+  else if (actualData_p->datatype == Qwt3D::GRID)
+  	return pair<int,int>(actualDataG_->columns(), actualDataG_->rows()); 	
+  else
+    return pair<int,int>(0,0);    
+}
+
+void SurfacePlot::createPoints()
+{
+  Dot pt;
+  createEnrichment(pt);
+}
+
+void SurfacePlot::createEnrichment(Enrichment& p)
+{
+	if (!actualData_p)
+    return;
+  
+  //todo future work
+  if (p.type() != Enrichment::VERTEXENRICHMENT)
+    return;
+  
+  p.assign(*this);
+	p.drawBegin();
+
+  VertexEnrichment* ve = (VertexEnrichment*)&p; 
+  if (actualData_p->datatype == Qwt3D::POLYGON)
+  {	
+    for (unsigned i = 0; i != actualDataC_->normals.size(); ++i) 
+	    ve->draw(actualDataC_->nodes[i]);
+  }
+  else if (actualData_p->datatype == Qwt3D::GRID)
+ 	{
+    int step = resolution();
+    for (int i = 0; i <= actualDataG_->columns() - step; i += step) 
+      for (int j = 0; j <= actualDataG_->rows() - step; j += step) 
+  			ve->draw(Triple(actualDataG_->vertices[i][j][0],
+										              actualDataG_->vertices[i][j][1],
+                                  actualDataG_->vertices[i][j][2]));
+  }
+  p.drawEnd(); 
+}
diff --git a/src/qwt3d_types.cpp b/src/qwt3d_types.cpp
new file mode 100644
index 0000000..ba99a54
--- /dev/null
+++ b/src/qwt3d_types.cpp
@@ -0,0 +1,222 @@
+#if defined(_MSC_VER) /* MSVC Compiler */
+#pragma warning ( disable : 4786 )
+#endif
+
+#include <stdlib.h> // qsort
+#include <algorithm>
+#include <float.h>
+#include "qwt3d_types.h"
+
+using namespace Qwt3D;
+
+#ifndef QWT3D_NOT_FOR_DOXYGEN
+
+namespace {
+  // convex hull
+  
+  typedef double coordinate_type;
+
+  int ccw(coordinate_type **P, int i, int j, int k) {
+    coordinate_type	a = P[i][0] - P[j][0],
+      b = P[i][1] - P[j][1],
+      c = P[k][0] - P[j][0],
+      d = P[k][1] - P[j][1];
+    return a*d - b*c <= 0;	   /* true if points i, j, k counterclockwise */
+  }
+
+
+#define CMPM(c,A,B) \
+  v = (*(coordinate_type**)A)[c] - (*(coordinate_type**)B)[c];\
+  if (v>0) return 1;\
+  if (v<0) return -1;
+
+  int cmpl(const void *a, const void *b) {
+    double v;
+    CMPM(0,a,b);
+    CMPM(1,b,a);
+    return 0;
+  }
+
+  int cmph(const void *a, const void *b) {return cmpl(b,a);}
+
+
+  int make_chain(coordinate_type** V, int n, int (*cmp)(const void*, const void*)) {
+    int i, j, s = 1;
+    coordinate_type* t;
+
+    qsort(V, n, sizeof(coordinate_type*), cmp);
+    for (i=2; i<n; i++) {
+      for (j=s; j>=1 && ccw(V, i, j, j-1); j--){}
+      s = j+1;
+      t = V[s]; V[s] = V[i]; V[i] = t;
+    }
+    return s;
+  }
+
+  int _ch2d(coordinate_type **P, int n)  {
+    int u = make_chain(P, n, cmpl);		/* make lower hull */
+    if (!n) return 0;
+    P[n] = P[0];
+    return u+make_chain(P+u, n-u+1, cmph);	/* make upper hull */
+  }
+
+
+} // ns anon
+
+
+GridData::GridData()
+{
+  datatype = Qwt3D::GRID;
+  setSize(0,0);
+  setPeriodic(false,false);
+}
+
+GridData::GridData(unsigned int columns, unsigned int rows)
+{
+  datatype = Qwt3D::GRID;
+	setSize(columns,rows);
+  setPeriodic(false,false);
+}
+
+int GridData::columns() const 
+{ 
+	return (int)vertices.size();
+}
+
+int GridData::rows() const 
+{ 
+	return (empty()) ? 0 : (int)vertices[0].size();	
+}
+
+void GridData::clear()
+{
+	setHull(ParallelEpiped());
+	{
+		for (unsigned i=0; i!=vertices.size(); ++i)
+		{	
+			for (unsigned j=0; j!=vertices[i].size(); ++j)
+			{	
+				delete [] vertices[i][j];	
+			}
+			vertices[i].clear();
+		}
+	}
+
+	vertices.clear();
+
+	{
+		for (unsigned i=0; i!=normals.size(); ++i)
+		{	
+			for (unsigned j=0; j!=normals[i].size(); ++j)
+			{	
+				delete [] normals[i][j];	
+			}
+			normals[i].clear();
+		}
+	}
+	
+	normals.clear();
+}
+
+
+void GridData::setSize(unsigned int columns, unsigned int rows)
+{
+	this->clear();
+	vertices = std::vector<DataRow>(columns);
+	{
+		for (unsigned int i=0; i!=vertices.size(); ++i)
+		{
+			vertices[i] = DataRow(rows);
+			for (unsigned int j=0; j!=vertices[i].size(); ++j)
+			{
+				vertices[i][j] = new GLdouble[3];
+			}
+		}
+	}
+	normals = std::vector<DataRow>(columns);
+	{
+		for (unsigned int i=0; i!=normals.size(); ++i)
+		{
+			normals[i] = DataRow(rows);
+			for (unsigned int j=0; j!=normals[i].size(); ++j)
+			{
+				normals[i][j] = new GLdouble[3];
+			}
+		}
+	}
+}
+
+Triple const& CellData::operator()(unsigned cellnumber, unsigned vertexnumber)
+{
+	return nodes[cells[cellnumber][vertexnumber]];
+}
+
+void CellData::clear()
+{
+	setHull(ParallelEpiped());
+  cells.clear();
+	nodes.clear();
+	normals.clear();
+}
+
+QColor Qwt3D::GL2Qt(GLdouble r, GLdouble g, GLdouble b)
+{
+	return QColor(round(r * 255), round(g * 255), round(b * 255));	
+}
+
+RGBA Qwt3D::Qt2GL(QColor col)
+{
+	QRgb qrgb = col.rgb();
+	RGBA rgba;
+	rgba.r = qRed(qrgb) / 255.0;
+	rgba.g = qGreen(qrgb) / 255.0;
+	rgba.b = qBlue(qrgb) / 255.0;
+	rgba.a = qAlpha(qrgb) / 255.0;
+	return rgba;	
+}
+
+
+void Qwt3D::convexhull2d( std::vector<unsigned>& idx, const std::vector<Tuple>& src )
+{
+    idx.clear();
+    if (src.empty())
+        return;
+    if (src.size()==1)
+    {
+        idx.push_back(0);
+        return;
+    }
+    coordinate_type** points = new coordinate_type*[src.size()+1] ;
+    coordinate_type* P = new coordinate_type[src.size()*2];
+
+    int i;
+		for (i=0; i<(int)src.size(); ++i)
+    {
+        points[i] = &P[2*i];
+        points[i][0] = src[i].x;
+        points[i][1] = src[i].y;
+    }
+
+    coordinate_type* start = points[0];
+    int m = _ch2d( points, src.size() );
+    idx.resize(m);
+    
+		for (i=0; i<m; ++i)
+ 		{
+			idx[i] = (points[i] - start)/2;
+		}
+    delete [] points;
+		delete [] P;
+}
+
+unsigned Qwt3D::tesselationSize(CellField const& t)
+{
+	unsigned ret = 0;
+	
+	for (unsigned i=0; i!=t.size(); ++i)
+		ret += t[i].size();
+	
+	return ret;
+}
+
+#endif // QWT3D_NOT_FOR_DOXYGEN

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/qwtplot3d.git



More information about the debian-science-commits mailing list