From b85a292ce06475d560bfa1195b63a8bfe211f22d Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Wed, 11 Jul 2012 14:15:27 -0500 Subject: [PATCH] Add 0.2.7 release of qwtplot3d for future TQt3 conversion and use --- lib/tqwtplot3d/3rdparty/gl2ps/COPYING.GL2PS | 25 + lib/tqwtplot3d/3rdparty/gl2ps/COPYING.LGPL | 482 ++ lib/tqwtplot3d/3rdparty/gl2ps/gl2ps.c | 5986 +++++++++++++++++ lib/tqwtplot3d/3rdparty/gl2ps/gl2ps.h | 199 + lib/tqwtplot3d/COPYING | 23 + lib/tqwtplot3d/doc/Doxyfile.doxygen | 227 + lib/tqwtplot3d/doc/footer.html | 7 + lib/tqwtplot3d/doc/web/navigation/doxygen.css | 176 + lib/tqwtplot3d/doc/web/navigation/doxygen.png | Bin 0 -> 2352 bytes lib/tqwtplot3d/doc/web/navigation/menu.css | 12 + lib/tqwtplot3d/doc/web/navigation/sflogo.png | Bin 0 -> 2112 bytes lib/tqwtplot3d/dsp.bat | 2 + .../examples/autoswitch/autoswitch.cpp | 102 + .../examples/autoswitch/autoswitch.h | 58 + .../examples/autoswitch/autoswitch.pro | 4 + lib/tqwtplot3d/examples/axes/axes.pro | 15 + lib/tqwtplot3d/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 + lib/tqwtplot3d/examples/axes/src/main.cpp | 31 + lib/tqwtplot3d/examples/box.png | Bin 0 -> 533 bytes lib/tqwtplot3d/examples/common.pro | 34 + lib/tqwtplot3d/examples/dsp.bat | 12 + .../examples/enrichments/enrichments.pro | 16 + .../enrichments/src/enrichmentmainwindow.cpp | 147 + .../enrichments/src/enrichmentmainwindow.h | 57 + .../src/enrichmentmainwindowbase.ui | 215 + .../src/enrichmentmainwindowbase4.ui | 167 + .../examples/enrichments/src/enrichments.cpp | 150 + .../examples/enrichments/src/enrichments.h | 31 + .../examples/enrichments/src/main.cpp | 30 + lib/tqwtplot3d/examples/examples.pro | 10 + lib/tqwtplot3d/examples/examples.sln | 43 + lib/tqwtplot3d/examples/filecell.png | Bin 0 -> 975 bytes lib/tqwtplot3d/examples/fileopen.png | Bin 0 -> 178 bytes lib/tqwtplot3d/examples/filledmesh.png | Bin 0 -> 918 bytes lib/tqwtplot3d/examples/floordata.png | Bin 0 -> 292 bytes lib/tqwtplot3d/examples/floorempty.png | Bin 0 -> 213 bytes lib/tqwtplot3d/examples/flooriso.png | Bin 0 -> 297 bytes lib/tqwtplot3d/examples/floormesh.png | Bin 0 -> 248 bytes lib/tqwtplot3d/examples/frame.png | Bin 0 -> 290 bytes lib/tqwtplot3d/examples/grid.png | Bin 0 -> 527 bytes lib/tqwtplot3d/examples/gridb.png | Bin 0 -> 1001 bytes lib/tqwtplot3d/examples/gridc.png | Bin 0 -> 820 bytes lib/tqwtplot3d/examples/gridf.png | Bin 0 -> 890 bytes lib/tqwtplot3d/examples/gridfr.png | Bin 0 -> 969 bytes lib/tqwtplot3d/examples/gridl.png | Bin 0 -> 877 bytes lib/tqwtplot3d/examples/gridr.png | Bin 0 -> 799 bytes lib/tqwtplot3d/examples/hiddenline.png | Bin 0 -> 1014 bytes lib/tqwtplot3d/examples/icon.gif | Bin 0 -> 1168 bytes lib/tqwtplot3d/examples/icon.ico | Bin 0 -> 2238 bytes lib/tqwtplot3d/examples/icon.png | Bin 0 -> 1369 bytes lib/tqwtplot3d/examples/icon.rc | 1 + lib/tqwtplot3d/examples/images.qrc | 31 + lib/tqwtplot3d/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 + lib/tqwtplot3d/examples/mesh2/src/femreader.h | 83 + lib/tqwtplot3d/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 + .../mesh2/src/lightingdlgbaseimpl.cpp | 22 + .../examples/mesh2/src/lightingdlgbaseimpl.h | 15 + lib/tqwtplot3d/examples/mesh2/src/main.cpp | 32 + lib/tqwtplot3d/examples/mesh2/src/mesh.cpp | 57 + .../examples/mesh2/src/mesh2mainwindow.cpp | 956 +++ .../examples/mesh2/src/mesh2mainwindow.h | 134 + .../examples/mesh2/src/mesh2mainwindowbase.ui | 1728 +++++ .../mesh2/src/mesh2mainwindowbase4.ui | 479 ++ lib/tqwtplot3d/examples/mesh2/src/thesis.tex | 9 + lib/tqwtplot3d/examples/movie.png | Bin 0 -> 1260 bytes lib/tqwtplot3d/examples/nodata.png | Bin 0 -> 824 bytes lib/tqwtplot3d/examples/none.png | Bin 0 -> 487 bytes lib/tqwtplot3d/examples/normals.png | Bin 0 -> 1344 bytes lib/tqwtplot3d/examples/polygon.png | Bin 0 -> 733 bytes lib/tqwtplot3d/examples/qwtplot.png | Bin 0 -> 543 bytes lib/tqwtplot3d/examples/savecontent.png | Bin 0 -> 550 bytes lib/tqwtplot3d/examples/scattered.png | Bin 0 -> 479 bytes .../examples/simpleplot/simpleplot.cpp | 83 + .../examples/simpleplot/simpleplot.pro | 3 + lib/tqwtplot3d/examples/wireframe.png | Bin 0 -> 1119 bytes lib/tqwtplot3d/include/qwt3d_autoptr.h | 75 + lib/tqwtplot3d/include/qwt3d_autoscaler.h | 51 + lib/tqwtplot3d/include/qwt3d_axis.h | 131 + lib/tqwtplot3d/include/qwt3d_color.h | 63 + lib/tqwtplot3d/include/qwt3d_colorlegend.h | 77 + lib/tqwtplot3d/include/qwt3d_coordsys.h | 100 + lib/tqwtplot3d/include/qwt3d_drawable.h | 66 + lib/tqwtplot3d/include/qwt3d_enrichment.h | 62 + lib/tqwtplot3d/include/qwt3d_enrichment_std.h | 116 + lib/tqwtplot3d/include/qwt3d_function.h | 41 + lib/tqwtplot3d/include/qwt3d_global.h | 58 + lib/tqwtplot3d/include/qwt3d_graphplot.h | 24 + lib/tqwtplot3d/include/qwt3d_gridmapping.h | 34 + lib/tqwtplot3d/include/qwt3d_helper.h | 36 + lib/tqwtplot3d/include/qwt3d_io.h | 141 + lib/tqwtplot3d/include/qwt3d_io_gl2ps.h | 91 + lib/tqwtplot3d/include/qwt3d_io_reader.h | 35 + lib/tqwtplot3d/include/qwt3d_label.h | 80 + lib/tqwtplot3d/include/qwt3d_mapping.h | 27 + lib/tqwtplot3d/include/qwt3d_multiplot.h | 24 + lib/tqwtplot3d/include/qwt3d_openglhelper.h | 130 + .../include/qwt3d_parametricsurface.h | 44 + lib/tqwtplot3d/include/qwt3d_plot.h | 315 + lib/tqwtplot3d/include/qwt3d_portability.h | 91 + lib/tqwtplot3d/include/qwt3d_scale.h | 87 + lib/tqwtplot3d/include/qwt3d_surfaceplot.h | 132 + lib/tqwtplot3d/include/qwt3d_types.h | 455 ++ lib/tqwtplot3d/include/qwt3d_volumeplot.h | 24 + lib/tqwtplot3d/lingua_de.ts | 10 + lib/tqwtplot3d/qwtplot3d.pro | 95 + lib/tqwtplot3d/scripts/fixvc7.py | 16 + lib/tqwtplot3d/scripts/makedistro.py | 67 + lib/tqwtplot3d/scripts/makedocu.py | 36 + lib/tqwtplot3d/scripts/qwtplot3d.supp | 17 + lib/tqwtplot3d/scripts/valgr.sh | 1 + lib/tqwtplot3d/src/qwt3d_autoscaler.cpp | 253 + lib/tqwtplot3d/src/qwt3d_axis.cpp | 386 ++ lib/tqwtplot3d/src/qwt3d_color.cpp | 63 + lib/tqwtplot3d/src/qwt3d_colorlegend.cpp | 223 + lib/tqwtplot3d/src/qwt3d_coordsys.cpp | 633 ++ lib/tqwtplot3d/src/qwt3d_dataviews.cpp | 10 + lib/tqwtplot3d/src/qwt3d_drawable.cpp | 140 + lib/tqwtplot3d/src/qwt3d_enrichment_std.cpp | 347 + lib/tqwtplot3d/src/qwt3d_function.cpp | 101 + lib/tqwtplot3d/src/qwt3d_gridmapping.cpp | 32 + lib/tqwtplot3d/src/qwt3d_gridplot.cpp | 596 ++ lib/tqwtplot3d/src/qwt3d_io.cpp | 355 + lib/tqwtplot3d/src/qwt3d_io_gl2ps.cpp | 387 ++ lib/tqwtplot3d/src/qwt3d_io_reader.cpp | 225 + lib/tqwtplot3d/src/qwt3d_label.cpp | 262 + lib/tqwtplot3d/src/qwt3d_lighting.cpp | 192 + lib/tqwtplot3d/src/qwt3d_meshplot.cpp | 320 + lib/tqwtplot3d/src/qwt3d_mousekeyboard.cpp | 387 ++ lib/tqwtplot3d/src/qwt3d_movements.cpp | 106 + .../src/qwt3d_parametricsurface.cpp | 104 + lib/tqwtplot3d/src/qwt3d_plot.cpp | 498 ++ lib/tqwtplot3d/src/qwt3d_scale.cpp | 304 + lib/tqwtplot3d/src/qwt3d_surfaceplot.cpp | 183 + lib/tqwtplot3d/src/qwt3d_types.cpp | 222 + 146 files changed, 23541 insertions(+) create mode 100644 lib/tqwtplot3d/3rdparty/gl2ps/COPYING.GL2PS create mode 100644 lib/tqwtplot3d/3rdparty/gl2ps/COPYING.LGPL create mode 100644 lib/tqwtplot3d/3rdparty/gl2ps/gl2ps.c create mode 100644 lib/tqwtplot3d/3rdparty/gl2ps/gl2ps.h create mode 100644 lib/tqwtplot3d/COPYING create mode 100644 lib/tqwtplot3d/doc/Doxyfile.doxygen create mode 100644 lib/tqwtplot3d/doc/footer.html create mode 100644 lib/tqwtplot3d/doc/web/navigation/doxygen.css create mode 100644 lib/tqwtplot3d/doc/web/navigation/doxygen.png create mode 100644 lib/tqwtplot3d/doc/web/navigation/menu.css create mode 100644 lib/tqwtplot3d/doc/web/navigation/sflogo.png create mode 100644 lib/tqwtplot3d/dsp.bat create mode 100644 lib/tqwtplot3d/examples/autoswitch/autoswitch.cpp create mode 100644 lib/tqwtplot3d/examples/autoswitch/autoswitch.h create mode 100644 lib/tqwtplot3d/examples/autoswitch/autoswitch.pro create mode 100644 lib/tqwtplot3d/examples/axes/axes.pro create mode 100644 lib/tqwtplot3d/examples/axes/src/axes.h create mode 100644 lib/tqwtplot3d/examples/axes/src/axesmainwindow.cpp create mode 100644 lib/tqwtplot3d/examples/axes/src/axesmainwindow.h create mode 100644 lib/tqwtplot3d/examples/axes/src/axesmainwindowbase.ui create mode 100644 lib/tqwtplot3d/examples/axes/src/axesmainwindowbase4.ui create mode 100644 lib/tqwtplot3d/examples/axes/src/main.cpp create mode 100644 lib/tqwtplot3d/examples/box.png create mode 100644 lib/tqwtplot3d/examples/common.pro create mode 100644 lib/tqwtplot3d/examples/dsp.bat create mode 100644 lib/tqwtplot3d/examples/enrichments/enrichments.pro create mode 100644 lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindow.cpp create mode 100644 lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindow.h create mode 100644 lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindowbase.ui create mode 100644 lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindowbase4.ui create mode 100644 lib/tqwtplot3d/examples/enrichments/src/enrichments.cpp create mode 100644 lib/tqwtplot3d/examples/enrichments/src/enrichments.h create mode 100644 lib/tqwtplot3d/examples/enrichments/src/main.cpp create mode 100644 lib/tqwtplot3d/examples/examples.pro create mode 100644 lib/tqwtplot3d/examples/examples.sln create mode 100644 lib/tqwtplot3d/examples/filecell.png create mode 100644 lib/tqwtplot3d/examples/fileopen.png create mode 100644 lib/tqwtplot3d/examples/filledmesh.png create mode 100644 lib/tqwtplot3d/examples/floordata.png create mode 100644 lib/tqwtplot3d/examples/floorempty.png create mode 100644 lib/tqwtplot3d/examples/flooriso.png create mode 100644 lib/tqwtplot3d/examples/floormesh.png create mode 100644 lib/tqwtplot3d/examples/frame.png create mode 100644 lib/tqwtplot3d/examples/grid.png create mode 100644 lib/tqwtplot3d/examples/gridb.png create mode 100644 lib/tqwtplot3d/examples/gridc.png create mode 100644 lib/tqwtplot3d/examples/gridf.png create mode 100644 lib/tqwtplot3d/examples/gridfr.png create mode 100644 lib/tqwtplot3d/examples/gridl.png create mode 100644 lib/tqwtplot3d/examples/gridr.png create mode 100644 lib/tqwtplot3d/examples/hiddenline.png create mode 100644 lib/tqwtplot3d/examples/icon.gif create mode 100644 lib/tqwtplot3d/examples/icon.ico create mode 100644 lib/tqwtplot3d/examples/icon.png create mode 100644 lib/tqwtplot3d/examples/icon.rc create mode 100644 lib/tqwtplot3d/examples/images.qrc create mode 100644 lib/tqwtplot3d/examples/mesh2/mesh2.pro create mode 100644 lib/tqwtplot3d/examples/mesh2/src/colormapreader.cpp create mode 100644 lib/tqwtplot3d/examples/mesh2/src/colormapreader.h create mode 100644 lib/tqwtplot3d/examples/mesh2/src/designerworkaround.cpp create mode 100644 lib/tqwtplot3d/examples/mesh2/src/designerworkaround.h create mode 100644 lib/tqwtplot3d/examples/mesh2/src/femreader.h create mode 100644 lib/tqwtplot3d/examples/mesh2/src/functions.h create mode 100644 lib/tqwtplot3d/examples/mesh2/src/lightingdlg.cpp create mode 100644 lib/tqwtplot3d/examples/mesh2/src/lightingdlg.h create mode 100644 lib/tqwtplot3d/examples/mesh2/src/lightingdlgbase.ui create mode 100644 lib/tqwtplot3d/examples/mesh2/src/lightingdlgbase4.ui create mode 100644 lib/tqwtplot3d/examples/mesh2/src/lightingdlgbaseimpl.cpp create mode 100644 lib/tqwtplot3d/examples/mesh2/src/lightingdlgbaseimpl.h create mode 100644 lib/tqwtplot3d/examples/mesh2/src/main.cpp create mode 100644 lib/tqwtplot3d/examples/mesh2/src/mesh.cpp create mode 100644 lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindow.cpp create mode 100644 lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindow.h create mode 100644 lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindowbase.ui create mode 100644 lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindowbase4.ui create mode 100644 lib/tqwtplot3d/examples/mesh2/src/thesis.tex create mode 100644 lib/tqwtplot3d/examples/movie.png create mode 100644 lib/tqwtplot3d/examples/nodata.png create mode 100644 lib/tqwtplot3d/examples/none.png create mode 100644 lib/tqwtplot3d/examples/normals.png create mode 100644 lib/tqwtplot3d/examples/polygon.png create mode 100644 lib/tqwtplot3d/examples/qwtplot.png create mode 100644 lib/tqwtplot3d/examples/savecontent.png create mode 100644 lib/tqwtplot3d/examples/scattered.png create mode 100644 lib/tqwtplot3d/examples/simpleplot/simpleplot.cpp create mode 100644 lib/tqwtplot3d/examples/simpleplot/simpleplot.pro create mode 100644 lib/tqwtplot3d/examples/wireframe.png create mode 100644 lib/tqwtplot3d/include/qwt3d_autoptr.h create mode 100644 lib/tqwtplot3d/include/qwt3d_autoscaler.h create mode 100644 lib/tqwtplot3d/include/qwt3d_axis.h create mode 100644 lib/tqwtplot3d/include/qwt3d_color.h create mode 100644 lib/tqwtplot3d/include/qwt3d_colorlegend.h create mode 100644 lib/tqwtplot3d/include/qwt3d_coordsys.h create mode 100644 lib/tqwtplot3d/include/qwt3d_drawable.h create mode 100644 lib/tqwtplot3d/include/qwt3d_enrichment.h create mode 100644 lib/tqwtplot3d/include/qwt3d_enrichment_std.h create mode 100644 lib/tqwtplot3d/include/qwt3d_function.h create mode 100644 lib/tqwtplot3d/include/qwt3d_global.h create mode 100644 lib/tqwtplot3d/include/qwt3d_graphplot.h create mode 100644 lib/tqwtplot3d/include/qwt3d_gridmapping.h create mode 100644 lib/tqwtplot3d/include/qwt3d_helper.h create mode 100644 lib/tqwtplot3d/include/qwt3d_io.h create mode 100644 lib/tqwtplot3d/include/qwt3d_io_gl2ps.h create mode 100644 lib/tqwtplot3d/include/qwt3d_io_reader.h create mode 100644 lib/tqwtplot3d/include/qwt3d_label.h create mode 100644 lib/tqwtplot3d/include/qwt3d_mapping.h create mode 100644 lib/tqwtplot3d/include/qwt3d_multiplot.h create mode 100644 lib/tqwtplot3d/include/qwt3d_openglhelper.h create mode 100644 lib/tqwtplot3d/include/qwt3d_parametricsurface.h create mode 100644 lib/tqwtplot3d/include/qwt3d_plot.h create mode 100644 lib/tqwtplot3d/include/qwt3d_portability.h create mode 100644 lib/tqwtplot3d/include/qwt3d_scale.h create mode 100644 lib/tqwtplot3d/include/qwt3d_surfaceplot.h create mode 100644 lib/tqwtplot3d/include/qwt3d_types.h create mode 100644 lib/tqwtplot3d/include/qwt3d_volumeplot.h create mode 100644 lib/tqwtplot3d/lingua_de.ts create mode 100644 lib/tqwtplot3d/qwtplot3d.pro create mode 100644 lib/tqwtplot3d/scripts/fixvc7.py create mode 100644 lib/tqwtplot3d/scripts/makedistro.py create mode 100644 lib/tqwtplot3d/scripts/makedocu.py create mode 100644 lib/tqwtplot3d/scripts/qwtplot3d.supp create mode 100644 lib/tqwtplot3d/scripts/valgr.sh create mode 100644 lib/tqwtplot3d/src/qwt3d_autoscaler.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_axis.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_color.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_colorlegend.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_coordsys.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_dataviews.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_drawable.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_enrichment_std.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_function.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_gridmapping.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_gridplot.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_io.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_io_gl2ps.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_io_reader.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_label.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_lighting.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_meshplot.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_mousekeyboard.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_movements.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_parametricsurface.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_plot.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_scale.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_surfaceplot.cpp create mode 100644 lib/tqwtplot3d/src/qwt3d_types.cpp diff --git a/lib/tqwtplot3d/3rdparty/gl2ps/COPYING.GL2PS b/lib/tqwtplot3d/3rdparty/gl2ps/COPYING.GL2PS new file mode 100644 index 0000000..1d03143 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/3rdparty/gl2ps/COPYING.LGPL b/lib/tqwtplot3d/3rdparty/gl2ps/COPYING.LGPL new file mode 100644 index 0000000..fc84d1c --- /dev/null +++ b/lib/tqwtplot3d/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. + + + Copyright (C) + + 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/lib/tqwtplot3d/3rdparty/gl2ps/gl2ps.c b/lib/tqwtplot3d/3rdparty/gl2ps/gl2ps.c new file mode 100644 index 0000000..46d2a15 --- /dev/null +++ b/lib/tqwtplot3d/3rdparty/gl2ps/gl2ps.c @@ -0,0 +1,5986 @@ +/* $Id: gl2ps.c 173 2007-05-20 15:51:51Z krischnamurti $ */ +/* + * GL2PS, an OpenGL to PostScript Printing Library + * Copyright (C) 1999-2006 Christophe Geuzaine + * + * 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 + * Marc Ume + * Jean-Francois Remacle + * Bart Kaptein + * Quy Nguyen-Dai + * Sam Buss + * Shane Hill + * Romain Boman + * Rouben Rostamian + * Diego Santa Cruz + * Shahzad Muzaffar + * Lassi Tuura + * Guy Barrand + * Prabhu Ramachandran + * Micha Bieber + * Olivier Couet + * Shai Ayal + * Fabian Wenzel + * Ian D. Gay + * Cosmin Truta + * Baiju Devani + * Alexander Danilov + * + * For the latest info about gl2ps, see http://www.geuz.org/gl2ps/. + * Please report all bugs and problems to . + */ + +#include "gl2ps.h" + +#include +#include +#include +#include +#include +#include + +#if defined(GL2PS_HAVE_ZLIB) +#include +#endif + +#if defined(GL2PS_HAVE_LIBPNG) +#include +#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], ¤t[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.5; + prim->verts[0].xyz[1] = prim->verts[0].xyz[1] - (int)(node->image->height / 2) + 0.5; + 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.30 * dr + 0.59 * dg + 0.11 * 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("\n"); + gl2psPrintf("\n", + width, height, x, y, width, height); + gl2psPrintf("%s\n", gl2ps->title); + gl2psPrintf("\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("\n"); + gl2psPrintf("\n"); + gl2psPrintf("\n"); + + if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ + gl2psSVGGetColorString(gl2ps->bgcolor, col); + gl2psPrintf("\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("\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("\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.5 * (xyz[0][i] + xyz[1][i]); + xyz2[2][i] = 0.5 * (xyz[0][i] + xyz[2][i]); + } + for(i = 0; i < 4; i++){ + rgba2[0][i] = rgba[0][i]; + rgba2[1][i] = 0.5 * (rgba[0][i] + rgba[1][i]); + rgba2[2][i] = 0.5 * (rgba[0][i] + rgba[2][i]); + } + gl2psPrintSVGSmoothTriangle(xyz2, rgba2); + for(i = 0; i < 3; i++){ + xyz2[0][i] = 0.5 * (xyz[0][i] + xyz[1][i]); + xyz2[1][i] = xyz[1][i]; + xyz2[2][i] = 0.5 * (xyz[1][i] + xyz[2][i]); + } + for(i = 0; i < 4; i++){ + rgba2[0][i] = 0.5 * (rgba[0][i] + rgba[1][i]); + rgba2[1][i] = rgba[1][i]; + rgba2[2][i] = 0.5 * (rgba[1][i] + rgba[2][i]); + } + gl2psPrintSVGSmoothTriangle(xyz2, rgba2); + for(i = 0; i < 3; i++){ + xyz2[0][i] = 0.5 * (xyz[0][i] + xyz[2][i]); + xyz2[1][i] = xyz[2][i]; + xyz2[2][i] = 0.5 * (xyz[1][i] + xyz[2][i]); + } + for(i = 0; i < 4; i++){ + rgba2[0][i] = 0.5 * (rgba[0][i] + rgba[2][i]); + rgba2[1][i] = rgba[2][i]; + rgba2[2][i] = 0.5 * (rgba[1][i] + rgba[2][i]); + } + gl2psPrintSVGSmoothTriangle(xyz2, rgba2); + for(i = 0; i < 3; i++){ + xyz2[0][i] = 0.5 * (xyz[0][i] + xyz[1][i]); + xyz2[1][i] = 0.5 * (xyz[1][i] + xyz[2][i]); + xyz2[2][i] = 0.5 * (xyz[0][i] + xyz[2][i]); + } + for(i = 0; i < 4; i++){ + rgba2[0][i] = 0.5 * (rgba[0][i] + rgba[1][i]); + rgba2[1][i] = 0.5 * (rgba[1][i] + rgba[2][i]); + rgba2[2][i] = 0.5 * (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("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("\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("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("%s\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("\n"); + gl2psPrintf("\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("\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("\n", x, y, w, h); + gl2psPrintf(" \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("\n"); + gl2psPrintf("\n", x, y, w, h); +} + +static GLint gl2psPrintSVGEndViewport(void) +{ + GLint res; + + res = gl2psPrintPrimitives(); + gl2psPrintf("\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/lib/tqwtplot3d/3rdparty/gl2ps/gl2ps.h b/lib/tqwtplot3d/3rdparty/gl2ps/gl2ps.h new file mode 100644 index 0000000..60b18c2 --- /dev/null +++ b/lib/tqwtplot3d/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 + * + * 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 . + */ + +#ifndef __GL2PS_H__ +#define __GL2PS_H__ + +#include +#include + +/* 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 +# 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 +#else +# include +#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@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/lib/tqwtplot3d/COPYING b/lib/tqwtplot3d/COPYING new file mode 100644 index 0000000..abb97f0 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/doc/Doxyfile.doxygen b/lib/tqwtplot3d/doc/Doxyfile.doxygen new file mode 100644 index 0000000..8910fb7 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/doc/footer.html b/lib/tqwtplot3d/doc/footer.html new file mode 100644 index 0000000..2fe3584 --- /dev/null +++ b/lib/tqwtplot3d/doc/footer.html @@ -0,0 +1,7 @@ +
+The documentation for the QwtPlot3D API has been created by +doxygen + $doxygenversion and is hosted at +SourceForge.net Logo
+ + diff --git a/lib/tqwtplot3d/doc/web/navigation/doxygen.css b/lib/tqwtplot3d/doc/web/navigation/doxygen.css new file mode 100644 index 0000000..13034f5 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/doc/web/navigation/doxygen.png b/lib/tqwtplot3d/doc/web/navigation/doxygen.png new file mode 100644 index 0000000000000000000000000000000000000000..96ae72c2978be48bb081e0795f5e9a5d6905a5b9 GIT binary patch literal 2352 zcmaJ@XHXM}5)Mc=AW}p^5e%RSEsY{YdPy*fgck593B?GZMk&IDB6^_&r6UR=V1t07 zqDYYB{P-jdO973>Gf8e9NRM)Dp)o!g0qM<4Vj=zPe@|Dq666;okhst+uYS@xk zAe#!=^Zln?PyVKr%6E;`S(kqWY=*HsfA1V;)fhQ<$CMos^=cI}FxoX8aHZD(`7N&D z>eW}uY`q&yA(Aq{v|hyY~*BV!IpRizEa^A zSwUf5fG8o|FrCa?7W_ZsbCSbIMfvD5rc2)xa_CE)&3MK>PdiZzPSx=EY{5R=Lw9$W zFB~Q4-_erioglSItWbyFcScK%P|Bx2nok_;7V~gL{^sw)Hmw`$rsv1K}`8Yt2#c0pX2g5sO;y1o~4%iuIyi#qw zFm*RC`MvCuf!1<4v?T_#Q{Sw>Dv=96=Qk`bvEfC+V}+C_G!9f5qp+Mfqpdo&v-7X2 zEsjl=2Zs2jpeR3I^jOrC#EnCRYK7ykw~Y<^$KBzQ$j?=wli)Z_dg%f@3mh@mn~ zY-rW-_)2Tp)x!)>H?E^r>=E{}#T=G-CW-@osY zch;71#~zaaQaCN&u+y;iqyJD$efQ0`ds~0bG7EEg?iz@?@KkW>xdI>kcON*eM-mkj z{Hg4Mq|yM@aKlnN8Ad!tqDiW7k~_vI0!L4-1Z&Wup7|~d>#qjJ0-uA&ia#r&mdx8v zh{Ysj=iMgA&&1A@moF|nsz(e)_;Uiol|tq()vU(gqOB|ji;{rH_>zyt2xSg9h+h{C zv+F5Xy#5KK7P)%}Ck#D|^?1V$N)szVm7J2X#m+w(imL|lM%~vBw^Q~q$CrnXoTf$H zzF~>!<$mS2O?lzwP|kfiF}g8jcl3mUEgkkkh%w!KZMvAFF9^}~ej@k#Gd^V_{0z7E zlS6D1*YZT=yhuXqJ9{VQ#HEDN*DR$8sI6F7<;IiQSrcoeN7g_o#?!`Af^b9`2;50K zitSJI72p0Sb8pZ7DS_NNl_sYR+va{vYOi<{J}UY2dXxVnRvC@qh1F8VTgYH6vT~(% zZ2N{=>^>N0x=jb@(&D^o^RLm}($~_;&Kub{C2Xfmah^5anC-b6$;BEl3*$8jem8}c z3*MM|I(n@y9TAF*ctIWJT!UQdUmM^y{K3@8sQJdNrafkJtINN7ONa1e;w?Mt{_JhM zvRka(c#HYT@E0V`S6xwQ!o-vU4DQhKh-)xd(lG?l6971ya~`Kg%#4-Zl9lG!@VLCj zn%e5Mm!q<2O$UGcRpXu>y%9VED_L9OY%qWuy3i~< z+emnMRoLY#-xm~rEgRP6atqF;dvM1{=%Q7NcKcBg&Z1l zV~6}Z`XPV+=bsYaz2&oFCc3ZEn}yXbvh;enHYUk;@jUTd(xG51%O-4mi-__eW*D%0++`&?dm# zPd_nXLUL4%gBDan;34>)_!5SOs{V7u1HVyR7H*pVx$aUUgqXX95@2i(7j1|H^I|!M zS3hU81OfgU9~=o25UZE}Kn~T?I2_2;b7HMR`%*)h);W}}SN$d(wjY3w22CPf3pSEK z`@JL}GUw`L^lZx+{KurgBTG8o(X~G|(-<9c9%;J8&^(JEc$Oi*N?=TC)Lzw#&F7Nl zHQB3u-YV(8aQrkAK!U7fLifRwqTWQcQt+0@;kmR<&^uK8n9YK;XTuDH?XY{HL*v09 z8svU;%Hhy$AH9$^e+pAEde;2I<;K%f*-dV3{IarZHE-WX1+D)GFP8KnOsc_^ z6q~mV=laSj_m1;^5X}%ECLfW5I$=E3`=TMVtLt?(a30*5=_&F*bvhx?FF`d>rP;x^MFfsMbkCxS5D-e^%!V{JsKKS`i`&ka` z-g#uQghXfa@Au4JFJ6eWrAEFVsOiW@X;hgN@VQgD2(fD=RxXatsl;WS2C1NQ5IP1br%vg@40K^|6=DP_ zk`iN1j)|m@h&uj}I)0bKLPIDz#87e&KcIbI4*IVgDKNyBa(Q1*52cUvH89j85a4h> zq`m(*h0x7Qh1|1-#2F|e^Q z@T(J}>DjaAoSYnjf`VjN2oOL677%C7p4+r#%lGd;kOec+Qk2BSe^01pQ{!gv$YbCY zhx+ir^_AjxC<6myZdN8RbUuIn0`z=lS}M>Ah-oUyN0$?y98v=A2Fqr@q z0}}#T^aBJCqOe@BcnQ!Zp!*)k{^L6&K?;I^01!d6 z0HuHl8|dfhv*rLj42&gUzyYOz+JR1d|Na9oCEvYw52yx+TwR>bRy7`SFc@13wWU65O2fC`|unK4i`nB-sjJs6D(Ocz@Z6A z5x`7`sQ_p`&~OM_2V4`U6>H-EHS_UQvfT0e|mcW33 z6ST00SDBm|5gSex19HGoXL`0A?{@2)cp;ard6R@Z<>;hZ_ZS z2~g_D(WBa0TJV$$6bEZ`!eux>05KtF4WLqBF$0NtAVMzNu3Wta30hnR0m}%WPk{EV zT(btK3@!NKJ_lL>MB$+!SPkJ$u>Q6CATBGeg53a0U)I);cmkHkkPHaVWe}HuGK-`X zW?TZD2g!z*03d)60Rd3~%xpjiG#$v;y%(Y9$kAiKD?n$UIT#KA0+3zCC;-AR6ve>{IVxUH5O3fy+*}nsi(9K8E`mOM zAc9+IlBR8v|C5BF%UPqU8-YOjv`fJZ`sBg*v#L1@EcCw-QP_x3Km^6ScOooqlD#Ad zw&OIDWrhnE^0Z%|f{=9W``K10?EYz}j&V59ny?fo-wYX#f0%+(3#M38FfC$0{_MLDk14@1R^a+^@Ob&RA1qdLP zAru5o_70FB$jJkB6BaF40P$*kVq#TIHAD?iq`jr}YZ-Pn_`g@d1jgU9$!#`|;yP zAU7s53ZfXo1u6!r1ag7mK$So(n8pId0Rm`b;RoimXT!G2@pVoF(CfG zdByPQ2gCEr40ks$ynX%e3)7z`-+vsqK~SS6cz9+HxV#`000hur42XZsd_QlnF`T)~ zaBTm-%dfuP;{W}GnMFYaoaaB|(FiFx*RNd*EHdGOz~ZB=r4?S9z{?AGV*~;K0%*Vn zZ}CNrpuoq)SAX67@#_)Wm#e(r&#k;q@aegTzj+q(7V&!3Ep48R6OQ9)ruRHTx!GEf9qxm>((5y;rEZr!Pq zr(9fJAvR8#GzlPp25G13*M&zPN|ygTa^wFm1`c}-k@dMu0$j+|0T2M=57=aW`s68G zBq%rt7&^d!Sig4N6L5sf$jId6iC#!P@(zF8~GvKmd(S q`9T3d0I@*AV>BQD0t^5EplX~|`sPId0000 +#include +#include + +#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/lib/tqwtplot3d/examples/autoswitch/autoswitch.h b/lib/tqwtplot3d/examples/autoswitch/autoswitch.h new file mode 100644 index 0000000..f4a6745 --- /dev/null +++ b/lib/tqwtplot3d/examples/autoswitch/autoswitch.h @@ -0,0 +1,58 @@ +#ifndef AUTOSWITCH_H__ +#define AUTOSWITCH_H__ + +#include +#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/lib/tqwtplot3d/examples/autoswitch/autoswitch.pro b/lib/tqwtplot3d/examples/autoswitch/autoswitch.pro new file mode 100644 index 0000000..38487ee --- /dev/null +++ b/lib/tqwtplot3d/examples/autoswitch/autoswitch.pro @@ -0,0 +1,4 @@ +include( ../common.pro ) + +SOURCES = autoswitch.cpp +HEADERS = autoswitch.h diff --git a/lib/tqwtplot3d/examples/axes/axes.pro b/lib/tqwtplot3d/examples/axes/axes.pro new file mode 100644 index 0000000..185fadb --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/examples/axes/src/axes.h b/lib/tqwtplot3d/examples/axes/src/axes.h new file mode 100644 index 0000000..675ae8b --- /dev/null +++ b/lib/tqwtplot3d/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 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/lib/tqwtplot3d/examples/axes/src/axesmainwindow.cpp b/lib/tqwtplot3d/examples/axes/src/axesmainwindow.cpp new file mode 100644 index 0000000..d3086bc --- /dev/null +++ b/lib/tqwtplot3d/examples/axes/src/axesmainwindow.cpp @@ -0,0 +1,245 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#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/lib/tqwtplot3d/examples/axes/src/axesmainwindow.h b/lib/tqwtplot3d/examples/axes/src/axesmainwindow.h new file mode 100644 index 0000000..fd99d0d --- /dev/null +++ b/lib/tqwtplot3d/examples/axes/src/axesmainwindow.h @@ -0,0 +1,64 @@ +#include + +#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/lib/tqwtplot3d/examples/axes/src/axesmainwindowbase.ui b/lib/tqwtplot3d/examples/axes/src/axesmainwindowbase.ui new file mode 100644 index 0000000..92bab56 --- /dev/null +++ b/lib/tqwtplot3d/examples/axes/src/axesmainwindowbase.ui @@ -0,0 +1,243 @@ + +AxesMainWindowBase + + + AxesMainWindowBase + + + + 0 + 0 + 826 + 608 + + + + print + + + + unnamed + + + 11 + + + 6 + + + + frame + + + + 7 + 7 + 0 + 0 + + + + StyledPanel + + + Sunken + + + + + layout11 + + + + unnamed + + + + layout9 + + + + unnamed + + + + TextLabel1_2 + + + Number gap + + + + + numbergapslider + + + + 7 + 0 + 0 + 0 + + + + 10 + + + Horizontal + + + Above + + + 1 + + + + + + + layout10 + + + + unnamed + + + + TextLabel1_2_2 + + + Label gap + + + + + labelgapslider + + + + 7 + 0 + 0 + 0 + + + + 10 + + + Horizontal + + + Above + + + 1 + + + + + + + + + smoothBox + + + Smooth Lines + + + true + + + + + layout11 + + + + unnamed + + + + layout9 + + + + unnamed + + + + ticNumeberLabel + + + true + + + Tics + + + AlignCenter + + + + + ticLengthSlider + + + 100 + + + 10 + + + Vertical + + + Below + + + Tic Length (rel.) + + + + + ticNumberSlider + + + false + + + 25 + + + 0 + + + Vertical + + + Below + + + Change Tic Number (available only for letter example) + + + + + + + + + + + menubar + + + + + + + + diff --git a/lib/tqwtplot3d/examples/axes/src/axesmainwindowbase4.ui b/lib/tqwtplot3d/examples/axes/src/axesmainwindowbase4.ui new file mode 100644 index 0000000..1e4a0b5 --- /dev/null +++ b/lib/tqwtplot3d/examples/axes/src/axesmainwindowbase4.ui @@ -0,0 +1,295 @@ + + + + + MainWindow + + + + 0 + 0 + 694 + 600 + + + + MainWindow + + + + + 8 + + + 6 + + + + + 0 + + + 6 + + + + + + 7 + 7 + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 0 + + + 6 + + + + + 0 + + + 6 + + + + + + 0 + 0 + 0 + 0 + + + + <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> + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 20 + + + + + + + + + + 0 + + + 6 + + + + + + 0 + 7 + 0 + 0 + + + + 100 + + + 10 + + + Qt::Vertical + + + true + + + QSlider::TicksBelow + + + + + + + + 0 + 7 + 0 + 0 + + + + 25 + + + Qt::Vertical + + + true + + + QSlider::TicksBelow + + + + + + + + + + + + + 0 + + + 6 + + + + + + 0 + + + 6 + + + + + 0 + + + 6 + + + + + <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> + + + + + + + + 7 + 5 + 0 + 0 + + + + 10 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + + + + + + + 0 + + + 6 + + + + + <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> + + + + + + + + 7 + 5 + 0 + 0 + + + + 10 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + + + + + + + + + + + 1 + 5 + 0 + 0 + + + + Smooth Lines + + + + + + + + + + 590 + 10 + 61 + 421 + + + + + + + + + diff --git a/lib/tqwtplot3d/examples/axes/src/main.cpp b/lib/tqwtplot3d/examples/axes/src/main.cpp new file mode 100644 index 0000000..518faf6 --- /dev/null +++ b/lib/tqwtplot3d/examples/axes/src/main.cpp @@ -0,0 +1,31 @@ +/******************************************************************** + created: 2003/09/10 + filename: main.cpp + + author: Micha Bieber +*********************************************************************/ + +#include +#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/lib/tqwtplot3d/examples/box.png b/lib/tqwtplot3d/examples/box.png new file mode 100644 index 0000000000000000000000000000000000000000..1aa8c08f64c5e262656f3e7226bf0fa2aefdff47 GIT binary patch literal 533 zcmV+w0_y#VP)WdKueAUPmSa(W;#FfcP9F*iCjF*-3fAS*C2FfiU%8)5(e00(qQO+^RO z0|^uuJ4)$`ssI2032;bRa{vGe@Bjb`@Bu=sG?)MY00d`2O+f$vv5yPVM9IPeFEIT*1R$o%I+z+YjxtuH@*`ppUyx&>8C z2(YlSFiLW9u?R4t8OR7U@IR3L52P8PV!Q;M_aWdjRPBFucBaqRy#62NVj{f^*C(UC z!xKn9qnd$G+7gJLvH%G+p!07bdl?9{fqX({aRAky0_l?w=kR*Lut5nZ_7x<-2o%f( z(vx_2Se|_O^5+o)@iEN}#0E0boE{IZy6=R#R1ZjPX8{t2f%pZ`z%U?vg#=&g0P)%< zPrrY_2o50r2gP4uu}EY%euet#JGvYbDG@>}7@>v& +#include +#include +#include + + +#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/lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindow.h b/lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindow.h new file mode 100644 index 0000000..68b97b0 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindowbase.ui b/lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindowbase.ui new file mode 100644 index 0000000..b6ff9fc --- /dev/null +++ b/lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindowbase.ui @@ -0,0 +1,215 @@ + +EnrichmentMainWindowBase + + + EnrichmentMainWindowBase + + + + 0 + 0 + 843 + 702 + + + + print + + + + unnamed + + + 11 + + + 6 + + + + Layout11 + + + + unnamed + + + 0 + + + 6 + + + + Layout10 + + + + unnamed + + + 0 + + + 6 + + + + TextLabel1_2 + + + false + + + + 5 + 0 + 0 + 0 + + + + Width + + + + + widthSlider + + + false + + + + 7 + 0 + 0 + 0 + + + + + 0 + 40 + + + + 10 + + + 200 + + + Horizontal + + + Below + + + 10 + + + Relative psition of slicing plane + + + + + + + Layout9 + + + + unnamed + + + 0 + + + 6 + + + + + + + + Layout8 + + + + unnamed + + + 0 + + + 6 + + + + levelSlider + + + true + + + + 40 + 0 + + + + 100 + + + 10 + + + Vertical + + + Below + + + 10 + + + Changes the level, where marker are shown + + + + + TextLabel1 + + + Level + + + AlignCenter + + + + + + + frame + + + StyledPanel + + + Sunken + + + + + + + menubar + + + + + + diff --git a/lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindowbase4.ui b/lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindowbase4.ui new file mode 100644 index 0000000..0ed32e3 --- /dev/null +++ b/lib/tqwtplot3d/examples/enrichments/src/enrichmentmainwindowbase4.ui @@ -0,0 +1,167 @@ + + + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + 8 + + + 6 + + + + + 0 + + + 6 + + + + + 0 + + + 6 + + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 0 + + + 6 + + + + + + 5 + 0 + 0 + 0 + + + + <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> + + + + + + + + 0 + 7 + 0 + 0 + + + + 100 + + + 10 + + + Qt::Vertical + + + true + + + QSlider::TicksBelow + + + 10 + + + + + + + + + + + 0 + + + 6 + + + + + false + + + + 0 + 0 + 0 + 0 + + + + <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> + + + + + + + false + + + 2 + + + 200 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + + + + + + + + diff --git a/lib/tqwtplot3d/examples/enrichments/src/enrichments.cpp b/lib/tqwtplot3d/examples/enrichments/src/enrichments.cpp new file mode 100644 index 0000000..7780412 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/examples/enrichments/src/enrichments.h b/lib/tqwtplot3d/examples/enrichments/src/enrichments.h new file mode 100644 index 0000000..2a47968 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/examples/enrichments/src/main.cpp b/lib/tqwtplot3d/examples/enrichments/src/main.cpp new file mode 100644 index 0000000..a590d9d --- /dev/null +++ b/lib/tqwtplot3d/examples/enrichments/src/main.cpp @@ -0,0 +1,30 @@ +/******************************************************************** + created: 2003/09/10 + filename: main.cpp + + author: Micha Bieber +*********************************************************************/ + +#include +#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/lib/tqwtplot3d/examples/examples.pro b/lib/tqwtplot3d/examples/examples.pro new file mode 100644 index 0000000..1d2a507 --- /dev/null +++ b/lib/tqwtplot3d/examples/examples.pro @@ -0,0 +1,10 @@ +TEMPLATE = subdirs +SUBDIRS = \ + simpleplot \ + autoswitch \ + enrichments \ + axes \ + mesh2 + + + diff --git a/lib/tqwtplot3d/examples/examples.sln b/lib/tqwtplot3d/examples/examples.sln new file mode 100644 index 0000000..68980b6 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/examples/filecell.png b/lib/tqwtplot3d/examples/filecell.png new file mode 100644 index 0000000000000000000000000000000000000000..c2da1fe080b19146cb5d374a149d1305d5617a04 GIT binary patch literal 975 zcmah{&x;&I6#k~WVqun=KgnJW71ewMWBUdyj}k9XA5e ziY7)9A|fvfDEGTFX27dsLTGo189`b*IfjCJa=}EOSBbA&yBzLL_DHd)aHEn43&j06 zOhSq%$bwPs2QxN=w;dA?ZI>7YsqN%66a!BtOgOwMe05-#^W8~KDvJskm5Pud?#1Ce zB&i#MQO^&E4TZNYiC4C(7-gwF&1otIbD2ot>{msm4rDn`COK1CTFAUq0-20^BAizw zRgjjW-XtJ36vehIc?DM;QYP%Fq-i>si$s>rzFlN=AP4g#$=Ntdxy*ef{7gnYfq4a~ zke298KnkLOETJ``4v`5=C8jCnLKlzsZDiDu10)I9xRvsD?nC&Ej2eNaLZfiE#M%V4 z0t%p9Dd7+hfCSQ2QXa$B3+`Z`w+oD0;BEMT-ymv$zx^(tmA#bPf9wgOImQyS)ZEHi zKzo%uMPP;aADVwb|Ij=Q_a7`S=~qhyeuy{z`1yVPAnvf}!(ZZ~UoYV0wz=`z=c;+` z%2(HSf4H`_)uCrz`Rvp9*2$M$e6W7==!XhV|#p*GI3u_5F7z X$?xOMH}5^%d$^p%$#-sUz5B^ye-sD; literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/fileopen.png b/lib/tqwtplot3d/examples/fileopen.png new file mode 100644 index 0000000000000000000000000000000000000000..85dab435c401f5c2a89f70c09b5c87d44c6c7a38 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fm7Xq+As)x?UcJcGV8Fo|u;2EV zS^eo(t|gb37A)4-p%XFZPOYS&v8~`Q`x?6>;kVl#@&ujPceu}P4pX1ik9FJmva%Ef zcPj02lTSbJs9kRDI@cZj^~H~}u6tg4vG1$Vfe4c~5{-Vciv!FJg+e8Itt2}Agv&pl bx>~|e=*B)fzM)Yb=m-W+S3j3^P6Gk@eQm1n`+u?|E9H&$j7ylA0mKD3* zem@@lz6sOP(oU8M!gpoFrNrU3+Z9!}SuD#8!yHQWA@|_q9W2}Z;i*-GWh^7YXt#r^ z|9oaM3Rdfl)M$4lWm&dqjU?T$ge03NudIZU)>UmD3Wb_+tNU+Bc})FgNq&CXnQjgV z7!ZB4&{I7IQY;1o!*ww5x&fR{Czq3x^QgYQ-l96vyG6-URN<=&`ozHSyK?h4y34;x5In|Pt&`bIOKAqD7Bg_xS zD8JvY)pgtS<598zMRzhLbg-}naXg=y0aZWfc58YZ3`Mcnw9krYonw!Xezl}-@4^KwzbsY5&kmfT!OKIG%%q^46m zPwI5K!)j}#z6L@Ngq{jfy!cX?PQ34L}T9CzYZ-N|{l8s`Rgdgn2mW>|P0q?>y+MJV=RqWX+R6lP? zA3qAO&1z*}J_0JPo%TX$aWN#@;wZyMkUY;Y7#PelKee2q$n!x7KuJbnL4lHLQ_)mY zqv@S4mzYC5*r+PT&f9UX;8BmxXg!~ERbwxsK^n9^EXt6*Qtfj~gcj7Axk$<$1s zp$l*AKzn=pH?P+lq$o;3GID5WNa*eDJu*H%o)Hd*wV!?i1=pjS?Uy0Tats3+!8Ux0 s9WX@@#O?imu)7OoG#an`XU;$J8)sxl-*LzP`~Uy|07*qoM6N<$g16VF{r~^~ literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/floordata.png b/lib/tqwtplot3d/examples/floordata.png new file mode 100644 index 0000000000000000000000000000000000000000..e577276c0a29e4348656cf4de07acdba51d85448 GIT binary patch literal 292 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw{1|(OCFP#RYv`btgN}P*Q6H7Al^Atidb5j|7 z^A(H@6?}`T6pRcEjDduefu)tHp@O!7p@D(C;;C&wZR{nUzOL+-ndOD}439@Io&*%) zEbxddW?Nn{1`Ydl>XLn>}1CrGd=iyI^f{`Oxv zQ|E>YZ_VSAMsE*2YfX^4d*T1G#EA~C#9jT47HD!m_us^0wXZ<-#_Jbt|F)n0u<*uI z3B6R+%Tud=mmiMp%z07YuVt;^I&Yyxtk*hi^Xv0m3RTZs`0r@@%i$G!Xbk7(#z#l| gOt1Ga{bFL6`A|xvr~mkMpgR~mUHx3vIVCg!01p0Td;kCd literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/floorempty.png b/lib/tqwtplot3d/examples/floorempty.png new file mode 100644 index 0000000000000000000000000000000000000000..83d5fd7cb98aee543b321c14e6ee9ad607db5e15 GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw{1|(OCFP#RYv`btgN}P*Q6H7Al^Atidb5j|7 z^A(H@6?}`T6pRcEjDduefu)tHp@O!7p@D(C;;C&wZR{nUzOL+-S=hMv3~VEoo&*YU z7I;J!Gca&{0AWU_H6}BFf-LEdzK#qG8~eHcB(ehex}GkMAr-fh6C_xb#SM}KfBQ2V zYZ`sAzu3f_`C^53`z&qAl?fWkt-st4IxsR^IWPD*(&v#iP$Pqg3 z7I;J!Gca&{0AWU_H6}BFf-LEdzK#qG8~eHcB(ehejh-%!Ar-fh6C_xb#SM}KfBQ2V z8}jZwdD4A~gpWSAn4?>X@2mUviCgDJe2`C(Fbg-}y7!m=(2I4hLEWY|HgGMHZp$;6 zw7$bwWH#fCBNx7IQs6W?w5LgzC$a5s{rWQbP0l+XkKO<`Nu literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/floormesh.png b/lib/tqwtplot3d/examples/floormesh.png new file mode 100644 index 0000000000000000000000000000000000000000..51e71257e89a907b5a9dd8f6b6d7de54629a6a7e GIT binary patch literal 248 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw{1|(OCFP#RYv`btgN}P*Q6H7Al^Atidb5j|7 z^A(H@6?}`T6pRcEjDduefu)tHp@O!7p@D(C;;C&wZR{nUzOL+-S=hLkOr|yH-2n=5 z7I;J!Gca&{0AWU_H6}BFf-LEdzK#qG8~eHcB(ehe0iG_7Ar-fh6C_xb#SM}KfBQ2V z2lA$F+2zgk-+n7^%WL=YSM>{=HvReYe}+-m`rxBe6%M#e+q{8Y`p#4Xwww2sO}(Be k{#YYRB4f%8_k#iq3FVdQ&MBb@0MOz~djJ3c literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/frame.png b/lib/tqwtplot3d/examples/frame.png new file mode 100644 index 0000000000000000000000000000000000000000..9d1a3880f71460d3915813bba8010d67af74f805 GIT binary patch literal 290 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw{1|(OCFP#RYv`SnfN}P*Q6H7Al^Atidb5j|D z^A#)=e2c0Sj0_Bn6%5U-Obx9J%@wo_3=ItKg-a&^b+MOt`ns}TX66);Q>)+V@D(V; zS>O>_%)r3)0fZTy)|kuy3bLd-`Z_W&Z0zU$lgJ9>S9`iRhE&{2PFP@+Ab8`zk&YvY z>_PSoGajFBZIKy^k(ex9h zJTtET7gqP^Y&bP0l+XkKA1Y$9 literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/grid.png b/lib/tqwtplot3d/examples/grid.png new file mode 100644 index 0000000000000000000000000000000000000000..0745d21f047d16cd2f07e6adee8f2c5082ef9ea4 GIT binary patch literal 527 zcmV+q0`UEbP)WdKueAUPmSa(W;#FfcP9F*iCjF*-3fAS*C2FfiU%8)5(e00(qQO+^RP z0|pd3HqV!!m;e9(32;bRa{vGe@Bjb`@Bu=sG?)MY00d`2O+f$vv5yPVM9IPeFEIj|YXjKqEirH>FpbBb(y2%;I$UHIoi zz<(h9KPu9PVbOFJMj)G)pz}Tie1@^P#W#JzsSw%4!~l>(WYl+fVwHdy7?=5n*lU+|___$J7mEJ^UHAoA0svD*<19## Rw9Wtk002ovPDHLkV1k4t$87)r literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/gridb.png b/lib/tqwtplot3d/examples/gridb.png new file mode 100644 index 0000000000000000000000000000000000000000..658df5202581da1aafaa8bcca5e5cb9c5d664b54 GIT binary patch literal 1001 zcmVWdKueAUPmSa(W;#FfcP9F*iCjF*-3fAS*C2FfiU%8)5(e00(qQO+^RP z0|pfc4E!>7EdT%j32;bRa{vGe@Bjb`@Bu=sG?)MY00d`2O+f$vv5yPF$$>%Nh>G`BEmmC1kyw1gHJ}i zh`s1TK_a0K5)26{5E9dzWNpSDSTc7)B(CD6}kKKBU5j1yu-+91+i+|NSkm6X#!qH zx4LSYzH^3O?lDKb59b+E^I9?qW!D;A`u&t$lFXqVSFXC_?KzP7CUZ zZ-I(NBR`LjA8?(9Mez88oXJE{&e8KKaddvidP5o5{p}2|V7-wMw>%$z0yO?F3u04j zV#no;veg7Tt+zA{1F(=n;_`&49R{+x80$W)YzASQTy!%L$K@-Ba4MBZa0bzQ=Xb&;h0o$;py@==Jx^!bmPc6BIlGNSR{!7d8`Ud4E+rqp3~ zkISB{APkFmz6SxF^ool&Ew-8!VqAP4`bTt&SS(+SHi~XH10sat?(ts+7DE7sy!^!v X57DkZ06+;n00000NkvXXu0mjfa(227 literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/gridc.png b/lib/tqwtplot3d/examples/gridc.png new file mode 100644 index 0000000000000000000000000000000000000000..37330a37562bb7c1bde15201d553dfda9f3ac1d4 GIT binary patch literal 820 zcmV-41Izr0P)WdKueAUPmSa(W;#FfcP9F*iCjF*-3fAS*C2FfiU%8)5(e00(qQO+^RP z0|pfiGHVIU0000032;bRa{vGe@Bjb`@Bu=sG?)MY00d`2O+f$vv5yP6?e79dmO2D7TY#^2j7-ZKh_3jY6a_Aaxc4p8n2kZ%Iyzq|`kdkIME z0_kfXnD|Wv{(U@vV(4Z@UOwLcpC`X$5{7g3Ny7~V%JKrK4j>K#;uk=}7#SJ$6LM;$=Ym1&9@Z zcpebnKoa8t;zl5L1mav5fejyl^cogT-ab8s&qYN*jswuZR3QEK4+HBoo;O#n9$~dO z`kYC^8Wb@OzmMjyF#P5OMj%)W=nI~ZpBo*34vD`cU|HGsFZLG5l0P2;q*-1uiMRkc z;!jy*q@@2mNw~+Xpr`cr!CRnWQJdc;#Hm28tU1^&P$} zWL?_zW_1rR%`mVCY|sPZr;I?tfbIXU9diGkMBDv7c8!5ZaER4P>oJqelAnxh0YKNC z1c`wR1+p)J88884O>voj{^K(gn?9IJnV_7f=$aNyXJKR@0I=x;g((w^fi6kNrMUDB z4VQuWdKueAUPmSa(W;#FfcP9F*iCjF*-3fAS*C2FfiU%8)5(e00(qQO+^RP z0|pfW6N}Z8QUCw|32;bRa{vGe@Bjb`@Bu=sG?)MY00d`2O+f$vv5yPOz9tw7Tq~o9>c+ zNU#>7y6D1!3N(bQ1iMfuvqCe(E$PRUv{Kt2oppA1dOz8LZQXFZY~bNLXU;kAdC&RI zIV=<9<4tWW!fH?iMu5zy`}{zNCa4K3PlsZUnrKLF|3Zyz?uGm6t()E|TWU}y!a%>oa>KDc|S zh$>FAqb+&4J&iU_ams}%7)8&s*UQ765adOX3tr%IC1hm>epQR)0cl0mYyR z&`q<0Jeml+4$WN|U^Mo-!T~-hIDN8Wp^Nsm4&;MIRynXa#tVg*xmFaC?SlA|E`bN6 z0}~hpze9ovV1vYHXS9q&CTO+kZq}I6qb)eow9wVExcr2K)`@d-mrkQt3PE~l%D_9| z1qXqRRs!mQ2p(LGIZ=Bk{?>Y>U!3fzx*XGRZShoO1itETx=%gz#HAk_o=-YI%4H;C z^KZw>b2%UR%o{_RE%cI?8{~QIPN}znXCy;EzqJ=4dG}m(om1SZ+LYjrs!~(iD|(Ab zRAbifPPPOmuB;WEBQ7?6Pl3OGotKNX8D;M`s$+sof$<%u|8CB>EnfCaNvyV}Y@s`8 zkhd0R20m9p@D~Kflw{MMviZ`Rw9Nr$kZ07tp?-#E$GEgWw{C|Qf}ZfUKTl6b3AMR+ Q;{X5v07*qoM6N<$f~KI7YXATM literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/gridfr.png b/lib/tqwtplot3d/examples/gridfr.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e8e47c2d6d58fdd3d168b3a12d355cb12f3640 GIT binary patch literal 969 zcmV;)12+7LP)WdKueAUPmSa(W;#FfcP9F*iCjF*-3fAS*C2FfiU%8)5(e00(qQO+^RP z0|pff3rTyhO#lD@32;bRa{vGe@Bjb`@Bu=sG?)MY00d`2O+f$vv5yPjZ-vAC;JrA$ZfC6Osoe_LJot1y$T1TV7#5 zYKS9!5RZ8g#>*NmY7*!Dxxz?2Y>(rpfh5kFZO){b!B?vIupi_y$Rfm>0i{2}1Wf28 zr170>=~dX`oSg^x2?h5^c7@t6=?aX;yhuoO64EI@WnA7z2;PiE5Ybib?nYY{*^e4+ zjK@4p!65}Huy4`+5qfG{YgW~H@(omw0*fXpCF7h zPF$XpiE2C1m9Hk`e?(y(+`dr>p$G52QWScVEE8qFUt&`e@;{<5PeoETsNV1otT0U&IE23wwPR*P;guZfKMM)wAydoCX9v{ r68#&>6NVbsS%pr0=^_;T>t_81gbAC?yI?BR00000NkvXXu0mjflB=gG literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/gridl.png b/lib/tqwtplot3d/examples/gridl.png new file mode 100644 index 0000000000000000000000000000000000000000..02a6a01308ea5a454abe5e3e026d20e7216ef406 GIT binary patch literal 877 zcmV-z1CsoSP)WdKueAUPmSa(W;#FfcP9F*iCjF*-3fAS*C2FfiU%8)5(e00(qQO+^RP z0|pfh4faB^{r~^~32;bRa{vGe@Bjb`@Bu=sG?)MY00d`2O+f$vv5yP(*1 zK~#9!l~vzM6j2zxcbwhXnbqAbh1FfDEODV9E|icVL}(D2!A3&VLj++^JqXr6Q0z-l zP%nY>5cniPW`STJArTcmR7M3>D*z8Y1(zifwSk%cki5g?)Tk$ zmy$fsLvFKlUFxcQ!-pI2Iu2;W-jfAf|3$Aln#2)8?g1~WJv}mu@xFl*qLs6WGpeFGCk?a7hkpSIioB=Jut+_eGUfhZ6I>TNEYxz(ye zL#?dMnFROGaDhQI`&X!QNRg@nb_ET$bZ$N)Lp;Xgr*2q|ums<(&c#22dle!^J<43F zUpN-x#dC#pTo4*%4lDhxHVCqUrVtB~a&K=pT=v~})TrS38;-pT;K@PiUS-Q)r#NpJ zZ`<|sh$#hZe2i;d8UFH#4;@!?e2+$GX~XKfbb^-Mlr&}GYsq#u# zvLy{c-kVDZJG0}9%d~VKC7Khs=FyU4$Z1ur@-1bqtferlFTmVc;xSIt(hijhl`bt) zhu9ME5$Kkb*`&FU1%zXH3KrBq5;QeA%lRLmxdL3Bqa*;{=0@(4tLK42VZ zF5*((=+-Tz_Zc~zcai|hr)Rlr>&epORLdbko^2$j5NF5qEMl+p<;&FT-?BE-f@T7O z5j%p`oI)%FdacJ1`eA?GWDHN_mv6W-j!FYA4%W9bMQfSbpM{d4zaT->S#WdKueAUPmSa(W;#FfcP9F*iCjF*-3fAS*C2FfiU%8)5(e00(qQO+^RP z0|pfZ9V09#k^lez32;bRa{vGe@Bjb`@Bu=sG?)MY00d`2O+f$vv5yPSvRiD!)~Pz)7K$N^T#y@lk1$HcOIi9^?1N4J>KXUDO{wzL{j_n{U3^nPtKn zB`IMB@&VnzM}P}9%3p{{c|nrb65L>FFB<&HiX(#H8J2rA@Eca?FrQR8n4cO52oG*b z3~i5A{~2@hkhA>`+HtW$h?fQ7G;c@HaJbjQwS`np z`jTX|URqu&mi(zgyv<6msraq--tvW$U&V%@d1uS@4sCiM&74s;*V;(nB0Z!ujnCQL z6yoik8z10wYE(He0`3B|NkRIB7z*UH1J6tV$AEWsa-=$weWdp56L%vUy9bZz<9+z) z_?*~yySW(em(VF<`94}QI8`2W_I#ex?pG6a%4(*LC+B-tUIx+K2`nv&b+gFUD;i6R zR}NZFkgA4f96FP?x_FxM9|2aj6=DH}FQrSOaM)Nmh@4tQAagwxmHfBRd=G5i#Irk6 z%i>d_Y%$VUGzT2@_+o3Q_8d}H**@zPRbOU^c)lY*GzT5K@(Xz zt;WS8!()``+ujh}X47e>uK^rUrRdJ#%*#`bJ)wPq@M2Y_R#}>hE)U_)&iCN`Jb1-*`C3V@?35giJq)+o6g5k0ih#GBMmx*!H`$iqR6W{>)yUY_Z<9k$Zyb`waq_GAH daHyI8_zm;xGQ_!1&>8>$002ovPDHLkV1kU0VT%9& literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/hiddenline.png b/lib/tqwtplot3d/examples/hiddenline.png new file mode 100644 index 0000000000000000000000000000000000000000..cb9ea63abf99ae5fdd8dbbd84fbd2d0c98587851 GIT binary patch literal 1014 zcmVyn|lv; z%`MMe8wR7%_{z=AZO`4^-7L%UW2`B6R?}!S(IFurpZ)y&ECz#t#m2^7czSy7`}+De z@$4Pq8uF^72s9)zls`B`rC+z2yIPG4OLfH)BOBAB_}7-#l;0pO-&KnA_WBn83F?X zKW1iTdfE?4*C`^)B9z|R)zzh&ot>rj_I6rbT_taCZ`#`0B9OrM(Bbi|H{x_Cy?`3&; zxq>@wZf?@#=d?onNG;raFa%g^7iU zi3vJ5IH36Wc*0=sXii?Y>yStl)hK49OI9Leq zFqurWxVT8WySst{Oqq=B@pg|Kjgnx*2W0rHqoYGRI5^!WVy4mBiv6( zNfF|Qhljk9VL6#0Gc#lB>+6$21q0XCm6a8%#bQx`gcb=4 z)o?AUva<3!re+;3Gl;2Bwl{D}M8EXM$H!NHdSqh5d&@8U^kDT834H~I6CmIlTJ!$e k*}r3`F|yD9v*yqE0hYyjqNo@(2LJ#707*qoM6N<$f?kN_%K!iX literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/icon.gif b/lib/tqwtplot3d/examples/icon.gif new file mode 100644 index 0000000000000000000000000000000000000000..f59b1ab0541f1800e6549ca5d69f4df5f110d9cb GIT binary patch literal 1168 zcmeIx?@JSL90%}^?suFr+tQ_0wlh%6vo3=l^lp3TG{6Nd~(Wq2lokQ4`r11U*K0wW2m%z>N)Ss-P^ z$cU9QNJ)aigCdZMKq(@nAVxu~A|XXaDi5jvsz|CLrDj-FVpLgF^-zUJj4GC*yYic4rVs+H?yiO$+#_X17 zzJ%xVJnm?lNsZfEkiCK|5Bq1Et@hK+rHfk!N89WNI(MIa`{RqHXsS~!wfu6qz{IbU_6lg+IT8_cETliZa5{el^D+_|}Vdvfst=B(oA%jtsqp5w2s zjN@*@(%wDJ+ODC=HzgkL$<`F%8IBsQSnpRRt4d|{QRfY!FC8?R%yj?E)u_Shstfyq z9f9SMhVpNX;nh>?We%K3ad^7W<|2k(F3+zPTjs8R`nk4XGTWY)tpsl6UKq0;^Y=)T z_>!K`t3|$%lrPLNMO6NN=Y z?M2$MuMVG!78oHiQe?)#dAR5CM~i!Eld@xp-t-uL&qojLXX)s!dYA8=y|TBf5UbfR Sp27TCeElJ@;k(oX(C`=Z5g7&m literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/icon.ico b/lib/tqwtplot3d/examples/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f9f5da1a2ccaf324a9be5ce217711079234d605d GIT binary patch literal 2238 zcmeH|F-#g^6vzLEMZjx;94Oa!_U6 zQMGv908SdTov?V`1gcF`FL-PL7GneFHYzn6R)gmq;G#q84yug~Y@63zpw>mD-lgqb zSOjVgP{55fL0F`y9cXFI6cY}9_M|)_F;Q8Quw}q&;1?zm%jn?Z%3g}yz7XaOjc1}?vF2# zGjocnt&go(PRZ0l%Wn_1Se&^DN+yy?Ii1zkHm+OD&OQtT0s{YM3W5+Y&5|TZi9|B3 z>xG4RaVioH1%tr}jt4ZM2BmmEQu?Nrl;Tm5Dng;jP$(Rk5=B0>6r~VFsa#%>`vs8* zxoBLH;`8jy(j$=?hhm12Pf&xYNJNz6OeVG5xAa)$bAuB}!_X4ZxGZN?Re81Z({e$C z3MOUagJJBJ_5Aww+X2bb)oJ=Nq<2*%E8TL}%jsy&(C5;rg!Fi%H=mRZHJg!>(!yxJ zSJsv6Tv|?y*5uammDf)6PAK&*s6JLm1@dG-;FW;BH`&Es>W1G%v5&-%TOxS zm`b%FL$zUDCYGvHDV6m(Z^F=8h}~$)4tW_E9v-_!lhi{HyMgxrPiuIV;8~LQv4RH#3Itjs(73?h0!s)iDR8X7vmyl|4I-lv8C>*{ zB1eckBO)&_5)Bdq5{pY5DextwR|dT;8{wt93>%eXCtmI#qakxcX+o#lZ`&;vSGvK8ZVfvSA?7yQ0Y;k9=3&9_+Y` z4HrzV{;(wWuC}wZpy}3{uNS|qk0)o1vdC75%H1XVlHr|PxUBVMbK7RuzNjCH9x8CC zEXF#QBBh-($ct_$K0Qnc?RlZ^;u*heTg2f9(?)OU#C5f!ror2&J#t)EG;U7runt69 z@PUzQSGD`Il*z@Jw}Sw`)7;ygb!x3b_bLC|(@R7FV=XS6=mJXwwu*e*5fj?k;v6bV z8&mJDP?Rs|`@Sh&f0Wh~{+|7L`Gn + + box.png + filecell.png + fileopen.png + filledmesh.png + floordata.png + floorempty.png + flooriso.png + floormesh.png + frame.png + grid.png + gridb.png + gridc.png + gridf.png + gridfr.png + gridl.png + gridr.png + hiddenline.png + icon.png + movie.png + nodata.png + none.png + normals.png + polygon.png + qwtplot.png + savecontent.png + scattered.png + wireframe.png + + diff --git a/lib/tqwtplot3d/examples/mesh2/mesh2.pro b/lib/tqwtplot3d/examples/mesh2/mesh2.pro new file mode 100644 index 0000000..8f345a5 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/examples/mesh2/src/colormapreader.cpp b/lib/tqwtplot3d/examples/mesh2/src/colormapreader.cpp new file mode 100644 index 0000000..90f7d0c --- /dev/null +++ b/lib/tqwtplot3d/examples/mesh2/src/colormapreader.cpp @@ -0,0 +1,81 @@ +#include + +#include +#include +#include +#include + +#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/lib/tqwtplot3d/examples/mesh2/src/colormapreader.h b/lib/tqwtplot3d/examples/mesh2/src/colormapreader.h new file mode 100644 index 0000000..3322846 --- /dev/null +++ b/lib/tqwtplot3d/examples/mesh2/src/colormapreader.h @@ -0,0 +1,28 @@ +#ifndef __colormapreader_2003_06_08_13_23__ +#define __colormapreader_2003_06_08_13_23__ + +#include +#include +#include + +#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/lib/tqwtplot3d/examples/mesh2/src/designerworkaround.cpp b/lib/tqwtplot3d/examples/mesh2/src/designerworkaround.cpp new file mode 100644 index 0000000..433a317 --- /dev/null +++ b/lib/tqwtplot3d/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 tmplist = ag->actions(); + for (QList::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/lib/tqwtplot3d/examples/mesh2/src/designerworkaround.h b/lib/tqwtplot3d/examples/mesh2/src/designerworkaround.h new file mode 100644 index 0000000..d57418a --- /dev/null +++ b/lib/tqwtplot3d/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 +#include +#include +#include +#include +#include +#include + + +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/lib/tqwtplot3d/examples/mesh2/src/femreader.h b/lib/tqwtplot3d/examples/mesh2/src/femreader.h new file mode 100644 index 0000000..374a181 --- /dev/null +++ b/lib/tqwtplot3d/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 +#include +#include "qwt3d_global.h" +#include "qwt3d_types.h" + +class NodeFilter +{ + public: + explicit NodeFilter() + { + values = std::vector(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 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[i]; + cell[i] = cell[i] - 1; + } + return cell; + } +}; + + +template +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 +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/lib/tqwtplot3d/examples/mesh2/src/functions.h b/lib/tqwtplot3d/examples/mesh2/src/functions.h new file mode 100644 index 0000000..1a86e0d --- /dev/null +++ b/lib/tqwtplot3d/examples/mesh2/src/functions.h @@ -0,0 +1,214 @@ +#ifndef __EXAMPLE_H__ +#define __EXAMPLE_H__ + +#include +#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/lib/tqwtplot3d/examples/mesh2/src/lightingdlg.cpp b/lib/tqwtplot3d/examples/mesh2/src/lightingdlg.cpp new file mode 100644 index 0000000..0d46b2c --- /dev/null +++ b/lib/tqwtplot3d/examples/mesh2/src/lightingdlg.cpp @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include + +#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/lib/tqwtplot3d/examples/mesh2/src/lightingdlg.h b/lib/tqwtplot3d/examples/mesh2/src/lightingdlg.h new file mode 100644 index 0000000..2dd79b1 --- /dev/null +++ b/lib/tqwtplot3d/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 +#include +#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/lib/tqwtplot3d/examples/mesh2/src/lightingdlgbase.ui b/lib/tqwtplot3d/examples/mesh2/src/lightingdlgbase.ui new file mode 100644 index 0000000..6e5af4b --- /dev/null +++ b/lib/tqwtplot3d/examples/mesh2/src/lightingdlgbase.ui @@ -0,0 +1,361 @@ + +LightingDlgBase + + + LightingDlgBase + + + + 0 + 0 + 450 + 345 + + + + + 5 + 5 + 0 + 0 + + + + + 450 + 345 + + + + + 450 + 345 + + + + + 0 + 0 + + + + Lighting Configuration + + + false + + + + unnamed + + + 11 + + + 6 + + + + frame + + + + 290 + 290 + + + + + 290 + 290 + + + + StyledPanel + + + Sunken + + + + + Layout11 + + + + unnamed + + + 0 + + + 6 + + + + stdlight + + + + + + Std + + + true + + + true + + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 16 + 0 + + + + + + buttonOk + + + + + + &OK + + + true + + + true + + + + + + + Layout8 + + + + unnamed + + + 0 + + + 6 + + + + Layout2 + + + + unnamed + + + 0 + + + 6 + + + + ambdiff + + + Ambient & Diffuse Part + + + + + ambdiffSL + + + 100 + + + 80 + + + Horizontal + + + + + + + Layout2_2 + + + + unnamed + + + 0 + + + 6 + + + + spec + + + Specular Part + + + + + specSL + + + 100 + + + 30 + + + Horizontal + + + + + + + Layout2_3 + + + + unnamed + + + 0 + + + 6 + + + + shin + + + Shininess + + + + + shinSL + + + 1000 + + + 500 + + + Horizontal + + + + + + + Layout2_4 + + + + unnamed + + + 0 + + + 6 + + + + emiss + + + Emission + + + + + emissSL + + + 100 + + + Horizontal + + + + + + + Layout2_4_2 + + + + unnamed + + + 0 + + + 6 + + + + dist + + + Distance + + + + + distSL + + + 1000 + + + 100 + + + Horizontal + + + + + + + + + + + buttonOk + clicked() + LightingDlgBase + accept() + + + + diff --git a/lib/tqwtplot3d/examples/mesh2/src/lightingdlgbase4.ui b/lib/tqwtplot3d/examples/mesh2/src/lightingdlgbase4.ui new file mode 100644 index 0000000..2102170 --- /dev/null +++ b/lib/tqwtplot3d/examples/mesh2/src/lightingdlgbase4.ui @@ -0,0 +1,293 @@ + + + + + Dialog + + + + 0 + 0 + 428 + 330 + + + + Dialog + + + + 8 + + + 6 + + + + + 0 + + + 6 + + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 0 + + + 6 + + + + + Std + + + + + + + Qt::Horizontal + + + + 91 + 31 + + + + + + + + &Ok + + + + + + + + + 0 + + + 6 + + + + + 0 + + + 6 + + + + + <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> + + + + + + + 100 + + + 80 + + + Qt::Horizontal + + + + + + + + + 0 + + + 6 + + + + + <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> + + + + + + + 100 + + + 30 + + + 30 + + + Qt::Horizontal + + + + + + + + + 0 + + + 6 + + + + + <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> + + + + + + + 1000 + + + 500 + + + Qt::Horizontal + + + + + + + + + 0 + + + 6 + + + + + <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> + + + + + + + 100 + + + 0 + + + Qt::Horizontal + + + + + + + + + 0 + + + 6 + + + + + <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> + + + + + + + 1000 + + + 100 + + + Qt::Horizontal + + + + + + + + + + + + + + 10 + 280 + 351 + 33 + + + + + + + + + stdlight + clicked() + Dialog + accept() + + + 278 + 253 + + + 96 + 254 + + + + + buttonOk + clicked() + Dialog + reject() + + + 369 + 253 + + + 179 + 282 + + + + + diff --git a/lib/tqwtplot3d/examples/mesh2/src/lightingdlgbaseimpl.cpp b/lib/tqwtplot3d/examples/mesh2/src/lightingdlgbaseimpl.cpp new file mode 100644 index 0000000..25ca438 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/examples/mesh2/src/lightingdlgbaseimpl.h b/lib/tqwtplot3d/examples/mesh2/src/lightingdlgbaseimpl.h new file mode 100644 index 0000000..4255129 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/examples/mesh2/src/main.cpp b/lib/tqwtplot3d/examples/mesh2/src/main.cpp new file mode 100644 index 0000000..cce8242 --- /dev/null +++ b/lib/tqwtplot3d/examples/mesh2/src/main.cpp @@ -0,0 +1,32 @@ +/******************************************************************** + created: 2003/09/09 + filename: main.cpp + + author: Micha Bieber +*********************************************************************/ + +#include +#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/lib/tqwtplot3d/examples/mesh2/src/mesh.cpp b/lib/tqwtplot3d/examples/mesh2/src/mesh.cpp new file mode 100644 index 0000000..60683eb --- /dev/null +++ b/lib/tqwtplot3d/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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#if QT_VERSION < 0x040000 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindow.h b/lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindow.h new file mode 100644 index 0000000..435a325 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindowbase.ui b/lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindowbase.ui new file mode 100644 index 0000000..49a2625 --- /dev/null +++ b/lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindowbase.ui @@ -0,0 +1,1728 @@ + +Mesh2MainWindowBase + + + Mesh2MainWindowBase + + + + 0 + 0 + 954 + 710 + + + + + 5 + 5 + 0 + 0 + + + + + 381 + 328 + + + + Mesh2 + + + false + + + + unnamed + + + 11 + + + 6 + + + + Spacer4 + + + Vertical + + + Fixed + + + + 16 + 50 + + + + + + Layout11 + + + + unnamed + + + 0 + + + 6 + + + + Layout9 + + + + unnamed + + + 0 + + + 6 + + + + projection + + + + 0 + 0 + 0 + 0 + + + + Ortho + + + true + + + + + colorlegend + + + true + + + + 0 + 0 + 0 + 0 + + + + Legend + + + + + autoscale + + + true + + + + 0 + 0 + 0 + 0 + + + + Autoscale + + + true + + + Autoscale axes + + + Autoscale axes + + + + + mouseinput + + + + 0 + 0 + 0 + 0 + + + + Mouse + + + true + + + Enable mouse input + + + + + shader + + + true + + + + 0 + 0 + 0 + 0 + + + + Shading + + + true + + + Checked means Gouraud (smooth) shading, flat else + + + Checked means Gouraud (smooth) shading, flat else + + + + + + + Layout7 + + + + unnamed + + + 0 + + + 6 + + + + Layout6 + + + + unnamed + + + 0 + + + 6 + + + + normalsquality + + + 3 + + + 32 + + + 4 + + + true + + + Vertical + + + Above + + + 1 + + + Quality (Roundness) + + + + + normalslength + + + 1 + + + 100 + + + 5 + + + 8 + + + true + + + Vertical + + + Above + + + 5 + + + Length + + + + + + + TextLabel1 + + + Normals + + + + + + + + + frame + + + StyledPanel + + + Sunken + + + + + Layout8 + + + + unnamed + + + 0 + + + 6 + + + + normButton + + + + 0 + 0 + 0 + 0 + + + + + 50 + 35 + + + + + 50 + 35 + + + + 0 + + + Std + + + Set standard view + + + + + lighting + + + false + + + + 0 + 0 + 0 + 0 + + + + + 60 + 35 + + + + + 80 + 35 + + + + 0 + + + Lighting + + + Calibrate Lighting + + + + + lightingswitch + + + + + + Turn Lighting on/off. + + + + + Layout10 + + + + unnamed + + + 0 + + + 6 + + + + TextLabel2 + + + Polygon Offset + + + AlignCenter + + + + + offsSlider + + + + 0 + 25 + + + + 30 + + + 1 + + + 5 + + + 5 + + + Horizontal + + + Above + + + 2 + + + Increase surface quality by setting polygon offset (OpenGL specific) + + + + + + + Spacer5 + + + Horizontal + + + Preferred + + + + 41 + 16 + + + + + + Layout9 + + + + unnamed + + + 0 + + + 6 + + + + TextLabel1_2 + + + Resolution + + + AlignCenter + + + + + resSlider + + + + 0 + 25 + + + + 1 + + + 100 + + + 1 + + + Horizontal + + + Above + + + 5 + + + Set data resolution (no effect for nonrectangular data) + + + + + + + + + + + menubar + + + + + + + + + + + + + + + + + + + + + + + + + + + + Toolbar + + + true + + + 0 + + + false + + + false + + + false + + + Toolbar + + + + + + + + png + + + + + bmp + + + + + ppm + + + + + xpm + + + + filetypeCB + + + + + Spacer3 + + + Horizontal + + + Fixed + + + + 20 + 20 + + + + + + + --- + + + + + Hat + + + + + Rosenbrock + + + + + Saddle + + + + + Sombrero + + + + + Ripple + + + + functionCB + + + + 150 + 0 + + + + Display function + + + + + + --- + + + + + Torus + + + + + Seashell + + + + + Boy + + + + + Dini + + + + + Cone + + + + psurfaceCB + + + Display parametric surface. Turn Lighting on for better quality. + + + + + + + Toolbar_2 + + + true + + + 0 + + + false + + + false + + + false + + + false + + + Toolbar_2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + openFile + + + image0 + + + Open File + + + &Open File + + + Open File + + + Ctrl+O + + + + + Exit + + + Exit + + + Exit + + + Exit + + + Ctrl+Q + + + + + coord + + + Coordinates + + + &Coord + + + Coordinates + + + false + + + + Box + + + true + + + image1 + + + Box + + + Box + + + Box + + + Box + + + A + + + + + Frame + + + true + + + image2 + + + Frame + + + &Frame + + + Frame + + + Frame + + + F + + + + + None + + + true + + + true + + + image3 + + + No Axes + + + No Axes + + + No Axes + + + No Axes + + + + + + animation + + + true + + + image4 + + + Animation + + + Animation + + + Animation + + + Ctrl+A + + + + + dump + + + image5 + + + Dump Content + + + Dump Content + + + Dump Content + + + Dump Content + + + + + plotstyle + + + Plot Style + + + Plot Style + + + Plot Style + + + false + + + + wireframe + + + true + + + true + + + image6 + + + Wireframe + + + Wireframe + + + Wireframe + + + Wireframe + + + + + hiddenline + + + true + + + true + + + image7 + + + Hidden Line + + + Hidden Line + + + Hidden Line (EXPERIMENTAL!) + + + Hidden Line (EXPERIMENTAL!) + + + + + polygon + + + true + + + true + + + image8 + + + Polygon only + + + Polygon only + + + Polygon only + + + Polygon only + + + + + filledmesh + + + true + + + true + + + image9 + + + Mesh & filled Polygons + + + Mesh & filled Polygons + + + Mesh & filled Polygons + + + Mesh & filled Polygons + + + + + nodata + + + true + + + false + + + image10 + + + No Data + + + No Data + + + No Data + + + No Data + + + + + pointstyle + + + true + + + image11 + + + Points + + + Points + + + Points + + + + + + color + + + Color + + + &Color + + + Color + + + Color + + + false + + + false + + + + axescolor + + + Axes + + + &Axes + + + Axes + + + Axes + + + + + backgroundcolor + + + Background + + + &Background + + + Background + + + Background + + + + + meshcolor + + + Mesh + + + &Mesh + + + Mesh + + + Mesh + + + + + numbercolor + + + Numbers + + + &Numbers + + + Numbers + + + Numbers + + + + + labelcolor + + + Label + + + &Label + + + Label + + + Label + + + + + titlecolor + + + Caption + + + Caption + + + Caption + + + Caption + + + + + datacolor + + + Data Color + + + Data Color + + + Data Color + + + + + resetcolor + + + Reset + + + &Reset + + + Reset + + + Reset + + + + + + font + + + Fonts + + + &Fonts + + + Fonts + + + false + + + false + + + + numberfont + + + Scale numbering + + + &Scale numbering + + + Scale numbering + + + Scale numbering + + + + + labelfont + + + Axis label + + + &Axis label + + + Axis label + + + Axis label + + + + + titlefont + + + Caption + + + &Caption + + + Caption + + + Caption + + + + + resetfont + + + Reset + + + &Reset + + + Reset + + + Reset + + + + + + floorstyle + + + Floor Style + + + Floor Style + + + Floor Style + + + false + + + + floordata + + + true + + + image12 + + + Floor Data Projection + + + Floor Data Projection + + + Floor Data Projection + + + Floor Data Projection + + + + + flooriso + + + true + + + image13 + + + Floor Isolines + + + Floor Isolines + + + Floor Isolines + + + Floor Isolines + + + + + floornone + + + true + + + true + + + image14 + + + Empty Floor + + + Empty Floor + + + Empty Floor + + + Empty Floor + + + + + + openMeshFile + + + image15 + + + Open FEM files + + + Open FEM files + + + + + normals + + + true + + + image16 + + + Show normal vectors + + + Show normal vectors + + + + + grids + + + true + + + grid + + + grid + + + grid + + + false + + + false + + + + front + + + true + + + image17 + + + Action + + + Action + + + Front Grid + + + + + + + + back + + + true + + + image18 + + + Action_2 + + + Action_2 + + + Back Grid + + + + + right + + + true + + + image19 + + + Action_3 + + + Action_3 + + + Right Grid + + + + + left + + + true + + + image20 + + + Action_4 + + + Action_4 + + + Left Grid + + + + + ceil + + + true + + + image21 + + + Action_5 + + + Action_5 + + + Ceiling Grid + + + + + floor + + + true + + + image22 + + + Action_6 + + + Action_6 + + + Floor Grid + + + + + + + 89504e470d0a1a0a0000000d49484452000000100000000d0806000000a0bbee240000009049444154789c9d92410ac4200c457f4ab65de4429e6c6018989365e1755cf40076a18106621503f2157d21ff23e59c31ab9452b5bdaad2f3ee588155956c5933535a99603491aa12cf461cc156c4ccb55c00500008e41cc351736ed260a0a05ce2cea6724ad8b48718435ee3ea16fce3371b030b1efe7ce7e0ffd732e916f660e091c10e0cf40c803dd83558a9e81fdc37d14cdbb2be9c140000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000009e49444154789c633c76ec1803b5010b2e09df88f7ff3f7efa4d9261ac2c8c0c5c5c2cd80db5f37af5ffd0363146121dc860e7f5eaff8f9f7f1998a869e0a16d628c3f7ffe4335945203617c265c12e41ac8c0008d283baf57ff79785818ecbc5efd27d5506c0e8147d4b6554264b9129b38464451038c1a3a6a2895002c7751cd50e4ec4a1543711628d43290810129ef9353983030e02950c829f2f00100bdf84c6a92a74e8d0000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000006e49444154789c633c76ec1803b5011332c7ceebd57faa1b4a2d306ae8a8a1a3865203c0b239d50cb5f37af5ffd03631460c430f6d1363b4f37af59fd48205d94006060606167405304998c1c88a893110aba1a4188ecd40bc8612321c978144194a8acb493614dd707c8026891f00185139a40ba3f8e90000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000009f49444154789c633c76ec1803b501133e493baf57ff49a19dfd5eff6760606060c4e6523baf57ff0f6d136324c795ae816ffe6375293906c25cbb7bbd08231336097200cc21765eaf505d4a890b91cd801bea15f68ea44881d1e80eb1f37af59ff1d8b16364470c2e7d58639f12000f537223089bbe43dbc418475d3a925dca0463906328b23e640ba8e652640b2876293607a1b8941c9a2e799f81818101000a06a3357133957f0000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af4000002cb49444154789ced97cd6b134118879f6d420ba5474f62ff0441410f2e054fb9d4a3207ab5a8d05341a95aa546a8c58f2a9e02d2f6e6492f82a41e7a119115f16040a490a326d9cb26fd486c63348c87cd6c6626b3695a68eba12f2c939979dff7f7cce76e1ccff33848eb3b50f54380ff0120a9565cd7153627cff39cdd0a6c97b34f75948d66e9baae884bd44d58c6d8f2ca3ec7f3bc48bc1baddad76d4654d16ed0b23f6906026432f0b7de7e7a496afac87a26038d5af84058de7dd6f6d7f6c0f3c7303109953c08113e08b877159abfedeb192b7c19ca43303eaefbdf3c0fd747e1e95258d700fccf61b99a87be7e48f4436220146f36f4c038e15c3605c08973cbb689eab05d1d4375c3aac2b96c8a522120bff22336b6d90807914ea72d00ad5a62009c44b804cd063c7c054fdee881ea7248e15221c02f06e4577e4629a5bfb4b9b7615bd4de7a1989743add5a71c4ed4b885b1788ea663f2072d994c8655302104b2f4e8ac5e961b1383d2c66c606c5ccd8a000c4dc7d3dd6cc0188e818c64d99464b7b8d4b850080d16b5f599c1ec62f96231fc771b8b3f08b0737e0eca911462e7ed472e6b229de7f5f6662d2d88452cc7c6cc27e3188e24c71c709af8946152ae58d28565aa910b0d50a8900c223988e4064298fa629ac8a4a6159aeaf8587fe4f0d2ac106c96442f3f58b01f58a01b055a68314e0dd87e5aec2e6a8a7e66b5adf6aa54ab3d93400cad4d70c807a251ce5d1634722c752a14d1a3762f95b0aabb7a5dc5836681c0b805f0ca85537239feac66604600aab0053f3b58e0bc9148a834faa8e7eb16ca7b5089b2336df7caeeb0ac7d19747cb65ce40ac393ac076c2aacdbe040898bd32a4b5abfb449b0193d416d48bb0ea17f70695edda45649202acafd578f47a67df04aad940d5b69e3e484cf25e846d10b63c8efc6362be5e6de54e857bb108208ed424de5380bdb433a78f8b4f5fbe750c62dffe17d8c4f71520ce0e01fe01ed94001160906df80000000049454e44ae426082 + + + 789cbdd45b4fdb301407f0f77e8a08bfa1e99034899d68da03f7fba5dc61da83e3246d81722db430edbbcfe76f070d08d39e963f48f9d5a7c6764e989b0d4ef7b683d9b9cec3588f872630037d1fcc968fa3d1f3f71fdf7e7666ba61607f940cba335f3a3334084c20425cf0269c71e01538e7c04f70c181e7d951cc81fb70c681c7b0e6c0d7ecaee4c0f7b0e2c0353bd61cf8929de0822b38e3c025ac396c71011749e1f76360c3c138be9f2669e2c70b1817bc066769e6c74fe03ccd9dc510d6a9f6e38b7091367faf0b9bd4784bb84a2bef295b86b239ef235849e5ad1b4b9c87c0fe64269bf5dcc2b9f4eba13d58cb663d5b70219bf59cc246faf508377f294b3f7e0857b259df315ccbda7bc256a16ad67b00472af2de8563157b4770a29af3dd8753957adfc0f6f2eec1996af627e09c03efc04619df8f195ca9caf59f183456158cfe437bb87e4960fb402337df066c0fd4f7e3f2abdd7ce8bface0605cc12633be5f5fe0322b5dbf0af4571e71301ec3499ec4eeefafc3b68162f7fd25d83ec0d8ede70ecef22c467fd2336c72e3fa5de03cf29283f190ad430e8c7ed74aab14fb134563edd647302ed4a770cd81cfd9789ddd7ce86ffbfa24caed27877120f0196c38f036db841c78158e38f0021c73e047981fa87bdf1f603e6037ff08ae38f0155c73d83dfc3f29933274f5bd3109d25490a1b22515d5d4a7416fec7a8b867441977445a3d65cd30dddd2c0bd87b6f28eeee981c62d79a4279ad0d4d716f44c2f344f0b9f6460b3e86b0d2dd132add02a3e7d1ff7e99aaf2d699d3668d37eda9e016db5d47e366f5bedff9a771bf958bbd33a2b6797f63ed4f6de659f0ee8d03e87897d6a7fafbdb1955b7464e73cb6bf27ffb886099dbe3eb7f6da333aa7107791adeefada8a624a5a6a535fdbb3bb93beb62645995ddfdbda5c9010b8e395376be85b4d847e5b2b0a2184c1fdb12845e56b07f64ca6fccd37b5b5e80b773f154371e16aed3bf4d909fc11fb0efdfadaf90db563e86f + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000036249444154789cad955f485b6718c67fc71c63625193e11facc6d6ceaca9b55d7ae18522bd50acb13427548d10e386462c0c7b212d2c92ad7485c2d04ba1174abb9be1dd50a8f462ea5a5c87b8ddc82a6a2f8a7fd0760612ab47433c9e846f17838d4e5775f4b97ebf1fcffb3eeff77dd2d4d4141f5a29c73d70f76ea10804be17efab918f0af3f97c229148c36e7fc2a9534edc6eb7906599919111e97f396d686810555555f4f77f8bc1f09a8a8acfe8ebeb2391481c587f28545114e1f178181c1c241c0e939efe07e1b0896bd7bc381c0e9a9a9af68de250a8244974767602303c3c8cc3616263432299cc201008b0b3b3733ca76eb75b9c3bf73977ee4c73fbf697cccfcf73f1621eba2e989d7d85d56ac566b3d1dcdcfc8edbf706959a6aa2ac2c84ae47989e7e84a669dcbbf70579795f110afd4c3cfe94643289d1683c9a534551c4f5eb01b6b63ec2ebb563b797e072b9387ffe6336379f70f3e6d74c4c4cd0d3d343341a3d1a5492242e5fbe81ae434e4e84999919aaababb15ab3387122055dcf233f3f9ff2f2720c06c3e150455144454525cbcbf99c3d0b2b2bbfa2aa2a4ea7134982e2e24f585e8664126c361bd9d9d98743f7f6f690652b53535bc8f2ef3c7b3641515111369b0d803367f2585b83adad04f1781c8bc582dfefff3b2ce9df77dfe3f188e2e262eedfff81070f72585fbfc1dada530c0603252525689a86c552425a5a3f66f337cccefec4f6f636aaaa323a3a2a1de854d334fc7e3f60c3e13071eb5623b1580c9fcf87dfef27232383a2222b261354567ae9eeeea6a5a5054dd3febbfddcdc5cae5ef5323e0e57ae08c6c646292b2b23140ae1f57a515595c64637a5a599a4a656d0dede4e6b6b2b66b3f960687d7dbde8e8e86075351f21e0f4e930939393288a4266662691488468344a4e4e36972ec1cb97a069505050406161213e9f4fbc03adabab1356ab95b1b15f78f8f00d172eacf2fcf98fa8aa4a4d4d0d009b9b9b689a86d168a4b414c261585901b3d94c5b5b1b1b1b1bff04e5f178444a4a0ac160909327ed3c7ebcca8b178fd8d98922cb32b5b5b5389d4ee6e6e6181f1fa7abab8bc5c57516173b494fff8db76fbf63696989dddd5d2c16cb5fd06030287a7b7bf7bd8b03030362616181582c0640229120994ca2eb3a0059599fa2eb7176775f3134342401b85c2eb16fa53e848efd9d1c457f02e3f74bd7fe3f92e00000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000032f49444154789ccd954b48aa6b14869f5fff3684110a6184a905890e0a0cb1081a841199a24245176c104917880641749b37e832286892831a3588a068e2406ad04428a22b5d402a68521405997929ed3f8320d8b4f7ae7d3883b3868bf53debfdd6fbf12d21140af15f87ec6f0f381c0ec9e9744a7faa11bf0b6b6d6d9592c924e9741abd5e8fcbe592445164757555f8574aebebeba5caca4a666767c9cacaa2a4a48489890952a9d42febbf84badd6ec9e3f1e0f7fbb9bdbd45ad5673717181c3e1c06432d1d8d8f869145f420541a0b3b313809595152c160bd7d7d7c4e3713a3a3a8846a37fa7d4e572494545450c0e0e323030c0c9c909656565bcbebeb2bfbf8f4aa542abd5d2d4d4f493da3f1a258a226363631c1d1db1b0b0403299647a7a9a4422417f7f3f0a8582743acd8f1f3fbea7d4ed764bcdcdcd545555d1d7d787c160c06eb7333f3f4f6e6e2e3d3d3dacafaf333c3cccfdfdfdf7a08220d0d5d5852008dcdcdcb0b7b787cd66c36ab5623018787c7c242f2f0fabd58a5c2eff1aea76bba58a8a0a0a0b0b01d8d9d921128960369b114511bd5ecff1f131a9540aad564b4e4eced7d0979717323232686b6b636969898d8d0d743a1d5aad1680d2d252c2e130f7f7f7c4e371944a255eaff7c3ac4f46793c1ec96432313636462010606a6a8aebeb6be472392d2d2de8f57aeeeeee8846a3f4f6f6120e87797a7a221289f05b683299c4ebf562341a311a8de8f57a7c3e1fdddddd188d4600a2d128e170188bc582d3e9e4fcfc9c999999df43d56a350d0d0d004892442010a0b8b898d1d151b2b3b33ff25b5b5b442211464646383b3bc3eff7ff7aa675757592cfe743a3d100707373c3e6e6266eb7fb0308ef2fc366b3b1bdbd4d2c1643a3d1909f9f4f6b6babf413b4b6b65652a954048341262727d9dddd25180c128944a8aeaefe64667979395757579c9d9d919999497b7b3b0f0f0fef4d43a1101e8f4792c9640c0d0d515050c0f2f232070707c462314451a4a6a606b3d94c4646c6c7f50f0f0f595b5b43a7d3a15028b8bcbc249148a0542adfa1434343d2f8f8f8a77f716e6e4e3a3d3de5f9f9f923f7f6f6462c167b37441449a552c864321617170500bbdd2e09ff8b75f29df8072ad2411c44a7ba050000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000001f149444154789ccd95bf6b5a5114c73fef298d20c14715b120e2f806e990ada34aab0ebe27a2832e85f817b410dedfe01808b45b978810a18180a393e1b5a1b482143a6490fe701031a9b4b12ae8ed906290e7cfd2a107ce70bff7dccffd9e33dc2b99a6c9bf0e79db03d96c56a45229b1aac6be292c97cb89c964422814c2e170904c2685dd6ee7f4f454fa2b683a9d16d16894e3e76f80cb3faa0bcf93fec2fab5ed6b9a26745de778ff037cdf994b5555c964329651ac756ab3d978f9f802ae772c7be7cf6e70edffb4e82ba19aa6897c3e0fd76f97d6288a62d156b66fb3d938f4376e5d2ec9482482aeeb732358eaf4cee5fb55f7f2eac125ca783ca72d854a92c4e1f01c862b99b38ed642354d13e17018ae3eae27021e8f676ebd70a6e3f19893de3bb8fab5512a8a42a15098cdd5e254d775a1aa2af43e6fe41260efd11ed56a75b6b64047a31117df3e6d0c0478715642b9b96bda02f57abdf0a5b51514e09eebfe62682291105ffb7d7e6c8d04bfdf4f2e9713e572599a4163b19870bbddf4fa8b1f8975f1bad1e0e1ee2e0092699ae8ba2e6459c6300c82c120954a8566b3492010c0e7f3e1743a797a743407393938a0d3e900d0ed7669b55a0c87431445b9851a86218ac5a2e55dacd7eba256abd16eb767da743a653018ccd5c9b24ca9549200e2f1b890fe8bef6493f80da5c2b9a2130355fd0000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000002af49444154789ccd953d4c535118869f7b7b2929a505c34fd55aa988112126c41023098383290dd8de188146347132ea6270eaee62181c5c4c18d88418217670c1451773a3c60583160d52498c3f840a2df4f68a2dc7413dd814f9310e9ee44ddeefdcef3cf77cdfb93f8a6118fceba16e77416767a7e8eaea121be5685b855d8844c4c2b76fe4f3791af7ec410f8584aa69c46231e5afa017755d4c8ebb80121a3a05cf6e7f052af00452ebe66f5a7e5f28245edca986c552582ca5c2e391fef3dd5a7ababb8b5ab12934abaab0502ad5d2da4ad3f925192f2f2f6f6fa7a1504834eddbc7c99b2e58b0e3bd32c750db24e97c9ef1c7c7197f72029fcf476f6f6fc16e37eca9db66e361772900fdd7e7d12c8be61b694ccbe2522c46b5c3415e08ec767bc1ba3f42c3e1b0b81c08c0c22c00b51e0fb3915d0034c5e0d5a92a99bbe3d6e4d6ca7702d7caa72099856496b14f9fa46fdcbf5f7a9259ec36dbe6d070382c5adadae04b562abdb424fd3dc70c91d91a19f794956d0e5d5959a14c51389d3b085fb2f47b0354d5d515dce4e5bb77d2dbdc6ece9d3d2b0faba8a7baae8b63f5f58ccc3e05e068898f0f6363b8148533b6dd845329a69c4ed29939faca8f104f2448659749a7d3fc11aa59160fe6decaf819aff16654e2ce5578fff30d5a82fbce9d8c3c7f24f35c5fd79eaaa2f26babab61de94ba10eca1f9d0a18239e64d0eb7b616c4e50ec71ac4300c29afdb2dd250a0030d0d4573bf146a6f97fe6a7dbdf0d7d509c330d6caefe8e810355555247feb0d402e9522b9de69026f3e7e94d7aecccc30e47201a0188681aeeb425555a2d1287ebf9fd1d151262626304d13bba6313c3dbd2eb4d7efc7b7772f4ea7934422816559545656fe8046a35131303050f45d1c1c1c14f1789c4c2623e7565757314d13004dd3c8e572a8aacaf0f0b002100c0685f25ffc4eb632be03f01c3f1b679402620000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000025449444154789cad95bf4b725118809ffb71cda09f46dca1a5fe0169edd2108498e2d022414d91fd030d39b555343605d190181886e020b8b40971c5868c96a2200871b0a0522aaf50be0d1f5e3efbae7dfad1b31ddef33ee73de73d87a31886c14ff3abd3048fc7237ebf5f7e4cbabcbc2c9aa6e176bb191d1d6d296e5b3a313121b95c8e603048575717434343e8ba6e2b6e4baaebba288a42bd5ea756ab717777c7d3d3139148846030f897f89fd29b9b1ba9d56a00c4e3719e9f9f595f5fa7bbbb9bc1c1414cd3ecbcd2442241b95ca6582c128d46098542cccfcf53a954787878a0afaf8f4020d054edb7d2442221b1580c4dd3000887c3e8ba0ec0f1f1313b3b3bf4f7f7333232d294a77c774fabd5aa4c4f4fdbc63e3e3e787b7bc3e17090cfe795b6a4ad3adb8a6c366b895b6e3f9d4ed368d0fbfb3b22cd6b346276d84a2f2e2e646f6f8f72b90cc0fefe3ed168d48a9f9c9cb0b2b2c2ebeb6bfbd2a5a5250e0f0fd1348dfbfb7b76777771381c0098a6c9d1d111e3e3e3389dcef6a46b6b6b522a95e8e9e90160606080adad2d666666005055158fc783d7eb45555500cecfcf595d5db5ce47fd2a9d9b9bb384004ea7d31236a4b3b3b34d39bdbdbd140a05fb4a53a9942c2e2ee272b96cb7d58ab1b131dc6eb7bdf4f4f4d46a4e27a8aacac6c606979797bf8fc0300c0cc3c0344d7979799106f57a5d229188e4f3791111797c7c94838303b9bebeb6e65c5d5d492a95923f310c03756a6a4a32998c727676a67cad20994ccaeded2dd56a5501d8dede96c9c949161616acb99b9b9b323c3c6c8d7d3e9f7cfb4cff978ebf9376f80482fc1c4c4b56a72d0000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000018b49444154789ca595c16ac2401086bf4421822028b2143df80a3dbaf8183ea78fa1b9f424f4d46bcd412c2156c1404c7a48679b351b6ddaff363bb3ffcc3f339b789bcd86b6582e7401b05a879ecbdf6d43a67549f6087e1b524194c3cb7bf47fd2f97c5e9c4e27263e4c7c188d468d95ff8a546b5d789e479ee7e62c8e63e36b4daab52ed2340560301810e5a5fc5eafd778e72ee972a18b890f4992b0dbed2cdff178b412b7aa1440290560fa09309bcd2cbb8abb2b15fdb490e9746af9aed72bd001200ced7d6dacd43500e92740a7d331f6afe44b900c28cbb29a54f1b9e0241539499200d0edd6bb140401e7f3d9495a8b9677fdf6794629c57ebf472965645f2e17b34e411000a24017f22d68ec69bfdf07e0f94931f1e1703898aaa5152e054ed22887d78fb816381e8f0da9eb4e75536a11699a321c0ead0b2e922ab22cb39259956aad0b194e1b484b641e5da80f4756a75a511cc79682bb49aac676bbfd7e19f632974986264918869e1412e5a5bd5adf90defe16c40e433929096e9f63d399f7977fd4237c01356dabc16040cf010000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000000a949444154789cedd4210ec2301886e1b764084e0306f38969041804090acb1948b8010967d805309304fb131cc7014c512c7475ed1024fb64c59357fca93333badea073b1477f8216ed07493e07343317a10093c52609bcd715d02a95e4a7ab35f04a423f8b4a8bd13309ba5627cccc05a8245f6ee7e4560628c030b1f2723c37950d2ac9cf76259086b6d794a656d6fb5b50095048f2cbc31878e4e57dcd01d9c71ea1fd7ffa1fe81b2e1b2dcf4b906cbb0000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000000b549444154789ced94210e843010456736bd018223ec1d8ac490705e120c92b90ba266cdcaa2a6197e0b0858b109dff1075eff6f1b5844e86ebd6e273ed09f401d1adefb780528229c4175609fabb68b611a4f3d0de4d05460d57629317e7ca62ca9c210d4f47524229a8785756edfb5811254cd008b20ace9eb68c1d8aa9814810a38d2fbfbd99c83b329f7aa63624c86da24b575c234f23c2c8cf5f1d4ed5e2668c9b4b2f54bd7a82426a2cb973d833effd3ff80aec3fb78ab235e84730000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000006049444154789ced94410a00310803a3ecabfc3ff9d6eea950aca79a1e169a63846110d148421d97132ff408f4c94544bc1d20495ba063b0031c429ecb5de01cd94e6721afca6e24a659c8abb29bb66925e46a4b003000ed635fa0f79ffe03fa017ed12c22088282610000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d49484452000000100000000d0806000000a0bbee24000000b449444154789c9d92b109c3301444ef9b0ba4c94a1ec08517c8162e3580cb6ce1055c6400155e47858a182cf8298284432c47e8e07302f18ee34bb22c0bfea91f1f1acfb319647fd794c0b319244e0c8b2e250d728d66330801a06ddb54d15a2b39700f470949edb68069f5b85f6f785e98858fc21b00099e568f6e0b70defd784e0d80049f795624d5bfbcf68ae4248be770076ac2d91e3fcb1b096bad084975de55c1c0ee156ae01400a00afe0a28d1d13f780395128c0ebcec51330000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000003d349444154789cad955d4c935718c77fefcb8b1d8375654851b4ad4416d88749759822ebdc3242305cf015207cc4cd091931123232b30e2f5d3243e2c7c55822178b81086431d130038b78e1dce21b8dcb00c900d18c0db715c720016d2994becf2eb05860cc64f19f9c9be79cffff3ce7fc9273145dd7791672166549ff455d01d0c285f06478623de5e5e589a2287477772faf8bf40328e14e9f165c515121f3f3f3f87c3e1c0e075eaf974d9aca2d2659ed53230be1e2ea9d8b8b8bc5ed76d3dcdc4c5c5c1c3b76ece0f467c7f8c878c8bcacf42e1f3f5291c18b4083f10285c5959c3c758ad6d656ac562b13f7ee92bfd1c4a449e168289efdab32d4d5a191e1374351442950535303c0850b17c8743aa9fce30eea8d6bdc79ef30edbed01aefbaa100e5626170fbeb7ce2f170e4c811868686c8c8c8e077037e2a39c8424616369b8d4365256b41ad07a9a8a8483a3b3b191c1ce4ecd9b3dcbf7f9fc4c4441e3c7880d96c263636965028446660862f03134f3ad4751d5dd7f12721e1a1eb3a5b3626487d7dbd1886218661486969a954555589aeeb929e9e2ec78f7f2e133775b95e53295713357914e1d5feadc3cd856fca2975036fb876a12c06f1fe3d455f5f1f8d8d8deccec8207fd34becedf91acb77177939c14a833c87e962effaf4014a0c0b1fa624937cee0c0b3f5c66f4d5ddcccecee2743ad114855da62886a682ec3ed38669f3566e65ee793aa8bb0b217aede9d4a91606141377bebf8add6ec766b381a6e12b3bc0c94706d30949cc2d04b199e3682d2f5ce6a2f8935801a9a0a040525252686b6ba3a7a7878e8e0ebc5e2f515151a4a6a6e27038989c9ca4bfbf1f97cbc56fa3a324cd4e73626e826455881663e5f1b71766496dc8c42bd97b49b3db486b68c0e170505d5d4d6d6d2d6969692082e997515efbf9470a1ffe49d28b0662183c3f67a0893ca11fa6766c638c746e35cbecbb4e0994e5c842739334969788dbed969999191111916050825f7d2157766e974b79efc8e2e56fe4dee56ef9d81a27df5a3788aeeb4b771a267f32b8815f0f7f4a5c470fdafb87f0dd1de1af1bd7c9cfcfc76c363f46aba11dac63bcee28a7032af3ee6cac7bdee2da96540ec56c5e092a373757e2e3e3e9edbdc289b6730c6c72d0b5f36d2ef943646767af81e972b9181f1f67646484989818f61ff880a9e9e92550baae53505020aaaae2f178d8b66d1be7cf9f67606000bfdf8fa669e4e4e4e0743a898e8e064044b87dfb365d5d5dd8ed76626363191b1b23100860b15896423d1e8f343535ad79435b5a5a647878189fcfb75c330c03bfdffff82634161717515595f6f6760560dfbe7da23cabef2452fff94afd5ffd032309c5843513f3e00000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000001d649444154789cad94bd6e13411485bf593b71a0c146c2a1020ccf00c52e72401148aca248502081441f3a9078803c000554d0d3514488c2a141518c3c083a1e00cc4f43369158689238b22f0d331acf4c420239cd68eedd337beeb9335769ad396c247b25db7921075967e7d70540c594b6f3426edf9a63e1ce7b75509557ae6f48f4d07f413b2fa4db692af0ca3765003c7d76417ce25e3007b6f3e2ff95ba0a0daa00833495fec4595a3b9ff85c39c599e157bb7eacb43837ec07f17ee534ade117ba5a2bff274a6bcd5a96cb74af6393db692635dd0b9ae4c77d9e4102d090722ca8109e3f3a1278aa180ff93ca3340128d5b12079f3dee65faf538cd7ed345515a02e3ff9955d9629d9b6c9eff377e5f8c6878034485301d85235eacef7aed2aaf963b3b7ac5ce2c9974f02a5833495c93f8d99048aec9a34234a13a3d447cc531f319ef5f487aa07c9fd781ae359a5b12ebe5afc26ae62b377d78694366f5ea0bda765362b0923a622c6ef862d55634442bdf73aa8a80a705436310d587a3892b9a58b76efc26f94b90946e1d84071bdb9f120d9f7b87379eefbb79e1aaf008654a287b8f1179716a521250b57df842f4f6bcdcacc7dc976ded9e1b1969c607ab46ef7bbc5df4e9c6766f57150d9a10d6917bf0149be09d8da731f230000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000022049444154789cbd544d6b1351143d379f6d864ea682465d48d322fe8350c6121424b571ef42a9086ebaf00f7415b7baa94217821604578a6e131a2c81e03c24bf40d1dae2424d049b843469c666ae8b38d397f9282d8a67f378e7bd7bdeb9e732434208fc6b44820e4c5de78fe1699c1f7cc666388d99c1165aa422c96d67bf1d3e87a9c11767dd8ca431b3bf05f2737a7bbec60f07f7a1bd794d32dfd72f725c188772f5b96b1cf273f96c3d4389ee370f4fe0402e9b6f30004c5a3b1811b50f00a0379ef27b2f10d5e22902802625fddb07803d7d8e4d8ac2faf36e0816e26ca24f315808814150b88b7d446086c610e65f600063dc3f709abffe9365b71d52a01a15baa13e85666c5041590681515096a1191b74537d829810c444d0de9669c2a8906a54a849c9a16836dfe0e2cb1324b731c11d0040b19426005829e788415829e7c8e6efccbf63f068ce1ab786a2b6908c9e72c613897b506bebb3e42edc21edc0a95b20b1fbd5376b19f7aebc62f74393dc0c1ed4eea5ab1c35db81825d1a47827b6090d3c11ec5612134fca2b2f906bb23889a6dc48418e14c5d679b8b01b89babf0834e010951753853d73930d3ae72f6f0de01ac962f7beafe7fa6ef6f3de2e94f2f503fad23f55de0472a8393f59ab3da7c4bbb8064f383b3af46f5a1a85fa647c1c2c236974a539e3a4fa68f9f67bc7f8d00c88272849e4c97166b47762cd7c9c61ca7c771280bf90dd971bab458732e1c67f59b45e0f4ff06bf01765c1564eeb8ff4b0000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000018b49444154789cad94bd4e02511085cf6c02283f020df8136da8b4a222e49290d068dc589b6882356fe05368a9f696da8a89da68e426121b5f4134c62d600984c8168c05b98bb8a0bb614f738bbd33fbcd99b943524af82dedaf8f45dd602fe76de9902d21982691167583f7f7765029d7c92d9d25040340478b616252afb284e00e45d198cf60a3f7325ebe2a0300cece73ec0c9f4e18e32eb277a764527c36524b087ed3966184d790edd6d1a330a2dc1d91eabb4d4f4d39d87a6600785d5847fee698340c30c75fe85074485ad40d7ea8a65c3745e9b3a073ba56256541435bc1eae07d483a29a11b4f936cc2286cdbf7328f1764527c98f4678394dc8c539f4288700f412909009a854d4e707b36d210f71191f776acf27426d21625008cc6ea434b23a6baefa7a72d4af8eba9fad1bfa4d3cecb238d43dcc753e90400d00b2fc112826b81bc3f730a8c7c0d4a490e52b76f5e95aa129a14b76d7078ea65dd9914b70953b56b3bce26f542a894e0369a5a72ac5163a495729dbc6e7a19c861f1f1ca51992f4bfab7be019433035af1a435310000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000001b749444154789cad944f4b1b4118879f775bb361ab348945db2248f150f00388cc4a3c94169b43a128bdf7de0fd4bb070f1e7a2901e9a12071ce822741d4937f626b23d8e82ed5d74399ed26ae66433a971766769ff799df0c23d65afef7f0b22663633436463f2c6c2940b5d6cc555fbd3b5100c9323d0e6b1a143c46be7f957e2d5fbfffa1b74c6363b4ac2dfce8b42f98b3fdf6e589744077e79614a060adb483677d41d7eb63e2e00934364627ae0f28582bcdf0ad16db477d19a6e19e03ee0dbd00a031ff494b7ac685041d3fdd559d61ba89586bd9ac7e544faf7979b58322146d432213aa6f37ee3da86aada9dd50808700d37fb639976104c5812e82a7f83db69e054c328dc4a7a897c9426c8c06edc31ec8db79ba461e80af1187de780204888aa33da1f79afe9212538dd5e48382b5e25ffe1cccb4ac2d4ec337c91d05683f7a3e986977a600c1ef83c14cd399c2df5cf7a71601f8bc3ca377d5f5fa9874cf27f7f438ace9f8465ddc21c1bf187a9966459064eac6f9c8642ea0db6aba4107b4258f39091714a0b2b692fbb94b83d20d3c80929ef160b89cdb300dca3a2c0fa031344b656d45f2bef0e99a9569e6cb3fe8b801fd070405ed1b07300000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a5960000018549444154789ced95414b024114c7ff6f152b08db223d98873282fc021dc6f21015e8a50f10de3dd457a83e46f7e8d6d98282c0720e42e782b02e5b9041b9218186be2eedb0ee4eb946dd7a97997d33fffffce6bd852129257e3bc2ba645b080680ebd01ce63b37782113e3dc402d3483d9ce9defdb191bc618ccaeed376d0bc18f460cb5c51d88f226188421b4109192d2005e33cb6cb28d371a41fafc800020fda933bb3676cd6d90fbfa0e2100300804f69ef965d81445ac724c3dd76f0bc1969140eae29000e0617d8b279f2e119192bc87ea728e61365f679252fa363f67d6388c77442b674aaccb79419c50a4f7e124a684e0dbd03452dc846524302c043b4d68191318ed3671b5b4c1aa3980cf5091aee42c3e3d4af62c0689d59cc5271a9d01003ac3bdfd85be5dd21966f375369c8977b158a8f625d7e9caa53819cee427a43add3f697fd2efc672294edebcfa4fb3f93aeb8c8390ea743ed220b574c2ad7397c257d320b5d419b90f50a48310ba8d74cd52a4c542556d1864d4d594fee28dfa001f1808dc614860130000000049454e44ae426082 + + + 89504e470d0a1a0a0000000d4948445200000015000000150806000000a917a596000001b349444154789ced94bf6b144114c73fb3b7779eec9122c64b90588414162a5888e244b7500cdc220111442336da68e79f23889585b6a6486171e081235af9a34825118c928c21a0b9c0b9c7f92c64c6cbdd1073674a1f2cb36fdebcef7ededbc728630c7b6dd14ec134b332c87a61eeab00a810699a5999bf7e893b375fab41292f5e5e97a0e8309666561a8b55053de5bb3200ee3f3a25bd893b99134c33fbefa4dd84ce3c69767563a09fe2d65e414f1afadab0949e3414d84d4f4379696625722fbdc1dd8c5328afb15855ff498727bd3bdb089206873fd75abe4c9ee7d04a1d3b7e9aeada2bb62a87499a9f589bd08caf1ab62a9324cd15ecc419aaab2ffdb9b7f131fae634d75a004ac6047db7d7a1c0e3f2156ed5eff59ddb469a6b2dadf218e5d6fadf2aa74d91226def6faa0a075e3cfb73a1d46a1fe5f3d9390118a92fa86eaa9231aafb71fb8979aeae8d3cf4a24ed08b3efd36cffe2461293e02809da9499ba2f79d6dcccc4a4bedf3ad78f2fd36363ab8ad350031c09bf8382736df532a4cfdee57344a51da942427d75a3e14a698ee2cf3231aa5f2b3c9d2b91b32dd59e65d7c94938d077d53b2679774b7fd0274cf01d1d4dbcbe90000000049454e44ae426082 + + + + + Exit + activated() + Mesh2MainWindowBase + close() + + + lightingswitch + toggled(bool) + lighting + setEnabled(bool) + + + + diff --git a/lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindowbase4.ui b/lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindowbase4.ui new file mode 100644 index 0000000..7da1ef5 --- /dev/null +++ b/lib/tqwtplot3d/examples/mesh2/src/mesh2mainwindowbase4.ui @@ -0,0 +1,479 @@ + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + Mesh2 + + + + + 8 + + + 8 + + + 8 + + + 8 + + + 6 + + + 6 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Std + + + + + + + false + + + Lighting + + + + + + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + <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> + + + + + + + 30 + + + 5 + + + 5 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 2 + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + <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> + + + + + + + 1 + + + 100 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 5 + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 71 + 20 + + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Ortho + + + true + + + + + + + Legend + + + + + + + Autoscale + + + true + + + + + + + Mouse + + + true + + + + + + + Shading + + + true + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + <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> + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + 3 + + + 32 + + + 4 + + + 3 + + + Qt::Vertical + + + true + + + QSlider::TicksAbove + + + + + + + + 0 + 0 + + + + 1 + + + 100 + + + 5 + + + 8 + + + Qt::Vertical + + + true + + + QSlider::TicksAbove + + + + + + + + + + + + + + + + + + + + lightingswitch + toggled(bool) + lighting + setEnabled(bool) + + + 181 + 568 + + + 144 + 568 + + + + + diff --git a/lib/tqwtplot3d/examples/mesh2/src/thesis.tex b/lib/tqwtplot3d/examples/mesh2/src/thesis.tex new file mode 100644 index 0000000..cde629b --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/examples/movie.png b/lib/tqwtplot3d/examples/movie.png new file mode 100644 index 0000000000000000000000000000000000000000..cf576825f73c319e0ef3cf50b7c6fa52458188cd GIT binary patch literal 1260 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy>?NMQuI!h1M1)0*3O6j=2o&Nh z@Q5sCVBq=y!i-L9OlANDS<)SS9T^xl_H+M9WMyDrW(e>JaRrJ`o5nDykD;%Pp{tHz zLKj0z5kpG>LvubuQyxQ8E<=49Lrpxxv?PY+JcjaMhGH*<(g22vFox<_h6`I=x6L$M z)uUeG%h1r!P#(%q7RXQ*%uo@|Ft<*&C7G)-lA))Op*4lOwS?iw3Y)f6p89l#O;h#S z%NeSo85T4u)Tc7^=L=UxGn9ug^cM(M#V|}L6k%X!`2XkI|G(e=|Nip-_vin=KmGsx z_5c6>K&Os^(GZ|+2t3QVv;=6PWl4}q&hG#Flu?aIEGZ*Iy?DpP_uzR ztH0= zT3{wACnv~b%5(YV#X_ZQx5{a1Cp{B_=FFQL9}~wIxNl#g?rGZziu1*{AGMK}Iep3g zfw@3RXypUGty84#*qii+tk@Z)wbXaU^+yihT?LJd!lR^{)xBQ-DC^i1q;NCBW`9St zmc!f3XDjTU>j^*CX_OpyIGuB|DV1qW@e%#-S%*@1O1jQk zeOq?5;M0w-UBQ=&C%s&?s)TLYT<+U(^&I*R`Z;ZZ%lQBOOkJC!#$@Xj*>~IWCeKu< zw3|7vkC;z>oHp&uwrVxG+?*MA*UjE?=R#!ltZ(uU`hVEXh=0#MH?@7@+L;~_pvd%e L^>bP0l+XkKb7n0F literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/nodata.png b/lib/tqwtplot3d/examples/nodata.png new file mode 100644 index 0000000000000000000000000000000000000000..9279c361b05f471d9dd8ffd9fbda8713190209cd GIT binary patch literal 824 zcmV-81IPS{P)_NiUX?E>Ss!&GS%4F_!;2pe?lW7+34t~qrJU7(c0Q7noOqb{{H?utUtId zU^RSD6vgk!WRe^X2bs-gIz2tbGQGx26xVC+l!0r4zmmyh0)SaIn`OJZyDT1$v!$h_ zfwQwS750bVxqLy@O=!Kny_$uEg_i&lcsg zj2C#;{|)mYZp){=y*=@2n-DogqtOBtTm{?P+lAhP!5~4?Ur;anfjBZUqQwcm9vvN3 zFe9R^tu4}OwP}q;W4g}iy}G)(L95mJ2x2a&kgJCK&!E>T)S0huJVEPm&f#qg6o|94 zvu`D7)zs7&a7*;y?mdQ+%_ngQ&CSh8$vgxlBEAFS=H})FVxE@{hr=1jk86t)z6SrW zyu57W9|6bu`nnhQdQC2uujNl3i^b$#uh)Wsgu1)CL&#}%I-O7XKqe)P7d-stuEh|y@QMeO2x^_B2f!m9CCu>D88U-knj350000R1T|)&jAW? z7I;J!Gca&{0AWU_H6}BFf-LEdzK#qG8~eHcB(gFvFgkd;IEGZ*N=`Yz6v1LDRuyk>&ZC4NDEaGvwl+Ss@U$U`9>cY?M7gWA>7&J4lcrS87 zQRtCOoPOLt23HOKfHy)X8e%4JG0xQO_v{o=sFick&UjzqUdD4~DVxK;G6g=SN7^bs z!q_{mGZiXaC{<5vI~23Zy=l5(6Gx={nWa7f=Yoxt*_`DsEWPAoz-HN&blKb_hO0|u z)h>}~i7Q?ODg4&I@_~N~M=)boESKLK0q(q}Pj(%?rqh{t!`Xw>4?HrEZsc-mm?2^u zy5JWdW2SY$PHz2h$E6|y_uDpg>iQ&nan)Gcog=Nh#ZHLv(R`jG*Ig6#2K*6!aY+A! a5QEz0eN(so?VAJ)TLw>8KbLh*2~7Y45vcM2 literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/normals.png b/lib/tqwtplot3d/examples/normals.png new file mode 100644 index 0000000000000000000000000000000000000000..427574a20d8f8b7bc7d3236e720df407dab4a81c GIT binary patch literal 1344 zcmV-G1;6@tg54vAC%000SaNLh0L01EH`01EH{Laa2H00004XF*Lt006O%3;baP000EfNkld6R4TK#w|5)IaeMYlKuYJ&5_V#VND&UQq%8dF1;R$C2;op9!K|u@ z#p2MQprA%iPtOvU%jK=nX!aByoW7A?k@D;c60z zB$+&GNlHq3zP!9#ER)F~A|itO>eEjY@9|IHwj;bmXWt}_5EEFg<<;w&UM`0uuy;Mq!CgykZJD9+2ow2zNUXV_-&I9*f( zp`oGB-`@|fXJx^|mTPe5wIkpN31_t0>vC>>w(9bRr87GgXUE8Xnjz5;+SCvRqMO)H zf-_!TUbz&%%QZDMUVVLiP+3_CV`F2WR;yuhauUcxpff;;!$jNs>^HUvWS^DU&DE>s z5OXUfRc-Qxy&7Mio)afd*m<5uf$Z#T%+1Zk&dyE@3k$=NlFxDCW+(pk)*INa<{S(D zFi*B-VlTIH?H`27A^M191jt_TQUrt2(u>*MHLK*t``C(UA7vl0V zUd`BvSK^*S$6XW7n`h8qFxUbD0*4AiV1Q;0_0)LAc&Mi&wTUh+V z1Nn9#rb3&(NI0pU>WnT+%=Xk>;?O`XgccUMMe_6W!DuwP%L))d{9p*e@7{)ePalK7 zk_XBpcrNh_hbWY$Q}lrh?$Ac4)sMgCrQ5=!8+N>6n-xK8BjA&9sQ$SHY!Xknbm>!J)U~y>u>%7GGP C1#y}H literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/polygon.png b/lib/tqwtplot3d/examples/polygon.png new file mode 100644 index 0000000000000000000000000000000000000000..1b0bacf0e2b74d6c6c556ff62a11752a4e743dcd GIT binary patch literal 733 zcmV<30wVp1P)Hu#5U52J2!M zwcD6?124LeE|iFB4K2D!(haRdrc;^9@p$ZUCFtl(9reHiFYkGu&-p&@`#cZ8e=ur< zvz*y%zO7cPuQr=aZLwHflO*X4?u*BQs#L0Jo6WY`YPDwFZZ{xUj>qE?%d*e&`TS!% z(jF-l1YAd8CJ+eJ+MAQ@UPtA7gphNGW0(O<1JCm>eLkP-#l5#`Xt2=h8=p>5qA2RC z)#}F3>Fad5fL^a({rSwUQ#xaO@U2v-R4(E&)!n0yQmN5s7Ut&W#-Kz%$uSeP$z;0Q z8>k3HmA4p%IkW88B2ZF+l6$>gd@uGUhOpgOcCgCLBQJf;{&kEO#k07yqW@5Yc2rUn zHMQJ`6KKFd!;EyOb_VNK5lT?yLyyP9Lh?2j3E*%zD4blKdVSSR zpKu)a6jd(0&ScnQFc0iJ$5ra}`i)LET*I`NXqvth3WZ>6Vgkb9FeH;na5|lU6RK0U zaDQc`53s(t*u=4SAPQ5K)9JKiZZrtC?HvjO76d_<3I>Bae!u@amPWf)tI@Go%#uhX zY|&_RJeSMayD+>W8Nc_n1Pc0sW%vOH%QiO6lTjxBFvb{-#`%BD{B6GgXUf~~Pnt2f P00000NkvXXu0mjf1NK)7 literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/qwtplot.png b/lib/tqwtplot3d/examples/qwtplot.png new file mode 100644 index 0000000000000000000000000000000000000000..8e1ca4ed5084c10f6a7df195bab5542962c7763a GIT binary patch literal 543 zcmV+)0^t3LP)WdKcSAUPmUYjhwoFfcM8GBG+bG&(adAS*C2FfelaDyRSe00(qQO+^RN z3JDV-0YPGT^8f$<32;bRa{vGe@Bjb`@Bu=sG?)MY00d`2O+f$vv5yPT>q(M79%!8Z@l`(NS<*Bz%(d=;*2O03lQ^yXsWpwXqXbKgw#eB z5wQy_!Xg`id>x7n1{%V}A}%?LO_c_x~R*p8J16Q{wvt4e>0BT+GPMp1`51$;4@30_L-;YB2Eohq5v-F=YZ>%}18O zpve0F>z4_yhaU?Q4=>avMh1c4DCYk^f2c5V^SF{_Fteag03!>F7_XB%ia5Kv76Z49 zBQvw0a4yhtHlhs%DLyOB;q(9Z?+$*yP-c+#QG$n+jX@;6fR&Mv(Tr7Ewh-NLCM*Ur zo|R;?2PG*c4$kF3Lxn~2D%e5ZM+cmSray#|vl;(=`CQMYsL~JA%M6plme83Q+1O24 zrDWd;gva&sdH6kL;^Fy)!($Km+0@?kEP)WdKuQATuCMVQC;TFfcP9F)=zbGdeRfAS*C2Ffc}2v<3hG00(qQO+^RO z1p^5p3d)^u4gdfE32;bRa{vGi!vFvd!vV){sAK>D00d`2O+f$vv5yPR0_lJcDs?kg({_Vv)MR~1JDB5Xhi2T zozK1Lbeg6qF{<5ece@Uyp-Xi}yG4Z!4EtdmDp+xhuI2&J#dJ<4X=B#g+IZVH+fU(lfRpc{@DCbm& zsE|Y$5SXjJ&8h{6e0H~yY}a*=vhQkMp64Mm_;S6BB7&DOB#eIol8vJiq8Q%ocF1{* ob}RY5?0k0A_?wisxJUrM0R3zbBpsm?mH+?%07*qoM6N<$f+zCm=Kufz literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/scattered.png b/lib/tqwtplot3d/examples/scattered.png new file mode 100644 index 0000000000000000000000000000000000000000..a23a865d8da185f54ea99530406903900072d987 GIT binary patch literal 479 zcmV<50U-W~P)Uo|c_xoDXXRr_%;yCU}JxQ?`o%J+ThIL?67w(Wtxm=uAe ztdC%Q_S|esnWp*T)r6oSG;Jt!RaLC}c8WL>*e5+5A6?rWBBiWAWm%3==fwL0yPQoQ zzlgv&v{17qisIH7>g!IY^;Z@Y=2H2dW7S|wX} zD+q!(wiKfB?S>R3DUKN~i!gKpcrIL|2kFdSSzg z18VM7RqboWHboRgY002ovPDHLkV1fh#&DsC} literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/examples/simpleplot/simpleplot.cpp b/lib/tqwtplot3d/examples/simpleplot/simpleplot.cpp new file mode 100644 index 0000000..e21ca26 --- /dev/null +++ b/lib/tqwtplot3d/examples/simpleplot/simpleplot.cpp @@ -0,0 +1,83 @@ + //----------------------------------------------------------------- + // simpleplot.cpp + // + // A simple example which shows how to use SurfacePlot + //----------------------------------------------------------------- + + #include + #include + #include + #include + + + 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/lib/tqwtplot3d/examples/simpleplot/simpleplot.pro b/lib/tqwtplot3d/examples/simpleplot/simpleplot.pro new file mode 100644 index 0000000..836dc60 --- /dev/null +++ b/lib/tqwtplot3d/examples/simpleplot/simpleplot.pro @@ -0,0 +1,3 @@ +include( ../common.pro ) + +SOURCES = simpleplot.cpp diff --git a/lib/tqwtplot3d/examples/wireframe.png b/lib/tqwtplot3d/examples/wireframe.png new file mode 100644 index 0000000000000000000000000000000000000000..862842974afa9e6008d1db1f3776a1fa8dd391d5 GIT binary patch literal 1119 zcmV-l1fctgP)Hoi_DIGsqSp^2!1PnSFGB*g>E)cdUQ6O_zWHE3<7zk6BctK+1 z!VBUqB-`#ZAu(Jm@uK`}!Rex+L0Nz$kOJ$hG-Jp8Gg=l?)e z)kR@wXh;{2$DJ~ntn{FuI*ms2d1GT^_Q=SH(&zI*rTP;-p91yuO(-rdR%B&m_0T@< znL*WR_3IqR6?SxVq>ULH8zUeEfh*o|g2!Ra;wY+B?W)LL`>0TCL&B3m4|pqUguW%-isI z9uZJ3ES8TDi+zV^^bRpjFi{kJCX=arW@ctRbymp4QmIt-o^nKK{4<#KV|-QB#~?f!?LBm>K|mM2eMmWm=^Hv2IR9d#@(SD;iv)O#pX0tU94t}G!e%*}q^~(fsCsiWsb~|==1KbPax1>FvJ#KQViHQi7aRq>ms~6C?CgBh)YRl9 zm)Z9AwuH(ykB*MMOnPa^sPsUgQ72GaQbUM=)V*H+l13DxiCAp;SBl{;RMi?a&Bqyg l|2Y@0*X!T?pE3Vle*v)vk@Ed?&OrbG002ovPDHLkV1lBe4p0C9 literal 0 HcmV?d00001 diff --git a/lib/tqwtplot3d/include/qwt3d_autoptr.h b/lib/tqwtplot3d/include/qwt3d_autoptr.h new file mode 100644 index 0000000..15d46e5 --- /dev/null +++ b/lib/tqwtplot3d/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 +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& 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/lib/tqwtplot3d/include/qwt3d_autoscaler.h b/lib/tqwtplot3d/include/qwt3d_autoscaler.h new file mode 100644 index 0000000..31c7497 --- /dev/null +++ b/lib/tqwtplot3d/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 +#include "qwt3d_global.h" +#include "qwt3d_autoptr.h" + +namespace Qwt3D +{ + +//! ABC for autoscaler +class QWT3D_EXPORT AutoScaler +{ +friend class qwt3d_ptr; +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& 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 mantissi_; +}; + +} // ns + + +#endif diff --git a/lib/tqwtplot3d/include/qwt3d_axis.h b/lib/tqwtplot3d/include/qwt3d_axis.h new file mode 100644 index 0000000..08c2928 --- /dev/null +++ b/lib/tqwtplot3d/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 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 scale_; +}; + +} // ns + +#endif diff --git a/lib/tqwtplot3d/include/qwt3d_color.h b/lib/tqwtplot3d/include/qwt3d_color.h new file mode 100644 index 0000000..23daf3f --- /dev/null +++ b/lib/tqwtplot3d/include/qwt3d_color.h @@ -0,0 +1,63 @@ +#ifndef __COLORGENERATOR_H__ +#define __COLORGENERATOR_H__ + +#include +#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/lib/tqwtplot3d/include/qwt3d_colorlegend.h b/lib/tqwtplot3d/include/qwt3d_colorlegend.h new file mode 100644 index 0000000..186840c --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/include/qwt3d_coordsys.h b/lib/tqwtplot3d/include/qwt3d_coordsys.h new file mode 100644 index 0000000..8d536c1 --- /dev/null +++ b/lib/tqwtplot3d/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 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/lib/tqwtplot3d/include/qwt3d_drawable.h b/lib/tqwtplot3d/include/qwt3d_drawable.h new file mode 100644 index 0000000..4324d6c --- /dev/null +++ b/lib/tqwtplot3d/include/qwt3d_drawable.h @@ -0,0 +1,66 @@ +#ifndef __DRAWABLE_H__ +#define __DRAWABLE_H__ + + +#include +#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 dlist; +}; + +} // ns + +#endif diff --git a/lib/tqwtplot3d/include/qwt3d_enrichment.h b/lib/tqwtplot3d/include/qwt3d_enrichment.h new file mode 100644 index 0000000..e4d427a --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/include/qwt3d_enrichment_std.h b/lib/tqwtplot3d/include/qwt3d_enrichment_std.h new file mode 100644 index 0000000..a17bf58 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/include/qwt3d_function.h b/lib/tqwtplot3d/include/qwt3d_function.h new file mode 100644 index 0000000..4351920 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/include/qwt3d_global.h b/lib/tqwtplot3d/include/qwt3d_global.h new file mode 100644 index 0000000..d759107 --- /dev/null +++ b/lib/tqwtplot3d/include/qwt3d_global.h @@ -0,0 +1,58 @@ +#ifndef QWT3D_GLOBAL_H +#define QWT3D_GLOBAL_H + +#include +#if QT_VERSION < 0x040000 +#include +#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/lib/tqwtplot3d/include/qwt3d_graphplot.h b/lib/tqwtplot3d/include/qwt3d_graphplot.h new file mode 100644 index 0000000..a1ded9f --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/include/qwt3d_gridmapping.h b/lib/tqwtplot3d/include/qwt3d_gridmapping.h new file mode 100644 index 0000000..c7893e5 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/include/qwt3d_helper.h b/lib/tqwtplot3d/include/qwt3d_helper.h new file mode 100644 index 0000000..0c1bfd7 --- /dev/null +++ b/lib/tqwtplot3d/include/qwt3d_helper.h @@ -0,0 +1,36 @@ +#ifndef __HELPER_H__ +#define __HELPER_H__ + +#include +#include +#include +#include + +namespace +{ + inline double Min_(double a, double b) + { + return (a0) ? int(d+0.5) : int(d-0.5); +} + + +} //ns + +#endif diff --git a/lib/tqwtplot3d/include/qwt3d_io.h b/lib/tqwtplot3d/include/qwt3d_io.h new file mode 100644 index 0000000..aa2cd1f --- /dev/null +++ b/lib/tqwtplot3d/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 +#include + +#include +#include +#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 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/lib/tqwtplot3d/include/qwt3d_io_gl2ps.h b/lib/tqwtplot3d/include/qwt3d_io_gl2ps.h new file mode 100644 index 0000000..2bbeb43 --- /dev/null +++ b/lib/tqwtplot3d/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 + +#if QT_VERSION < 0x040000 +#include +#else +#include +#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/lib/tqwtplot3d/include/qwt3d_io_reader.h b/lib/tqwtplot3d/include/qwt3d_io_reader.h new file mode 100644 index 0000000..772946c --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/include/qwt3d_label.h b/lib/tqwtplot3d/include/qwt3d_label.h new file mode 100644 index 0000000..debff42 --- /dev/null +++ b/lib/tqwtplot3d/include/qwt3d_label.h @@ -0,0 +1,80 @@ +#ifndef __LABELPIXMAP_H__ +#define __LABELPIXMAP_H__ + +#include +#include +#include +#include +#include + +#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 ( QChar(0x3c0) etc.) please look at www.unicode.org. + */ + 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/lib/tqwtplot3d/include/qwt3d_mapping.h b/lib/tqwtplot3d/include/qwt3d_mapping.h new file mode 100644 index 0000000..be10b87 --- /dev/null +++ b/lib/tqwtplot3d/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 +#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/lib/tqwtplot3d/include/qwt3d_multiplot.h b/lib/tqwtplot3d/include/qwt3d_multiplot.h new file mode 100644 index 0000000..1678b70 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/include/qwt3d_openglhelper.h b/lib/tqwtplot3d/include/qwt3d_openglhelper.h new file mode 100644 index 0000000..e5499c2 --- /dev/null +++ b/lib/tqwtplot3d/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 +#else +#include +#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/lib/tqwtplot3d/include/qwt3d_parametricsurface.h b/lib/tqwtplot3d/include/qwt3d_parametricsurface.h new file mode 100644 index 0000000..9bcdb9f --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/include/qwt3d_plot.h b/lib/tqwtplot3d/include/qwt3d_plot.h new file mode 100644 index 0000000..668b29c --- /dev/null +++ b/lib/tqwtplot3d/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 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 displaylists_p; + Qwt3D::Data* actualData_p; + + +private: + struct Light + { + Light() : unlit(true){} + bool unlit; + Qwt3D::Triple rot; + Qwt3D::Triple shift; + }; + std::vector 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/lib/tqwtplot3d/include/qwt3d_portability.h b/lib/tqwtplot3d/include/qwt3d_portability.h new file mode 100644 index 0000000..e6a6d9d --- /dev/null +++ b/lib/tqwtplot3d/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 +#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 + +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/lib/tqwtplot3d/include/qwt3d_scale.h b/lib/tqwtplot3d/include/qwt3d_scale.h new file mode 100644 index 0000000..d6619ec --- /dev/null +++ b/lib/tqwtplot3d/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 +#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; + + 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 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; +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; +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/lib/tqwtplot3d/include/qwt3d_surfaceplot.h b/lib/tqwtplot3d/include/qwt3d_surfaceplot.h new file mode 100644 index 0000000..f84f2df --- /dev/null +++ b/lib/tqwtplot3d/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 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/lib/tqwtplot3d/include/qwt3d_types.h b/lib/tqwtplot3d/include/qwt3d_types.h new file mode 100644 index 0000000..63f27d1 --- /dev/null +++ b/lib/tqwtplot3d/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 +#endif + +#include + +#include "qwt3d_global.h" + +#if defined(Q_WS_WIN) + #include +#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 [x,y] +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 [x,y,z] +/** +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 FreeVectorField; + +//! A point field in R^3 +typedef std::vector TripleField; +//! Holds indices in a TripleField interpreted as counterclockwise node numbering for a convex polygon +typedef std::vector Cell; +//! Vector of convex polygons. You need a TripleField as base for the node data +typedef std::vector 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 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 DataRow; +typedef std::vector 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& idx, const std::vector& src ); + + +#endif // QWT3D_NOT_FOR_DOXYGEN + +} // ns + +#endif diff --git a/lib/tqwtplot3d/include/qwt3d_volumeplot.h b/lib/tqwtplot3d/include/qwt3d_volumeplot.h new file mode 100644 index 0000000..da2dcbe --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/lingua_de.ts b/lib/tqwtplot3d/lingua_de.ts new file mode 100644 index 0000000..d553d3b --- /dev/null +++ b/lib/tqwtplot3d/lingua_de.ts @@ -0,0 +1,10 @@ + + + NativeReader + + NativeReader::read: cannot open data file "%s" + + + + + diff --git a/lib/tqwtplot3d/qwtplot3d.pro b/lib/tqwtplot3d/qwtplot3d.pro new file mode 100644 index 0000000..d4fa0c1 --- /dev/null +++ b/lib/tqwtplot3d/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.6 + +# 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/lib/tqwtplot3d/scripts/fixvc7.py b/lib/tqwtplot3d/scripts/fixvc7.py new file mode 100644 index 0000000..968337a --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/scripts/makedistro.py b/lib/tqwtplot3d/scripts/makedistro.py new file mode 100644 index 0000000..4af5ce5 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/scripts/makedocu.py b/lib/tqwtplot3d/scripts/makedocu.py new file mode 100644 index 0000000..b6a233d --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/scripts/qwtplot3d.supp b/lib/tqwtplot3d/scripts/qwtplot3d.supp new file mode 100644 index 0000000..ebe0720 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/scripts/valgr.sh b/lib/tqwtplot3d/scripts/valgr.sh new file mode 100644 index 0000000..6c3090a --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/src/qwt3d_autoscaler.cpp b/lib/tqwtplot3d/src/qwt3d_autoscaler.cpp new file mode 100644 index 0000000..6e785cf --- /dev/null +++ b/lib/tqwtplot3d/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& 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 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(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& mantisse) +{ + init(0,1,1); + if (mantisse.empty()) + { + mantissi_ = std::vector(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/lib/tqwtplot3d/src/qwt3d_axis.cpp b/lib/tqwtplot3d/src/qwt3d_axis.cpp new file mode 100644 index 0000000..fe45f37 --- /dev/null +++ b/lib/tqwtplot3d/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(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(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/lib/tqwtplot3d/src/qwt3d_color.cpp b/lib/tqwtplot3d/src/qwt3d_color.cpp new file mode 100644 index 0000000..5543a8a --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/src/qwt3d_colorlegend.cpp b/lib/tqwtplot3d/src/qwt3d_colorlegend.cpp new file mode 100644 index 0000000..2b114aa --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/src/qwt3d_coordsys.cpp b/lib/tqwtplot3d/src/qwt3d_coordsys.cpp new file mode 100644 index 0000000..2aae28d --- /dev/null +++ b/lib/tqwtplot3d/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(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 beg(axes.size()); + vector end(axes.size()); + vector 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 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/lib/tqwtplot3d/src/qwt3d_dataviews.cpp b/lib/tqwtplot3d/src/qwt3d_dataviews.cpp new file mode 100644 index 0000000..7a022dd --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/src/qwt3d_drawable.cpp b/lib/tqwtplot3d/src/qwt3d_drawable.cpp new file mode 100644 index 0000000..4025817 --- /dev/null +++ b/lib/tqwtplot3d/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::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::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/lib/tqwtplot3d/src/qwt3d_enrichment_std.cpp b/lib/tqwtplot3d/src/qwt3d_enrichment_std.cpp new file mode 100644 index 0000000..d20ffc2 --- /dev/null +++ b/lib/tqwtplot3d/src/qwt3d_enrichment_std.cpp @@ -0,0 +1,347 @@ +#include +#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/lib/tqwtplot3d/src/qwt3d_function.cpp b/lib/tqwtplot3d/src/qwt3d_function.cpp new file mode 100644 index 0000000..28d874e --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/src/qwt3d_gridmapping.cpp b/lib/tqwtplot3d/src/qwt3d_gridmapping.cpp new file mode 100644 index 0000000..4de521b --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/src/qwt3d_gridplot.cpp b/lib/tqwtplot3d/src/qwt3d_gridplot.cpp new file mode 100644 index 0000000..6543785 --- /dev/null +++ b/lib/tqwtplot3d/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 (i0 && j0 && 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 (i0) + { + 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 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/lib/tqwtplot3d/src/qwt3d_io.cpp b/lib/tqwtplot3d/src/qwt3d_io.cpp new file mode 100644 index 0000000..c9ce46b --- /dev/null +++ b/lib/tqwtplot3d/src/qwt3d_io.cpp @@ -0,0 +1,355 @@ +#include + +#include "qwt3d_plot.h" +#include "qwt3d_io_gl2ps.h" +#include "qwt3d_io_reader.h" +#if QT_VERSION < 0x040000 +#else + #include +#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 list = QImageWriter::supportedImageFormats(); + QList::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); + + 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"or "PDF". + If zlib has been configured this will be extended by "EPS_GZ" and "PS_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 text, VectorWriter::SORTMODE sortmode) +{ + if (format == "EPS" || format == "EPS_GZ" || format == "PS" + || format == "PS_GZ" || format == "PDF") + { + VectorWriter* gl2ps = (VectorWriter*)IO::outputHandler(format); + if (gl2ps) + { + gl2ps->setSortMode(sortmode); + gl2ps->setTextMode(text); + } + 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") + 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/lib/tqwtplot3d/src/qwt3d_io_gl2ps.cpp b/lib/tqwtplot3d/src/qwt3d_io_gl2ps.cpp new file mode 100644 index 0000000..be94e51 --- /dev/null +++ b/lib/tqwtplot3d/src/qwt3d_io_gl2ps.cpp @@ -0,0 +1,387 @@ +#if defined(_MSC_VER) /* MSVC Compiler */ +#pragma warning ( disable : 4786 ) +#endif + +#include +#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", "EPS", +"PS", "PDF" (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 + { + formaterror_ = true; + return false; + } + formaterror_ = false; + return true; +} + +//! Performs actual output +bool VectorWriter::operator()(Plot3D* plot, QString const& fname) +{ + if (formaterror_) + return false; + + 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 + + " (beta) , (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); + + producer += " Micha Bieber "; + + FILE *fp = fopen(QWT3DLOCAL8BIT(fname), "wb"); + if (!fp) + { + Label::useDeviceFonts(false); + return false; + } + while( state == GL2PS_OVERFLOW ) + { + bufsize += 2*1024*1024; + gl2psBeginPage ( "---", 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); + 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(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); + + 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/lib/tqwtplot3d/src/qwt3d_io_reader.cpp b/lib/tqwtplot3d/src/qwt3d_io_reader.cpp new file mode 100644 index 0000000..2cc57a7 --- /dev/null +++ b/lib/tqwtplot3d/src/qwt3d_io_reader.cpp @@ -0,0 +1,225 @@ +#if defined(_MSC_VER) /* MSVC Compiler */ +#pragma warning ( disable : 4786 ) +#endif + +#include +#include +#include + +#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/lib/tqwtplot3d/src/qwt3d_label.cpp b/lib/tqwtplot3d/src/qwt3d_label.cpp new file mode 100644 index 0000000..eb8b8c0 --- /dev/null +++ b/lib/tqwtplot3d/src/qwt3d_label.cpp @@ -0,0 +1,262 @@ +#include +#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()); + 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(); +#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/lib/tqwtplot3d/src/qwt3d_lighting.cpp b/lib/tqwtplot3d/src/qwt3d_lighting.cpp new file mode 100644 index 0000000..2f368a0 --- /dev/null +++ b/lib/tqwtplot3d/src/qwt3d_lighting.cpp @@ -0,0 +1,192 @@ +#if defined(_MSC_VER) /* MSVC Compiler */ +#pragma warning ( disable : 4305 ) +#pragma warning ( disable : 4786 ) +#endif + +#include +#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/lib/tqwtplot3d/src/qwt3d_meshplot.cpp b/lib/tqwtplot3d/src/qwt3d_meshplot.cpp new file mode 100644 index 0000000..0c975fe --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/src/qwt3d_mousekeyboard.cpp b/lib/tqwtplot3d/src/qwt3d_mousekeyboard.cpp new file mode 100644 index 0000000..800bc06 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/src/qwt3d_movements.cpp b/lib/tqwtplot3d/src/qwt3d_movements.cpp new file mode 100644 index 0000000..73ff9b1 --- /dev/null +++ b/lib/tqwtplot3d/src/qwt3d_movements.cpp @@ -0,0 +1,106 @@ +#if defined(_MSC_VER) /* MSVC Compiler */ +#pragma warning ( disable : 4305 ) +#pragma warning ( disable : 4786 ) +#endif + +#include +#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/lib/tqwtplot3d/src/qwt3d_parametricsurface.cpp b/lib/tqwtplot3d/src/qwt3d_parametricsurface.cpp new file mode 100644 index 0000000..c3103c9 --- /dev/null +++ b/lib/tqwtplot3d/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/lib/tqwtplot3d/src/qwt3d_plot.cpp b/lib/tqwtplot3d/src/qwt3d_plot.cpp new file mode 100644 index 0000000..e61b125 --- /dev/null +++ b/lib/tqwtplot3d/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(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(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/lib/tqwtplot3d/src/qwt3d_scale.cpp b/lib/tqwtplot3d/src/qwt3d_scale.cpp new file mode 100644 index 0000000..ecac454 --- /dev/null +++ b/lib/tqwtplot3d/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 (idxstop_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 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 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 SurfacePlot::facets() const +{ + if (!hasData()) + return pair(0,0); + + if (actualData_p->datatype == Qwt3D::POLYGON) + return pair(int(actualDataC_->cells.size()), 1); + else if (actualData_p->datatype == Qwt3D::GRID) + return pair(actualDataG_->columns(), actualDataG_->rows()); + else + return pair(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/lib/tqwtplot3d/src/qwt3d_types.cpp b/lib/tqwtplot3d/src/qwt3d_types.cpp new file mode 100644 index 0000000..b6f3a4d --- /dev/null +++ b/lib/tqwtplot3d/src/qwt3d_types.cpp @@ -0,0 +1,222 @@ +#if defined(_MSC_VER) /* MSVC Compiler */ +#pragma warning ( disable : 4786 ) +#endif + +#include // qsort +#include +#include +#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=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(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(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& idx, const std::vector& 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