summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--RELEASE_NOTES5
-rw-r--r--bison.pri4
-rw-r--r--boost.pri64
-rw-r--r--doc/TODO.txt1
-rw-r--r--doc/release-checklist.txt6
-rw-r--r--doc/testing.txt56
-rw-r--r--eigen2.pri39
-rw-r--r--examples/example008.scad8
-rw-r--r--flex.pri4
m---------libraries/MCAD0
-rw-r--r--openscad.pro11
-rw-r--r--patches/OpenCSG-1.3.2-MacOSX-port.patch70
-rwxr-xr-xscripts/git-archive-all.py171
-rw-r--r--src/CGALCache.cc2
-rw-r--r--src/CSGTermEvaluator.cc2
-rw-r--r--src/OpenCSGRenderer.cc4
-rw-r--r--src/OpenCSGWarningDialog.ui3
-rw-r--r--src/Preferences.cc14
-rw-r--r--src/ThrownTogetherRenderer.cc6
-rw-r--r--src/colornode.h3
-rw-r--r--src/csgterm.cc128
-rw-r--r--src/csgterm.h11
-rw-r--r--src/csgtermnormalizer.cc150
-rw-r--r--src/csgtermnormalizer.h22
-rw-r--r--src/export.cc39
-rw-r--r--src/glview.cc9
-rw-r--r--src/lexer.l21
-rw-r--r--src/linalg.h6
-rw-r--r--src/mainwin.cc28
-rw-r--r--src/openscad.cc4
-rw-r--r--src/parser.y15
-rw-r--r--src/renderer.cc2
-rw-r--r--src/renderer.h2
-rw-r--r--src/state.h16
-rw-r--r--testdata/scad/features/cylinder-tests.scad5
-rw-r--r--testdata/scad/features/include-tests.scad4
-rw-r--r--testdata/scad/features/intersection-tests.scad2
-rw-r--r--testdata/scad/features/sub1/sub2/sub3/sub4/include-test2.scad4
-rw-r--r--testdata/scad/features/sub1/sub2/sub3/sub4/use-test2.scad14
-rw-r--r--testdata/scad/features/sub1/sub2/sub3/sub4/use-test3.scad4
-rw-r--r--testdata/scad/features/sub1/sub2/sub3/use-test4.scad4
-rw-r--r--testdata/scad/features/use test6.scad7
-rw-r--r--testdata/scad/features/use-test5.scad4
-rw-r--r--testdata/scad/features/use-tests.scad39
-rw-r--r--tests/.gitignore4
-rw-r--r--tests/CMakeLists.txt202
-rw-r--r--tests/CMingw-cross-env.cmake144
-rw-r--r--tests/FindGLEW.cmake10
-rw-r--r--tests/OffscreenContextWGL.cc4
-rw-r--r--tests/csgtestcore.cc21
-rw-r--r--tests/dumptest.cc3
-rw-r--r--tests/echotest.cc2
-rw-r--r--tests/regression/cgalpngtest/cylinder-tests-expected.pngbin12498 -> 11017 bytes
-rw-r--r--tests/regression/cgalpngtest/intersection-tests-expected.pngbin8295 -> 7455 bytes
-rw-r--r--tests/regression/cgalpngtest/use-tests-expected.pngbin0 -> 10852 bytes
-rw-r--r--tests/regression/dumptest/cylinder-tests-expected.txt3
-rw-r--r--tests/regression/dumptest/intersection-tests-expected.txt2
-rw-r--r--tests/regression/dumptest/testcolornames-expected.txt4
-rw-r--r--tests/regression/dumptest/use-tests-expected.txt34
-rw-r--r--tests/regression/opencsgtest/color-tests-expected.pngbin10950 -> 10389 bytes
-rw-r--r--tests/regression/opencsgtest/cylinder-tests-expected.pngbin13165 -> 11612 bytes
-rw-r--r--tests/regression/opencsgtest/example010-expected.pngbin33501 -> 29480 bytes
-rw-r--r--tests/regression/opencsgtest/example015-expected.pngbin8632 -> 8542 bytes
-rw-r--r--tests/regression/opencsgtest/example021-expected.pngbin20930 -> 20220 bytes
-rw-r--r--tests/regression/opencsgtest/intersection-tests-expected.pngbin8069 -> 7273 bytes
-rw-r--r--tests/regression/opencsgtest/use-tests-expected.pngbin0 -> 11165 bytes
-rw-r--r--tests/regression/throwntogethertest/color-tests-expected.pngbin10215 -> 9795 bytes
-rw-r--r--tests/regression/throwntogethertest/cylinder-tests-expected.pngbin8670 -> 11612 bytes
-rw-r--r--tests/regression/throwntogethertest/example008-expected.pngbin8557 -> 8362 bytes
-rw-r--r--tests/regression/throwntogethertest/example010-expected.pngbin35604 -> 30990 bytes
-rw-r--r--tests/regression/throwntogethertest/example014-expected.pngbin9140 -> 8797 bytes
-rw-r--r--tests/regression/throwntogethertest/example015-expected.pngbin8826 -> 8677 bytes
-rw-r--r--tests/regression/throwntogethertest/example021-expected.pngbin27112 -> 26151 bytes
-rw-r--r--tests/regression/throwntogethertest/intersection-tests-expected.pngbin8006 -> 11327 bytes
-rw-r--r--tests/regression/throwntogethertest/use-tests-expected.pngbin0 -> 11618 bytes
-rwxr-xr-xtests/test_cmdline_tool.py26
-rw-r--r--version.pri21
77 files changed, 1087 insertions, 406 deletions
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 6e83502..9722a01 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -4,6 +4,10 @@ OpenSCAD 2012.XX
Features:
o Snappier GUI while performing CGAL computations (computations running in separate thread)
+Deprecations:
+o The old include syntax "<filename.scad>" without the include keyword is no
+ longer supported and will cause a syntax error.
+
OpenSCAD 2011.12
================
@@ -19,6 +23,7 @@ o New import() statement reads the correct file format based on the filename ext
(.stl, .dxf and .off is supported)
o The color() statement now supports an alpha parameter, e.g. color(c=[1,0,0], alpha=0.4)
o The color() statement now supports specifying colors as strings, e.g. color("Red")
+o The color() statement now overrides colors specified further down in the tree
o if()/else() and the ternary operator can now take any value type as parameter. false, 0, empty string and empty vector or illegal value type will evaluate as false, everything else as true.
o Strings can now be lexographically compared using the <, <=, >, >= operators
o Added PI constant.
diff --git a/bison.pri b/bison.pri
index 7d3bed0..9840c5a 100644
--- a/bison.pri
+++ b/bison.pri
@@ -22,6 +22,10 @@ unix:freebsd-g++ {
QMAKE_YACC = /usr/local/bin/bison
}
+unix:netbsd* {
+ QMAKE_YACC = /usr/pkg/bin/bison
+}
+
unix:linux* {
exists(/usr/bin/bison) {
QMAKE_YACC = /usr/bin/bison
diff --git a/boost.pri b/boost.pri
index c2f5d8e..e313d40 100644
--- a/boost.pri
+++ b/boost.pri
@@ -6,35 +6,65 @@ boost {
!isEmpty(BOOST_DIR) {
QMAKE_INCDIR += $$BOOST_DIR
message("boost location: $$BOOST_DIR")
- win32:QMAKE_LIBDIR += -L$$BOOST_DIR/lib
+ win32: QMAKE_LIBDIR += -L$$BOOST_DIR/lib
}
- win32:!CONFIG(mingw-cross-env) {
- LIBS += -llibboost_thread-vc90-mt-s-1_46_1 -llibboost_program_options-vc90-mt-s-1_46_1
- }
-
CONFIG(mingw-cross-env) {
DEFINES += BOOST_STATIC
DEFINES += BOOST_THREAD_USE_LIB
DEFINES += Boost_USE_STATIC_LIBS
- LIBS += -lboost_thread_win32-mt -lboost_program_options-mt
+ BOOST_LINK_FLAGS = -lboost_thread_win32-mt -lboost_program_options-mt
}
- unix {
- BMT_TEST1 = /usr/lib64/libboost*thread-mt*
- BMT_TEST2 = /usr/lib/libboost*thread-mt*
- BMT_TEST3 = $$BOOST_DIR/lib/libboost*thread-mt*
+ isEmpty(BOOST_LINK_FLAGS):win32 {
+ BOOST_LINK_FLAGS = -llibboost_thread-vc90-mt-s-1_46_1 -llibboost_program_options-vc90-mt-s-1_46_1
+ }
- exists($$BMT_TEST1)|exists($$BMT_TEST2)|exists($$BMT_TEST3) {
- LIBS += -lboost_thread-mt -lboost_program_options-mt
- BOOST_IS_MT = true
- }
+ # check for OPENSCAD_LIBDIR + multithread
+ isEmpty(BOOST_LINK_FLAGS) {
+ OPENSCAD_LIBDIR = $$(OPENSCAD_LIBRARIES)
+ !isEmpty(OPENSCAD_LIBDIR) {
+ exists($$OPENSCAD_LIBDIR/lib/libboost*thread-mt*) {
+ BOOST_LINK_FLAGS = -lboost_thread-mt -lboost_program_options-mt
+ } else {
+ exists($$OPENSCAD_LIBDIR/lib/libboost*thread*) {
+ BOOST_LINK_FLAGS = -lboost_thread -lboost_program_options
+ }
+ }
+ }
}
- unix|macx {
- isEmpty(BOOST_IS_MT) {
- LIBS += -lboost_thread -lboost_program_options
+ # check for BOOSTDIR + multithread
+ isEmpty(BOOST_LINK_FLAGS) {
+ BOOST_DIR = $$(BOOSTDIR)
+ !isEmpty(BOOST_DIR) {
+ exists($$BOOST_DIR/lib/libboost*thread-mt*) {
+ BOOST_LINK_FLAGS = -lboost_thread-mt -lboost_program_options-mt
+ } else {
+ exists($$BOOST_DIR/lib/libboost*thread*) {
+ BOOST_LINK_FLAGS = -lboost_thread -lboost_program_options
+ }
+ }
}
}
+ isEmpty(BOOST_LINK_FLAGS) {
+ unix {
+ BMT_TEST1 = /usr/lib64/libboost*thread-mt*
+ BMT_TEST2 = /usr/lib/libboost*thread-mt*
+ BMT_TEST3 = /usr/pkg/lib/libboost*thread-mt* # netbsd
+ exists($$BMT_TEST1)|exists($$BMT_TEST2)|exists($$BMT_TEST3) {
+ BOOST_LINK_FLAGS = -lboost_thread-mt -lboost_program_options-mt
+ }
+ }
+ }
+
+ isEmpty(BOOST_LINK_FLAGS) {
+ unix|macx {
+ BOOST_LINK_FLAGS = -lboost_thread -lboost_program_options
+ }
+ }
+
+ LIBS += $$BOOST_LINK_FLAGS
+
}
diff --git a/doc/TODO.txt b/doc/TODO.txt
index d027c2e..97f1a95 100644
--- a/doc/TODO.txt
+++ b/doc/TODO.txt
@@ -255,7 +255,6 @@ o variants of module transparent() { %child(); }
o define modules
o define functions
o built-in variables and constants (builtin-tests.scad)
-o Write a regression test for the hexagonal cylinder orientation issue
o Caching
- Test that caching is actually performed (speedup + same results)
- Test the modifier characters correctly influence the cache (also when
diff --git a/doc/release-checklist.txt b/doc/release-checklist.txt
index 2ff9593..71158f6 100644
--- a/doc/release-checklist.txt
+++ b/doc/release-checklist.txt
@@ -2,8 +2,8 @@ OpenSCAD Release Checklist
--------------------------
o Update version
- release-linux.sh
- publish-macosx.sh
+ scripts/release-linux.sh
+ scripts/publish-macosx.sh
FIXME: Windows
o Update RELEASE_NOTES
@@ -12,7 +12,7 @@ o Tag release
git tag "openscad-2011.12"
o build source package
- git archive --format=tar openscad-2011.12 --prefix=openscad-2011.12/ | gzip > openscad-2011.12.src.tar.gz
+ scripts/git-archive-all.py --prefix=openscad-2011.12/ openscad-2011.12.src.tar.gz
o build binaries
tar xzf openscad-2011.12.src.tar.gz
diff --git a/doc/testing.txt b/doc/testing.txt
index 4623a96..f690939 100644
--- a/doc/testing.txt
+++ b/doc/testing.txt
@@ -10,7 +10,7 @@ $ cd tests
$ cmake .
$ make
-Windows:
+Windows + MSVC:
First, get a normal build working by following instructions at
http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Building_on_Windows
@@ -22,6 +22,10 @@ Then, from the QT command prompt:
> cmake .
> nmake -f Makefile
+Cross compiling Linux->Win32:
+
+Please see openscad/tests/CMingw-cross-env.cmake for instructions.
+
B) Running tests
$ ctest Runs tests enabled by default
@@ -50,55 +54,53 @@ Adding a new regression test:
Troubleshooting:
------------------------------
-0. Headless unix servers (no X11)
+0. Headless unix servers
-$ Xvfb :5 -screen 0 800x600x24 &
+If you are attempting to run the tests on a unix-like system but only
+have shell-console access, you may be able to run the tests by using a
+virtual framebuffer program like Xvnc or Xvfb. For example:
+
+$ Xvfb :5 -screen 0 800x600x24 &
$ DISPLAY=:5 ctest
-1. Trouble finding libraries
+Some versions of Xvfb may fail, however.
+
+1. Trouble finding libraries on unix
To help CMAKE find eigen2, OpenCSG, CGAL, Boost, and GLEW, you can use
environment variables, just like for the main qmake & openscad.pro. Examples:
- OPENCSGDIR=~/OpenCSG-1.3.2 EIGEN2DIR=~/eigen2 cmake .
+ OPENSCAD_LIBRARIES=~ cmake .
+ CGALDIR=~/CGAL-3.9 BOOSTDIR=~/boost-1.47.0 cmake .
- Valid variables are as follows (see CMakeLists.txt for more info):
+ Valid variables are as follows:
BOOSTDIR, CGALDIR, EIGEN2DIR, GLEWDIR, OPENCSGDIR, OPENSCAD_LIBRARIES
-2. Logs
+2. Location of logs
Logs of test runs are found in tests/build/Testing/Temporary
-Pretty-printed index.html is in a subdir of tests/build/Testing/Temporary
+A pretty-printed index.html is in a subdir of tests/build/Testing/Temporary
Expected results are found in tests/regression/*
Actual results are found in tests/build/testname-output/*
-3. Cross-compiling
+3. Image-based tests takes a long time, they fail, and the log says 'return -11'
-Cross-compiling of tests has not been automated nor tested
+Imagemagick may have crashed while comparing the expected images to the
+test-run generated (actual) images. You can try using the alternate
+ImageMagick comparison method by by erasing CMakeCache, and re-running
+cmake with -DCOMPARATOR=ncc. This will enable the Normalized Cross
+Comparison method.
-4. Image-based tests takes a long time, they fail, and it says 'return -11'
-
-Imagemagick may have crashed. You can try using the alternate IM comparator
-based on Normalized Cross Correlation. Pass -DCOMPARATOR=ncc to cmake
-
-5. Testing images fails with 'morphology' not found for ImageMagick
+4. Testing images fails with 'morphology not found" for ImageMagick in the log
Your version of imagemagick is old. Upgrade, or pass -DCOMPARATOR=old to
cmake. The comparison will be of lowered reliability.
-6. Unexplained or bizarre errors.
-
-This can happen on dynamic-library systems (linux) where you try to use
-your own version of a library while the system still has another version
-under the system paths. You can diagnose this by looking at your cmake
-log as well as your sysinfo.txt file, as well as running 'ldd' against
-your binaries, to make sure that the proper versions of libraries are
-getting compiled and linked with the test binaries.
-
-7. Other issues
+5. Other issues
-The OpenSCAD User Manual has a section on buildling. Check there for updates:
+The OpenSCAD User Manual has a section on buildling. Please check there
+for updates:
http://en.wikibooks.org/wiki/OpenSCAD_User_Manual
diff --git a/eigen2.pri b/eigen2.pri
index 44649f8..1bbb7a5 100644
--- a/eigen2.pri
+++ b/eigen2.pri
@@ -1,20 +1,37 @@
eigen2 {
+
+ CONFIG(mingw-cross-env) {
+ EIGEN2_INCLUDEPATH = mingw-cross-env/include/eigen2
+ }
+
# Optionally specify location of Eigen2 using the
- # EIGEN2DIR env. variable
- EIGEN2_DIR = $$(EIGEN2DIR)
- !isEmpty(EIGEN2_DIR) {
- EIGEN2_INCLUDEPATH = $$EIGEN2_DIR
+ # OPENSCAD_LIBRARIES env. variable
+ isEmpty(EIGEN2_INCLUDEPATH) {
+ OPENSCAD_LIBRARIES_DIR = $$(OPENSCAD_LIBRARIES)
+ !isEmpty(OPENSCAD_LIBRARIES_DIR) {
+ exists($$OPENSCAD_LIBRARIES_DIR/include/eigen2) {
+ EIGEN2_INCLUDEPATH = $$OPENSCAD_LIBRARIES_DIR/include/eigen2
+ }
+ }
}
- else {
- CONFIG(mingw-cross-env) {
- EIGEN2_INCLUDEPATH = mingw-cross-env/include/eigen2
- } else {
- freebsd-g++: EIGEN2_INCLUDEPATH *= /usr/local/include/eigen2
- macx: EIGEN2_INCLUDEPATH *= /opt/local/include/eigen2
- !macx:!freebsd-g++:!win32:EIGEN2_INCLUDEPATH *= /usr/include/eigen2
+
+ # Optionally specify location of Eigen2 using the
+ # EIGEN2DIR env. variable
+ isEmpty(EIGEN2_INCLUDEPATH) {
+ EIGEN2_DIR = $$(EIGEN2DIR)
+ !isEmpty(EIGEN2_DIR) {
+ EIGEN2_INCLUDEPATH = $$EIGEN2_DIR
+ message("EIGEN2 location: $$EIGEN2_INCLUDEPATH")
}
}
+ isEmpty(EIGEN2_INCLUDEPATH) {
+ freebsd-g++: EIGEN2_INCLUDEPATH = /usr/local/include/eigen2
+ macx: EIGEN2_INCLUDEPATH = /opt/local/include/eigen2
+ linux*: EIGEN2_INCLUDEPATH = /usr/include/eigen2
+ netbsd*: EIGEN2_INCLUDEPATH = /usr/pkg/include/eigen2
+ }
+
# eigen2 being under 'include/eigen2' needs special prepending
QMAKE_INCDIR_QT = $$EIGEN2_INCLUDEPATH $$QMAKE_INCDIR_QT
diff --git a/examples/example008.scad b/examples/example008.scad
index a12ef96..8372f6b 100644
--- a/examples/example008.scad
+++ b/examples/example008.scad
@@ -20,13 +20,13 @@ difference()
intersection()
{
- translate([ -125, -25, -25])
- linear_extrude(height = 50, convexity = 1)
+ translate([ -125, -25, -26])
+ linear_extrude(height = 52, convexity = 1)
import(file = "example008.dxf", layer = "X");
rotate(90, [0, 1, 0])
- translate([ -125, -25, -25])
- linear_extrude(height = 50, convexity = 1)
+ translate([ -125, -25, -26])
+ linear_extrude(height = 52, convexity = 1)
import(file = "example008.dxf", layer = "X");
}
} \ No newline at end of file
diff --git a/flex.pri b/flex.pri
index 2e1559e..57f854e 100644
--- a/flex.pri
+++ b/flex.pri
@@ -13,6 +13,10 @@ unix:freebsd-g++ {
QMAKE_LEX = /usr/local/bin/flex
}
+unix:netbsd* {
+ QMAKE_LEX = /usr/pkg/bin/flex
+}
+
unix:linux* {
exists(/usr/bin/flex) {
QMAKE_LEX = /usr/bin/flex
diff --git a/libraries/MCAD b/libraries/MCAD
-Subproject b7d9ec4c5e5939b2bffcda60b91f4623e9b3c62
+Subproject f32906ae90b1326a2d7241994e18c6f796799a9
diff --git a/openscad.pro b/openscad.pro
index 710a3bd..f104cf1 100644
--- a/openscad.pro
+++ b/openscad.pro
@@ -86,6 +86,15 @@ linux*:exists(/usr/lib64/libGLU*)|linux*:exists(/usr/lib/libGLU*) {
LIBS += -lGLU
}
+netbsd* {
+ LIBS += -L/usr/X11R7/lib
+ QMAKE_LFLAGS += -Wl,-R/usr/X11R7/lib
+ QMAKE_LFLAGS += -Wl,-R/usr/pkg/lib
+ !isEmpty(OPENSCAD_LIBDIR) {
+ QMAKE_LFLAGS += -Wl,-R$$OPENSCAD_LIBDIR/lib
+ }
+}
+
# See Dec 2011 OpenSCAD mailing list, re: CGAL/GCC bugs.
*g++* {
QMAKE_CXXFLAGS *= -fno-strict-aliasing
@@ -146,6 +155,7 @@ HEADERS += src/renderer.h \
src/builtin.h \
src/context.h \
src/csgterm.h \
+ src/csgtermnormalizer.h \
src/dxfdata.h \
src/dxfdim.h \
src/dxftess.h \
@@ -197,6 +207,7 @@ SOURCES += src/mathc99.cc \
src/node.cc \
src/context.cc \
src/csgterm.cc \
+ src/csgtermnormalizer.cc \
src/polyset.cc \
src/csgops.cc \
src/transform.cc \
diff --git a/patches/OpenCSG-1.3.2-MacOSX-port.patch b/patches/OpenCSG-1.3.2-MacOSX-port.patch
new file mode 100644
index 0000000..3d81dc4
--- /dev/null
+++ b/patches/OpenCSG-1.3.2-MacOSX-port.patch
@@ -0,0 +1,70 @@
+diff --git a/example/example.pro b/example/example.pro
+index 8891a28..5cb5e81 100644
+--- a/example/example.pro
++++ b/example/example.pro
+@@ -2,9 +2,16 @@ TEMPLATE = app
+ TARGET = opencsgexample
+
+ CONFIG += opengl warn_on release
+-INCLUDEPATH += ../glew/include ../include
+-
+-LIBS += -L../lib -lopencsg -lglut -L../glew/lib -lGLEW
++INCLUDEPATH += ../include
++LIBS += -L../lib -lopencsg -lGLEW
++macx {
++ INCLUDEPATH += /opt/local/include
++ LIBS += -framework GLUT -L/opt/local/lib
++}
++else {
++ INCLUDEPATH += ../glew/include
++ LIBS += -lglut -L../glew/lib
++}
+
+ HEADERS = displaylistPrimitive.h
+ SOURCES = displaylistPrimitive.cpp main.cpp
+diff --git a/opencsg.pro b/opencsg.pro
+index b56e622..5cf2d6d 100644
+--- a/opencsg.pro
++++ b/opencsg.pro
+@@ -1,2 +1,2 @@
+ TEMPLATE = subdirs
+-SUBDIRS = src example
++SUBDIRS = src
+diff --git a/src/src.pro b/src/src.pro
+index 4843a12..04d3f4d 100644
+--- a/src/src.pro
++++ b/src/src.pro
+@@ -1,10 +1,31 @@
+ TEMPLATE = lib
+ TARGET = opencsg
+ VERSION = 1.3.2
+-DESTDIR = ../lib
+
+ CONFIG += opengl warn_on release
+-INCLUDEPATH += ../include ../glew/include ../
++INCLUDEPATH += ../include ../
++
++# Optionally specify deployment location using the
++# MACOSX_DEPLOY_DIR env. variable
++DEPLOYDIR = $$(MACOSX_DEPLOY_DIR)
++
++!isEmpty(DEPLOYDIR) {
++ message("Deploy")
++ INSTALLDIR = $$(MACOSX_DEPLOY_DIR)
++ INCLUDEPATH += $$(MACOSX_DEPLOY_DIR)/include
++ LIBS += -L$$(MACOSX_DEPLOY_DIR)/lib -lGLEW
++ CONFIG += absolute_library_soname
++ headers.files = ../include/opencsg.h
++ headers.path = $$INSTALLDIR/include
++ INSTALLS += target headers
++ target.path = $$INSTALLDIR/lib
++}
++else {
++ DESTDIR = ../lib
++ INCLUDEPATH += ../glew/include
++ INSTALLS += target
++ target.path = $$DESTDIR
++}
+
+ HEADERS = ../include/opencsg.h \
+ opencsgConfig.h \
diff --git a/scripts/git-archive-all.py b/scripts/git-archive-all.py
new file mode 100755
index 0000000..ccfb08a
--- /dev/null
+++ b/scripts/git-archive-all.py
@@ -0,0 +1,171 @@
+#! /usr/bin/env python
+
+import sys
+from os import path, chdir
+from subprocess import Popen, PIPE
+from sys import argv, stdout
+from fnmatch import fnmatch
+
+
+class GitArchiver(object):
+ """
+ GitArchiver
+
+ Scan a git repository and export all tracked files, and submodules.
+ Checks for .gitattributes files in each directory and uses 'export-ignore'
+ pattern entries for ignore files in the archive.
+
+ Automatically detects output format extension: zip, tar, bz2, or gz
+ """
+
+ def __init__(self, prefix='', verbose=False, exclude=True, extra=[]):
+ self.prefix = prefix
+ self.verbose = verbose
+ self.exclude = exclude
+ self.extra = extra
+
+ self._excludes = []
+
+
+ def create(self, output_file):
+ """
+ create(str output_file) -> None
+
+ Creates the archive, written to the given output_file
+ Filetype may be one of: gz, zip, bz2, tar
+ """
+ #
+ # determine the format
+ #
+ _, _, format = output_file.rpartition(".")
+
+ if format.lower() == 'zip':
+ from zipfile import ZipFile, ZIP_DEFLATED
+ output_archive = ZipFile(path.abspath(output_file), 'w')
+ add = lambda name, arcname: output_archive.write(name, self.prefix + arcname, ZIP_DEFLATED)
+
+ elif format.lower() in ['tar', 'bz2', 'gz']:
+ import tarfile
+ t_mode = ('w:%s' % format) if format != 'tar' else 'w'
+
+ output_archive = tarfile.open(path.abspath(output_file), t_mode)
+ add = lambda name, arcname: output_archive.add(name, self.prefix + arcname)
+ else:
+ raise RuntimeError("Unknown format: '%s'" % format)
+
+ #
+ # compress
+ #
+
+ # extra files first (we may change folder later)
+ for name in self.extra:
+ if self.verbose:
+ toPath = '=> %s%s' % (self.prefix, name) if self.prefix else ""
+ print 'Compressing %s %s ...' % (name, toPath)
+ add(name, name)
+
+ self._excludes = []
+
+ for name, arcname in self.listFiles(path.abspath('')):
+ if self.verbose:
+ toPath = '=> %s%s' % (self.prefix, arcname) if self.prefix else ""
+ print 'Compressing %s %s ...' % (arcname, toPath)
+ add(name, arcname)
+
+ output_archive.close()
+
+
+ def listFiles(self, git_repositary_path, baselevel=''):
+ """
+ listFiles(str git_repository_path, str baselevel='') -> iterator
+
+ An iterator method that yields a tuple(filepath, fullpath)
+ for each file that should be included in the archive.
+ Skips those that match the exclusion patterns found in
+ any discovered .gitattributes files along the way.
+
+ Recurses into submodules as well.
+ """
+ for filepath in self.runShell('git ls-files --cached --full-name --no-empty-directory'):
+ fullpath = path.join(baselevel, filepath)
+ filename = path.basename(filepath)
+
+ if self.exclude and filename == '.gitattributes':
+ self._excludes = []
+ fh = open(filepath, 'r')
+ for line in fh:
+ if not line: break
+ tokens = line.strip().split()
+ if 'export-ignore' in tokens[1:]:
+ self._excludes.append(tokens[0])
+ fh.close()
+
+ if not filename.startswith('.git') and not path.isdir(filepath):
+
+ # check the patterns first
+ ignore = False
+ for pattern in self._excludes:
+ if fnmatch(fullpath, pattern) or fnmatch(filename, pattern):
+ if self.verbose: print 'Exclude pattern matched (%s): %s' % (pattern, fullpath)
+ ignore = True
+ break
+ if ignore:
+ continue
+
+ # baselevel is needed to tell the arhiver where it have to extract file
+ yield filepath, fullpath
+
+ # get paths for every submodule
+ for submodule in self.runShell("git submodule --quiet foreach 'pwd'"):
+ chdir(submodule)
+ # in order to get output path we need to exclude repository path from the submodule path
+ submodule = submodule[len(git_repositary_path)+1:]
+ # recursion allows us to process repositories with more than one level of submodules
+ for git_file in self.listFiles(git_repositary_path, submodule):
+ yield git_file
+
+
+
+ @staticmethod
+ def runShell(cmd):
+ return Popen(cmd, shell=True, stdout=PIPE).stdout.read().splitlines()
+
+
+
+if __name__ == "__main__":
+ from optparse import OptionParser
+
+ parser = OptionParser(usage="usage: %prog [-v] [--prefix PREFIX] [--no-exclude] OUTPUT_FILE", version="%prog 1.0")
+
+ parser.add_option('--prefix', type='string', dest='prefix',
+ default='', help="prepend PREFIX to each filename in the archive")
+
+ parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='enable verbose mode')
+
+ parser.add_option('--no-exclude', action='store_false', dest='exclude',
+ default=True, help="Dont read .gitattributes files for patterns containing export-ignore attrib")
+
+ parser.add_option('--extra', action='append', dest='extra', default=[],
+ help="Any additional files to include in the archive.")
+
+ options, args = parser.parse_args()
+
+ if len(args) != 1:
+ parser.error('You must specify exactly one output file')
+
+ outFile = args[0]
+
+ if path.isdir(outFile):
+ parser.error('You cannot use directory as output')
+
+ archiver = GitArchiver(options.prefix,
+ options.verbose,
+ options.exclude,
+ options.extra)
+
+ try:
+ archiver.create(outFile)
+ except Exception, e:
+ parser.exit(2, "%s\n" % e)
+
+ sys.exit(0)
diff --git a/src/CGALCache.cc b/src/CGALCache.cc
index 6bdad41..84de722 100644
--- a/src/CGALCache.cc
+++ b/src/CGALCache.cc
@@ -7,7 +7,9 @@ CGALCache *CGALCache::inst = NULL;
void CGALCache::insert(const std::string &id, const CGAL_Nef_polyhedron &N)
{
this->cache.insert(id, new CGAL_Nef_polyhedron(N), N.weight());
+#ifdef DEBUG
PRINTF("CGAL Cache insert: %s (%d verts)", id.substr(0, 40).c_str(), N.weight());
+#endif
}
void CGALCache::print()
diff --git a/src/CSGTermEvaluator.cc b/src/CSGTermEvaluator.cc
index 65209dd..4624d4c 100644
--- a/src/CSGTermEvaluator.cc
+++ b/src/CSGTermEvaluator.cc
@@ -159,7 +159,7 @@ Response CSGTermEvaluator::visit(State &state, const TransformNode &node)
Response CSGTermEvaluator::visit(State &state, const ColorNode &node)
{
if (state.isPrefix()) {
- state.setColor(node.color);
+ if (!state.color().isValid()) state.setColor(node.color);
}
if (state.isPostfix()) {
applyToChildren(node, CSGT_UNION);
diff --git a/src/OpenCSGRenderer.cc b/src/OpenCSGRenderer.cc
index 233124b..eb66687 100644
--- a/src/OpenCSGRenderer.cc
+++ b/src/OpenCSGRenderer.cc
@@ -86,7 +86,7 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
if (shaderinfo) glUseProgram(shaderinfo[0]);
for (; j < i; j++) {
const Transform3d &m = chain->matrices[j];
- double *c = chain->colors[j];
+ const Color4f &c = chain->colors[j];
glPushMatrix();
glMultMatrixd(m.data());
PolySet::csgmode_e csgmode = chain->types[j] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
@@ -99,7 +99,7 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
csgmode = PolySet::csgmode_e(csgmode + 10);
} else if (c[0] >= 0 || c[1] >= 0 || c[2] >= 0 || c[3] >= 0) {
// User-defined color or alpha from source
- setColor(c, shaderinfo);
+ setColor(c.data(), shaderinfo);
} else if (chain->types[j] == CSGTerm::TYPE_DIFFERENCE) {
setColor(COLORMODE_CUTOUT, shaderinfo);
} else {
diff --git a/src/OpenCSGWarningDialog.ui b/src/OpenCSGWarningDialog.ui
index f902521..fe3f192 100644
--- a/src/OpenCSGWarningDialog.ui
+++ b/src/OpenCSGWarningDialog.ui
@@ -33,6 +33,9 @@ p, li { white-space: pre-wrap; }
<property name="text">
<string>Enable OpenCSG</string>
</property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item>
diff --git a/src/Preferences.cc b/src/Preferences.cc
index 59f8d23..4c43f2d 100644
--- a/src/Preferences.cc
+++ b/src/Preferences.cc
@@ -47,10 +47,16 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent)
// Setup default settings
this->defaultmap["3dview/colorscheme"] = this->colorSchemeChooser->currentItem()->text();
- this->defaultmap["editor/fontfamily"] = this->fontChooser->currentText();
- this->defaultmap["editor/fontsize"] = this->fontSize->currentText().toUInt();
+#ifdef Q_WS_X11
+ this->defaultmap["editor/fontfamily"] = "Mono";
+#elif defined (Q_WS_WIN)
+ this->defaultmap["editor/fontfamily"] = "Console";
+#elif defined (Q_WS_MAC)
+ this->defaultmap["editor/fontfamily"] = "Monaco";
+#endif
+ this->defaultmap["editor/fontsize"] = 12;
this->defaultmap["advanced/opencsg_show_warning"] = true;
- this->defaultmap["advanced/enable_opencsg_opengl1x"] = false;
+ this->defaultmap["advanced/enable_opencsg_opengl1x"] = true;
// Toolbar
QActionGroup *group = new QActionGroup(this);
@@ -212,7 +218,7 @@ void Preferences::updateGUI()
if (!found.isEmpty()) this->colorSchemeChooser->setCurrentItem(found.first());
QString fontfamily = getValue("editor/fontfamily").toString();
- int fidx = this->fontChooser->findText(fontfamily);
+ int fidx = this->fontChooser->findText(fontfamily,Qt::MatchContains);
if (fidx >= 0) {
this->fontChooser->setCurrentIndex(fidx);
}
diff --git a/src/ThrownTogetherRenderer.cc b/src/ThrownTogetherRenderer.cc
index 36f7b95..146d2e1 100644
--- a/src/ThrownTogetherRenderer.cc
+++ b/src/ThrownTogetherRenderer.cc
@@ -67,7 +67,7 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
if (polySetVisitMark[std::make_pair(chain->polysets[i].get(), &chain->matrices[i])]++ > 0)
continue;
const Transform3d &m = chain->matrices[i];
- double *c = chain->colors[i];
+ const Color4f &c = chain->colors[i];
glPushMatrix();
glMultMatrixd(m.data());
PolySet::csgmode_e csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL;
@@ -93,10 +93,10 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight,
else csgmode = PolySet::csgmode_e(csgmode);
chain->polysets[i]->render_surface(csgmode, m);
} else if (c[0] >= 0 || c[1] >= 0 || c[2] >= 0 || c[3] >= 0) {
- setColor(c);
+ setColor(c.data());
chain->polysets[i]->render_surface(csgmode, m);
if (showedges) {
- glColor4d((c[0]+1)/2, (c[1]+1)/2, (c[2]+1)/2, 1.0);
+ glColor4f((c[0]+1)/2, (c[1]+1)/2, (c[2]+1)/2, 1.0);
chain->polysets[i]->render_edges(csgmode);
}
} else if (chain->types[i] == CSGTerm::TYPE_DIFFERENCE) {
diff --git a/src/colornode.h b/src/colornode.h
index b41e2a9..9323638 100644
--- a/src/colornode.h
+++ b/src/colornode.h
@@ -3,6 +3,7 @@
#include "node.h"
#include "visitor.h"
+#include "linalg.h"
class ColorNode : public AbstractNode
{
@@ -14,7 +15,7 @@ public:
virtual std::string toString() const;
virtual std::string name() const;
- double color[4];
+ Color4f color;
};
#endif
diff --git a/src/csgterm.cc b/src/csgterm.cc
index 56fcbb5..4e6912b 100644
--- a/src/csgterm.cc
+++ b/src/csgterm.cc
@@ -89,10 +89,9 @@ shared_ptr<CSGTerm> CSGTerm::createCSGTerm(type_e type, CSGTerm *left, CSGTerm *
return createCSGTerm(type, shared_ptr<CSGTerm>(left), shared_ptr<CSGTerm>(right));
}
-CSGTerm::CSGTerm(const shared_ptr<PolySet> &polyset, const Transform3d &matrix, const double color[4], const std::string &label)
- : type(TYPE_PRIMITIVE), polyset(polyset), label(label), m(matrix)
+CSGTerm::CSGTerm(const shared_ptr<PolySet> &polyset, const Transform3d &matrix, const Color4f &color, const std::string &label)
+ : type(TYPE_PRIMITIVE), polyset(polyset), label(label), m(matrix), color(color)
{
- for (int i = 0; i < 4; i++) this->color[i] = color[i];
initBoundingBox();
}
@@ -140,127 +139,6 @@ void CSGTerm::initBoundingBox()
}
}
-shared_ptr<CSGTerm> CSGTerm::normalize(shared_ptr<CSGTerm> term)
-{
- // This function implements the CSG normalization
- // Reference:
- // Goldfeather, J., Molnar, S., Turk, G., and Fuchs, H. Near
- // Realtime CSG Rendering Using Tree Normalization and Geometric
- // Pruning. IEEE Computer Graphics and Applications, 9(3):20-28,
- // 1989.
- // http://www.cc.gatech.edu/~turk/my_papers/pxpl_csg.pdf
-
- if (term->type == TYPE_PRIMITIVE) {
- return term;
- }
-
- do {
- while (term && normalize_tail(term)) { }
- if (!term || term->type == TYPE_PRIMITIVE) return term;
- term->left = normalize(term->left);
- } while (term->type != TYPE_UNION &&
- (term->right->type != TYPE_PRIMITIVE || term->left->type == TYPE_UNION));
- term->right = normalize(term->right);
-
- // FIXME: Do we need to take into account any transformation of item here?
- if (!term->right) {
- if (term->type == TYPE_UNION || term->type == TYPE_DIFFERENCE) return term->left;
- else return term->right;
- }
- if (!term->left) {
- if (term->type == TYPE_UNION) return term->right;
- else return term->left;
- }
-
- return term;
-}
-
-bool CSGTerm::normalize_tail(shared_ptr<CSGTerm> &term)
-{
- if (term->type == TYPE_UNION || term->type == TYPE_PRIMITIVE) return false;
-
- // Part A: The 'x . (y . z)' expressions
-
- shared_ptr<CSGTerm> x = term->left;
- shared_ptr<CSGTerm> y = term->right->left;
- shared_ptr<CSGTerm> z = term->right->right;
-
- shared_ptr<CSGTerm> result = term;
-
- // 1. x - (y + z) -> (x - y) - z
- if (term->type == TYPE_DIFFERENCE && term->right->type == TYPE_UNION) {
- term = createCSGTerm(TYPE_DIFFERENCE,
- createCSGTerm(TYPE_DIFFERENCE, x, y),
- z);
- return true;
- }
- // 2. x * (y + z) -> (x * y) + (x * z)
- else if (term->type == TYPE_INTERSECTION && term->right->type == TYPE_UNION) {
- term = createCSGTerm(TYPE_UNION,
- createCSGTerm(TYPE_INTERSECTION, x, y),
- createCSGTerm(TYPE_INTERSECTION, x, z));
- return true;
- }
- // 3. x - (y * z) -> (x - y) + (x - z)
- else if (term->type == TYPE_DIFFERENCE && term->right->type == TYPE_INTERSECTION) {
- term = createCSGTerm(TYPE_UNION,
- createCSGTerm(TYPE_DIFFERENCE, x, y),
- createCSGTerm(TYPE_DIFFERENCE, x, z));
- return true;
- }
- // 4. x * (y * z) -> (x * y) * z
- else if (term->type == TYPE_INTERSECTION && term->right->type == TYPE_INTERSECTION) {
- term = createCSGTerm(TYPE_INTERSECTION,
- createCSGTerm(TYPE_INTERSECTION, x, y),
- z);
- return true;
- }
- // 5. x - (y - z) -> (x - y) + (x * z)
- else if (term->type == TYPE_DIFFERENCE && term->right->type == TYPE_DIFFERENCE) {
- term = createCSGTerm(TYPE_UNION,
- createCSGTerm(TYPE_DIFFERENCE, x, y),
- createCSGTerm(TYPE_INTERSECTION, x, z));
- return true;
- }
- // 6. x * (y - z) -> (x * y) - z
- else if (term->type == TYPE_INTERSECTION && term->right->type == TYPE_DIFFERENCE) {
- term = createCSGTerm(TYPE_DIFFERENCE,
- createCSGTerm(TYPE_INTERSECTION, x, y),
- z);
- return true;
- }
-
- // Part B: The '(x . y) . z' expressions
-
- x = term->left->left;
- y = term->left->right;
- z = term->right;
-
- // 7. (x - y) * z -> (x * z) - y
- if (term->left->type == TYPE_DIFFERENCE && term->type == TYPE_INTERSECTION) {
- term = createCSGTerm(TYPE_DIFFERENCE,
- createCSGTerm(TYPE_INTERSECTION, x, z),
- y);
- return true;
- }
- // 8. (x + y) - z -> (x - z) + (y - z)
- else if (term->left->type == TYPE_UNION && term->type == TYPE_DIFFERENCE) {
- term = createCSGTerm(TYPE_UNION,
- createCSGTerm(TYPE_DIFFERENCE, x, z),
- createCSGTerm(TYPE_DIFFERENCE, y, z));
- return true;
- }
- // 9. (x + y) * z -> (x * z) + (y * z)
- else if (term->left->type == TYPE_UNION && term->type == TYPE_INTERSECTION) {
- term = createCSGTerm(TYPE_UNION,
- createCSGTerm(TYPE_INTERSECTION, x, z),
- createCSGTerm(TYPE_INTERSECTION, y, z));
- return true;
- }
-
- return false;
-}
-
std::string CSGTerm::dump()
{
std::stringstream dump;
@@ -281,7 +159,7 @@ CSGChain::CSGChain()
{
}
-void CSGChain::add(const shared_ptr<PolySet> &polyset, const Transform3d &m, double *color, CSGTerm::type_e type, std::string label)
+void CSGChain::add(const shared_ptr<PolySet> &polyset, const Transform3d &m, const Color4f &color, CSGTerm::type_e type, std::string label)
{
polysets.push_back(polyset);
matrices.push_back(m);
diff --git a/src/csgterm.h b/src/csgterm.h
index 4930349..4278d85 100644
--- a/src/csgterm.h
+++ b/src/csgterm.h
@@ -28,14 +28,11 @@ public:
shared_ptr<CSGTerm> right;
BoundingBox bbox;
- CSGTerm(const shared_ptr<PolySet> &polyset, const Transform3d &matrix, const double color[4], const std::string &label);
+ CSGTerm(const shared_ptr<PolySet> &polyset, const Transform3d &matrix, const Color4f &color, const std::string &label);
~CSGTerm();
const BoundingBox &getBoundingBox() const { return this->bbox; }
- static shared_ptr<CSGTerm> normalize(shared_ptr<CSGTerm> term);
- static bool normalize_tail(shared_ptr<CSGTerm> &term);
-
std::string dump();
private:
CSGTerm(type_e type, shared_ptr<CSGTerm> left, shared_ptr<CSGTerm> right);
@@ -44,7 +41,7 @@ private:
void initBoundingBox();
Transform3d m;
- double color[4];
+ Color4f color;
friend class CSGChain;
};
@@ -54,13 +51,13 @@ class CSGChain
public:
std::vector<shared_ptr<PolySet> > polysets;
std::vector<Transform3d> matrices;
- std::vector<double*> colors;
+ std::vector<Color4f> colors;
std::vector<CSGTerm::type_e> types;
std::vector<std::string> labels;
CSGChain();
- void add(const shared_ptr<PolySet> &polyset, const Transform3d &m, double *color, CSGTerm::type_e type, std::string label);
+ void add(const shared_ptr<PolySet> &polyset, const Transform3d &m, const Color4f &color, CSGTerm::type_e type, std::string label);
void import(shared_ptr<CSGTerm> term, CSGTerm::type_e type = CSGTerm::TYPE_UNION);
std::string dump();
diff --git a/src/csgtermnormalizer.cc b/src/csgtermnormalizer.cc
new file mode 100644
index 0000000..a830422
--- /dev/null
+++ b/src/csgtermnormalizer.cc
@@ -0,0 +1,150 @@
+#include "csgtermnormalizer.h"
+#include "csgterm.h"
+#include "printutils.h"
+
+shared_ptr<CSGTerm> CSGTermNormalizer::normalize(const shared_ptr<CSGTerm> &root)
+{
+ shared_ptr<CSGTerm> temp = root;
+ while (1) {
+ shared_ptr<CSGTerm> n = normalizePass(temp);
+ if (temp == n) break;
+ temp = n;
+
+ int num = count(temp);
+#ifdef DEBUG
+ PRINTF("Normalize count: %d\n", num);
+#endif
+ if (num > 5000) {
+ PRINTF("WARNING: Normalized tree is growing past 5000 elements. Aborting normalization.\n");
+ return root;
+ }
+ }
+ return temp;
+}
+
+shared_ptr<CSGTerm> CSGTermNormalizer::normalizePass(shared_ptr<CSGTerm> term)
+{
+ // This function implements the CSG normalization
+ // Reference:
+ // Goldfeather, J., Molnar, S., Turk, G., and Fuchs, H. Near
+ // Realtime CSG Rendering Using Tree Normalization and Geometric
+ // Pruning. IEEE Computer Graphics and Applications, 9(3):20-28,
+ // 1989.
+ // http://www.cc.gatech.edu/~turk/my_papers/pxpl_csg.pdf
+
+ if (term->type == CSGTerm::TYPE_PRIMITIVE) {
+ return term;
+ }
+
+ do {
+ while (term && normalize_tail(term)) { }
+ if (!term || term->type == CSGTerm::TYPE_PRIMITIVE) return term;
+ term->left = normalizePass(term->left);
+ } while (term->type != CSGTerm::TYPE_UNION &&
+ (term->right->type != CSGTerm::TYPE_PRIMITIVE || term->left->type == CSGTerm::TYPE_UNION));
+ term->right = normalizePass(term->right);
+
+ // FIXME: Do we need to take into account any transformation of item here?
+ if (!term->right) {
+ if (term->type == CSGTerm::TYPE_UNION || term->type == CSGTerm::TYPE_DIFFERENCE) return term->left;
+ else return term->right;
+ }
+ if (!term->left) {
+ if (term->type == CSGTerm::TYPE_UNION) return term->right;
+ else return term->left;
+ }
+
+ return term;
+}
+
+bool CSGTermNormalizer::normalize_tail(shared_ptr<CSGTerm> &term)
+{
+ if (term->type == CSGTerm::TYPE_UNION || term->type == CSGTerm::TYPE_PRIMITIVE) return false;
+
+ // Part A: The 'x . (y . z)' expressions
+
+ shared_ptr<CSGTerm> x = term->left;
+ shared_ptr<CSGTerm> y = term->right->left;
+ shared_ptr<CSGTerm> z = term->right->right;
+
+ shared_ptr<CSGTerm> result = term;
+
+ // 1. x - (y + z) -> (x - y) - z
+ if (term->type == CSGTerm::TYPE_DIFFERENCE && term->right->type == CSGTerm::TYPE_UNION) {
+ term = CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE,
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, x, y),
+ z);
+ return true;
+ }
+ // 2. x * (y + z) -> (x * y) + (x * z)
+ else if (term->type == CSGTerm::TYPE_INTERSECTION && term->right->type == CSGTerm::TYPE_UNION) {
+ term = CSGTerm::createCSGTerm(CSGTerm::TYPE_UNION,
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, y),
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, z));
+ return true;
+ }
+ // 3. x - (y * z) -> (x - y) + (x - z)
+ else if (term->type == CSGTerm::TYPE_DIFFERENCE && term->right->type == CSGTerm::TYPE_INTERSECTION) {
+ term = CSGTerm::createCSGTerm(CSGTerm::TYPE_UNION,
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, x, y),
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, x, z));
+ return true;
+ }
+ // 4. x * (y * z) -> (x * y) * z
+ else if (term->type == CSGTerm::TYPE_INTERSECTION && term->right->type == CSGTerm::TYPE_INTERSECTION) {
+ term = CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION,
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, y),
+ z);
+ return true;
+ }
+ // 5. x - (y - z) -> (x - y) + (x * z)
+ else if (term->type == CSGTerm::TYPE_DIFFERENCE && term->right->type == CSGTerm::TYPE_DIFFERENCE) {
+ term = CSGTerm::createCSGTerm(CSGTerm::TYPE_UNION,
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, x, y),
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, z));
+ return true;
+ }
+ // 6. x * (y - z) -> (x * y) - z
+ else if (term->type == CSGTerm::TYPE_INTERSECTION && term->right->type == CSGTerm::TYPE_DIFFERENCE) {
+ term = CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE,
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, y),
+ z);
+ return true;
+ }
+
+ // Part B: The '(x . y) . z' expressions
+
+ x = term->left->left;
+ y = term->left->right;
+ z = term->right;
+
+ // 7. (x - y) * z -> (x * z) - y
+ if (term->left->type == CSGTerm::TYPE_DIFFERENCE && term->type == CSGTerm::TYPE_INTERSECTION) {
+ term = CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE,
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, z),
+ y);
+ return true;
+ }
+ // 8. (x + y) - z -> (x - z) + (y - z)
+ else if (term->left->type == CSGTerm::TYPE_UNION && term->type == CSGTerm::TYPE_DIFFERENCE) {
+ term = CSGTerm::createCSGTerm(CSGTerm::TYPE_UNION,
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, x, z),
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, y, z));
+ return true;
+ }
+ // 9. (x + y) * z -> (x * z) + (y * z)
+ else if (term->left->type == CSGTerm::TYPE_UNION && term->type == CSGTerm::TYPE_INTERSECTION) {
+ term = CSGTerm::createCSGTerm(CSGTerm::TYPE_UNION,
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, x, z),
+ CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, y, z));
+ return true;
+ }
+
+ return false;
+}
+
+int CSGTermNormalizer::count(const shared_ptr<CSGTerm> &term) const
+{
+ if (!term) return 0;
+ return term->type == CSGTerm::TYPE_PRIMITIVE ? 1 : 0 + count(term->left) + count(term->right);
+}
diff --git a/src/csgtermnormalizer.h b/src/csgtermnormalizer.h
new file mode 100644
index 0000000..df37441
--- /dev/null
+++ b/src/csgtermnormalizer.h
@@ -0,0 +1,22 @@
+#ifndef CSGTERMNORMALIZER_H_
+#define CSGTERMNORMALIZER_H_
+
+#include "memory.h"
+
+class CSGTermNormalizer
+{
+public:
+ CSGTermNormalizer() : counter(0) {}
+ ~CSGTermNormalizer() {}
+
+ shared_ptr<class CSGTerm> normalize(const shared_ptr<CSGTerm> &term);
+
+private:
+ shared_ptr<CSGTerm> normalizePass(shared_ptr<CSGTerm> term) ;
+ bool normalize_tail(shared_ptr<CSGTerm> &term);
+ int count(const shared_ptr<CSGTerm> &term) const;
+
+ int counter;
+};
+
+#endif
diff --git a/src/export.cc b/src/export.cc
index 5ce2d15..8abd5fa 100644
--- a/src/export.cc
+++ b/src/export.cc
@@ -84,31 +84,22 @@ void export_stl(CGAL_Nef_polyhedron *root_N, std::ostream &output, QProgressDial
stream << x3 << " " << y3 << " " << z3;
std::string vs3 = stream.str();
if (vs1 != vs2 && vs1 != vs3 && vs2 != vs3) {
- // The above condition ensures that vs1-vs2, vs1-vs3, and their cross
- // product are non-zero. Floating point arithmetic may however truncate
- // small values to 0. This can be avoided by first scaling the components
- // of vs1-vs2 and vs1-vs3. This has no effect on the resulting unit
- // normal vector.
- double dn[6] = { x1-x2, y1-y2, z1-z2, x1-x3, y1-y3, z1-z3 };
- double maxdn = 0;
- int i;
- for (i = 0; i < 6; ++i) {
- double dx = dn[i];
- if (dx < 0) dx = -dx;
- if (dx > maxdn) maxdn = dx;
+ // The above condition ensures that there are 3 distinct vertices, but
+ // they may be collinear. If they are, the unit normal is meaningless
+ // so the default value of "1 0 0" can be used. If the vertices are not
+ // collinear then the unit normal must be calculated from the
+ // components.
+ if (!CGAL::collinear(v1.point(),v2.point(),v3.point())) {
+ CGAL_Polyhedron::Traits::Vector_3 normal = CGAL::normal(v1.point(),v2.point(),v3.point());
+ output << " facet normal "
+ << CGAL::sign(normal.x()) * sqrt(CGAL::to_double(normal.x()*normal.x()/normal.squared_length()))
+ << " "
+ << CGAL::sign(normal.y()) * sqrt(CGAL::to_double(normal.y()*normal.y()/normal.squared_length()))
+ << " "
+ << CGAL::sign(normal.z()) * sqrt(CGAL::to_double(normal.z()*normal.z()/normal.squared_length()))
+ << "\n";
}
- for (i = 0; i < 6; ++i) dn[i] /= maxdn;
- double nx = dn[1]*dn[5] - dn[2]*dn[4];
- double ny = dn[2]*dn[3] - dn[0]*dn[5];
- double nz = dn[0]*dn[4] - dn[1]*dn[3];
- double nlength = sqrt(nx*nx + ny*ny + nz*nz);
- // Avoid generating normals for polygons with zero area
- double eps = 0.000001;
- if (nlength < eps) nlength = 1.0;
- output << " facet normal "
- << nx / nlength << " "
- << ny / nlength << " "
- << nz / nlength << "\n";
+ else output << " facet normal 1 0 0\n";
output << " outer loop\n";
output << " vertex " << vs1 << "\n";
output << " vertex " << vs2 << "\n";
diff --git a/src/glview.cc b/src/glview.cc
index f25cac6..63573e3 100644
--- a/src/glview.cc
+++ b/src/glview.cc
@@ -154,9 +154,9 @@ void GLView::initializeGL()
"Extensions:\n"
"%s\n",
glewGetString(GLEW_VERSION),
+ glGetString(GL_VERSION),
glGetString(GL_RENDERER),
glGetString(GL_VENDOR),
- glGetString(GL_VERSION),
rbits, gbits, bbits, abits, dbits, sbits,
glGetString(GL_EXTENSIONS));
// FIXME: glGetString(GL_EXTENSIONS) is deprecated in OpenGL 3.0.
@@ -500,10 +500,11 @@ void GLView::paintGL()
// FIXME: This was an attempt to keep contrast with background, but is suboptimal
// (e.g. nearly invisible against a gray background).
- int r,g,b;
- r=g=b=0;
+// int r,g,b;
+// r=g=b=0;
// bgcol.getRgb(&r, &g, &b);
- glColor3d((255.0-r)/255.0, (255.0-g)/255.0, (255.0-b)/255.0);
+// glColor3f((255.0f-r)/255.0f, (255.0f-g)/255.0f, (255.0f-b)/255.0f);
+ glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_LINES);
// X Label
glVertex3d(xlabel_x-3, xlabel_y-3, 0); glVertex3d(xlabel_x+3, xlabel_y+3, 0);
diff --git a/src/lexer.l b/src/lexer.l
index c799028..07819b2 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -114,27 +114,6 @@ use[ \t\r\n>]*"<"[^\t\r\n>]+">" {
return TOK_USE;
}
-"<"[^ \t\r\n>]+">" {
- char *filename = strdup(yytext+1);
- filename[strlen(filename)-1] = 0;
- QFileInfo finfo(QDir(parser_source_path), filename);
- if (!finfo.exists()) {
- finfo = QFileInfo(QDir(librarydir), filename);
- }
-
- PRINTF("DEPRECATED: Support for implicit include will be removed in future releases. Use `include <filename>' instead.");
- handle_dep(finfo.absoluteFilePath().toStdString());
- yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r");
- if (!yyin) {
- PRINTF("WARNING: Can't open input file `%s'.", filename);
- } else {
- openfiles.append(yyin);
- yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
- BEGIN(INITIAL);
- }
- free(filename);
-}
-
<<EOF>> {
if(!path_stack.empty())
path_stack.pop();
diff --git a/src/linalg.h b/src/linalg.h
index c1a14d1..15ef870 100644
--- a/src/linalg.h
+++ b/src/linalg.h
@@ -15,4 +15,10 @@ using Eigen::Transform3d;
BoundingBox operator*(const Transform3d &m, const BoundingBox &box);
+class Color4f : public Eigen::Vector4f
+{
+public:
+ bool isValid() const { return this->minCoeff() >= 0.0f; }
+};
+
#endif
diff --git a/src/mainwin.cc b/src/mainwin.cc
index 82a28c3..0c5537f 100644
--- a/src/mainwin.cc
+++ b/src/mainwin.cc
@@ -43,6 +43,7 @@
#endif
#include "ProgressWidget.h"
#include "ThrownTogetherRenderer.h"
+#include "csgtermnormalizer.h"
#include <QMenu>
#include <QTime>
@@ -181,7 +182,6 @@ MainWindow::MainWindow(const QString &filename)
editor->setTabStopWidth(30);
#endif
editor->setLineWrapping(true); // Not designable
- setFont("", 12); // Init default font
this->glview->statusLabel = new QLabel(this);
statusBar()->addWidget(this->glview->statusLabel);
@@ -765,15 +765,8 @@ void MainWindow::compileCSG(bool procevents)
if (procevents)
QApplication::processEvents();
- this->root_norm_term = this->root_raw_term;
-
- // CSG normalization
- while (1) {
- shared_ptr<CSGTerm> n = CSGTerm::normalize(this->root_norm_term);
- if (this->root_norm_term == n) break;
- this->root_norm_term = n;
- }
-
+ CSGTermNormalizer normalizer;
+ this->root_norm_term = normalizer.normalize(this->root_raw_term);
assert(this->root_norm_term);
root_chain = new CSGChain();
@@ -787,11 +780,7 @@ void MainWindow::compileCSG(bool procevents)
highlights_chain = new CSGChain();
for (unsigned int i = 0; i < highlight_terms.size(); i++) {
- while (1) {
- shared_ptr<CSGTerm> n = CSGTerm::normalize(highlight_terms[i]);
- if (highlight_terms[i] == n) break;
- highlight_terms[i] = n;
- }
+ highlight_terms[i] = normalizer.normalize(highlight_terms[i]);
highlights_chain->import(highlight_terms[i]);
}
}
@@ -804,11 +793,7 @@ void MainWindow::compileCSG(bool procevents)
background_chain = new CSGChain();
for (unsigned int i = 0; i < background_terms.size(); i++) {
- while (1) {
- shared_ptr<CSGTerm> n = CSGTerm::normalize(background_terms[i]);
- if (background_terms[i] == n) break;
- background_terms[i] = n;
- }
+ background_terms[i] = normalizer.normalize(background_terms[i]);
background_chain->import(background_terms[i]);
}
}
@@ -1762,8 +1747,9 @@ MainWindow::preferences()
void MainWindow::setFont(const QString &family, uint size)
{
- QFont font(editor->font());
+ QFont font;
if (!family.isEmpty()) font.setFamily(family);
+ else font.setFixedPitch(true);
if (size > 0) font.setPointSize(size);
font.setStyleHint(QFont::TypeWriter);
editor->setFont(font);
diff --git a/src/openscad.cc b/src/openscad.cc
index 0d5b25e..c6dd7b6 100644
--- a/src/openscad.cc
+++ b/src/openscad.cc
@@ -364,6 +364,10 @@ int main(int argc, char **argv)
}
if (dxf_output_file) {
+ if (root_N.dim != 2) {
+ fprintf(stderr, "Current top level object is not a 2D object.\n");
+ exit(1);
+ }
std::ofstream fstream(dxf_output_file);
if (!fstream.is_open()) {
PRINTF("Can't open file \"%s\" for export", dxf_output_file);
diff --git a/src/parser.y b/src/parser.y
index b0df50d..3dd933c 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -588,12 +588,15 @@ AbstractModule *parse(const char *text, const char *path, int debug)
if (!module)
return NULL;
- BOOST_FOREACH(Module::ModuleContainer::value_type &m, module->usedlibs) {
- module->usedlibs[m.first] = Module::compile_library(m.first);
- if (!module->usedlibs[m.first]) {
- PRINTF("WARNING: Failed to compile library `%s'.", m.first.c_str());
- module->usedlibs.erase(m.first);
- }
+ // Iterating manually since we want to modify the container while iterating
+ Module::ModuleContainer::iterator iter = module->usedlibs.begin();
+ while (iter != module->usedlibs.end()) {
+ Module::ModuleContainer::iterator curr = iter++;
+ curr->second = Module::compile_library(curr->first);
+ if (!curr->second) {
+ PRINTF("WARNING: Failed to compile library `%s'.", curr->first.c_str());
+ module->usedlibs.erase(curr);
+ }
}
parser_error_pos = -1;
diff --git a/src/renderer.cc b/src/renderer.cc
index b791673..5a767b8 100644
--- a/src/renderer.cc
+++ b/src/renderer.cc
@@ -2,7 +2,7 @@
#include "rendersettings.h"
#include <QColor>
-void Renderer::setColor(const double color[4], GLint *shaderinfo) const
+void Renderer::setColor(const float color[4], GLint *shaderinfo) const
{
QColor col = RenderSettings::inst()->color(RenderSettings::OPENCSG_FACE_FRONT_COLOR);
double c[4] = {color[0], color[1], color[2], color[3]};
diff --git a/src/renderer.h b/src/renderer.h
index 8deabe8..2bc482d 100644
--- a/src/renderer.h
+++ b/src/renderer.h
@@ -25,7 +25,7 @@ public:
COLORMODE_BACKGROUND_EDGES
};
- virtual void setColor(const double color[4], GLint *shaderinfo = NULL) const;
+ virtual void setColor(const float color[4], GLint *shaderinfo = NULL) const;
virtual void setColor(ColorMode colormode, GLint *shaderinfo = NULL) const;
};
diff --git a/src/state.h b/src/state.h
index 5dc74df..df202aa 100644
--- a/src/state.h
+++ b/src/state.h
@@ -9,8 +9,8 @@ class State
public:
State(const class AbstractNode *parent)
: parentnode(parent), isprefix(false), ispostfix(false), numchildren(0) {
- m = Transform3d::Identity();
- for (int i=0;i<4;i++) this->c[i] = -1.0;
+ this->matrix_ = Transform3d::Identity();
+ this->color_.fill(-1.0f);
}
virtual ~State() {}
@@ -18,15 +18,15 @@ public:
void setPostfix(bool on) { this->ispostfix = on; }
void setNumChildren(unsigned int numc) { this->numchildren = numc; }
void setParent(const AbstractNode *parent) { this->parentnode = parent; }
- void setMatrix(const Transform3d &m) { this->m = m; }
- void setColor(const double c[4]) { memcpy(this->c, c, 4*sizeof(double)); }
+ void setMatrix(const Transform3d &m) { this->matrix_ = m; }
+ void setColor(const Color4f &c) { this->color_ = c; }
bool isPrefix() const { return this->isprefix; }
bool isPostfix() const { return this->ispostfix; }
unsigned int numChildren() const { return this->numchildren; }
const AbstractNode *parent() const { return this->parentnode; }
- const Transform3d &matrix() const { return this->m; }
- const double *color() const { return this->c; }
+ const Transform3d &matrix() const { return this->matrix_; }
+ const Color4f &color() const { return this->color_; }
private:
const AbstractNode * parentnode;
@@ -35,8 +35,8 @@ private:
unsigned int numchildren;
// Transformation matrix and color. FIXME: Generalize such state variables?
- Transform3d m;
- double c[4];
+ Transform3d matrix_;
+ Color4f color_;
};
#endif
diff --git a/testdata/scad/features/cylinder-tests.scad b/testdata/scad/features/cylinder-tests.scad
index 54e88cd..71f43a6 100644
--- a/testdata/scad/features/cylinder-tests.scad
+++ b/testdata/scad/features/cylinder-tests.scad
@@ -12,4 +12,9 @@ translate([22,-11,0]) cylinder(h=5, r=5, r1=0, center=true);
translate([22,0,0]) cylinder(h=5, r=5, r2=0);
translate([22,11,0]) cylinder(h=15, r=5, r2=5);
+// This tests for hexagonal cylinder orientation, since people
+// tend to "abuse" this for captured nut slots
+translate([-10,0,0]) cylinder(h=2, r=3, $fn=6);
+
+
// FIXME: We could test $fs, $fa, $fn as well
diff --git a/testdata/scad/features/include-tests.scad b/testdata/scad/features/include-tests.scad
index 36c04ca..fc4e9d0 100644
--- a/testdata/scad/features/include-tests.scad
+++ b/testdata/scad/features/include-tests.scad
@@ -7,7 +7,7 @@ include <non/existent/path/non-file>
//Test with empty path
include <include-test5.scad>
-//Test without preceeding space
+//Test without preceding space
include<include-test5.scad>
//Test with other strange character that is allowed
@@ -34,7 +34,7 @@ module test1()
translate([-2,-2,0]) test6();
//Just to give a top level object
- translate([0,-2,0]) sphere(0.7, $fn=16);
+ translate([0,-2,0]) sphere(test2_variable, $fn=16);
}
test1();
diff --git a/testdata/scad/features/intersection-tests.scad b/testdata/scad/features/intersection-tests.scad
index e53f3c9..4a1d7e3 100644
--- a/testdata/scad/features/intersection-tests.scad
+++ b/testdata/scad/features/intersection-tests.scad
@@ -22,7 +22,7 @@ translate([12,0,0]) intersection() {
translate([12,12,0]) intersection() {
cube([10,10,10], center=true);
- translate([0,0,7]) cylinder(r=4, h=4, center=true);
+ translate([0,0,7.01]) cylinder(r=4, h=4, center=true);
}
translate([24,0,0]) intersection() {
diff --git a/testdata/scad/features/sub1/sub2/sub3/sub4/include-test2.scad b/testdata/scad/features/sub1/sub2/sub3/sub4/include-test2.scad
index 140c4ed..c34632c 100644
--- a/testdata/scad/features/sub1/sub2/sub3/sub4/include-test2.scad
+++ b/testdata/scad/features/sub1/sub2/sub3/sub4/include-test2.scad
@@ -4,7 +4,9 @@ include <include-test3.scad>
//Test relative file location
include <../include-test4.scad>
-module test2 ()
+test2_variable = 0.7;
+
+module test2()
{
cube(center=true);
}
diff --git a/testdata/scad/features/sub1/sub2/sub3/sub4/use-test2.scad b/testdata/scad/features/sub1/sub2/sub3/sub4/use-test2.scad
new file mode 100644
index 0000000..68013db
--- /dev/null
+++ b/testdata/scad/features/sub1/sub2/sub3/sub4/use-test2.scad
@@ -0,0 +1,14 @@
+//Test nested use
+use <use-test3.scad>
+
+//Test relative file location
+use <../use-test4.scad>
+
+test2_variable = 0.7;
+
+module test2()
+{
+ translate([2,0,0]) test3();
+ translate([2,-2,0]) test4();
+ cube(center=true);
+}
diff --git a/testdata/scad/features/sub1/sub2/sub3/sub4/use-test3.scad b/testdata/scad/features/sub1/sub2/sub3/sub4/use-test3.scad
new file mode 100644
index 0000000..6e3537e
--- /dev/null
+++ b/testdata/scad/features/sub1/sub2/sub3/sub4/use-test3.scad
@@ -0,0 +1,4 @@
+module test3()
+{
+ cylinder(r1=0.7, r2=0.2, center=true);
+}
diff --git a/testdata/scad/features/sub1/sub2/sub3/use-test4.scad b/testdata/scad/features/sub1/sub2/sub3/use-test4.scad
new file mode 100644
index 0000000..c13368c
--- /dev/null
+++ b/testdata/scad/features/sub1/sub2/sub3/use-test4.scad
@@ -0,0 +1,4 @@
+module test4()
+{
+ cylinder(r=0.5, $fn=10, center=true);
+}
diff --git a/testdata/scad/features/use test6.scad b/testdata/scad/features/use test6.scad
new file mode 100644
index 0000000..0d96b26
--- /dev/null
+++ b/testdata/scad/features/use test6.scad
@@ -0,0 +1,7 @@
+module test6()
+{
+ difference() {
+ cube(center=true);
+ cylinder(r=0.4, h=2, center=true);
+ }
+}
diff --git a/testdata/scad/features/use-test5.scad b/testdata/scad/features/use-test5.scad
new file mode 100644
index 0000000..e4393cb
--- /dev/null
+++ b/testdata/scad/features/use-test5.scad
@@ -0,0 +1,4 @@
+module test5()
+{
+ sphere(r=0.5, $fn=8);
+}
diff --git a/testdata/scad/features/use-tests.scad b/testdata/scad/features/use-tests.scad
new file mode 100644
index 0000000..64af692
--- /dev/null
+++ b/testdata/scad/features/use-tests.scad
@@ -0,0 +1,39 @@
+//Test that the entire path is pushed onto the stack upto the last '/'
+use <sub1/sub2/sub3/sub4/use-test2.scad>
+
+//Test that a non existent path/file doesn't screw things up
+use <non/existent/path/non-file>
+
+//Test with empty path
+use <use-test5.scad>
+
+//Test without preceding space
+use<use-test5.scad>
+
+//Test with other strange character that is allowed
+use>>>>><use-test5.scad>
+
+//Test that filenames with spaces work
+use <use test6.scad>
+
+//Test with empty file
+use<test/>
+
+//Test with empty path and file
+use </>
+
+module test1()
+{
+ test2();
+ // test3() and test4() are not directly included and thus not imported into
+ // this scope
+ translate([4,0,0]) test3();
+ translate([4,-2,0]) test4();
+ translate([-2,0,0]) test5();
+ translate([-2,-2,0]) test6();
+
+ // test2_variable won't be visible
+ translate([0,-2,0]) sphere(test2_variable, $fn=16);
+}
+
+test1();
diff --git a/tests/.gitignore b/tests/.gitignore
index ba02d4c..4dc4e40 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -19,4 +19,6 @@ out.png
/echotest
/opencsgtest
/throwntogethertest
-/yee_compare
+/cgalstlsanitytest
+/sysinfo.txt
+/CTestCustom.cmake \ No newline at end of file
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index b374188..edab744 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -13,6 +13,9 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}")
# Build debug build as default
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo)
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
endif()
@@ -24,11 +27,11 @@ endif()
# Windows
#
-if(WIN32)
+if(WIN32 AND MSVC)
set(WIN32_STATIC_BUILD "True")
endif()
-if(WIN32_STATIC_BUILD)
+if(WIN32_STATIC_BUILD AND MSVC)
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set(EMSG "\nTo build Win32 STATIC OpenSCAD please see doc/testing.txt")
message(FATAL_ERROR ${EMSG})
@@ -36,7 +39,7 @@ if(WIN32_STATIC_BUILD)
endif()
# Disable warnings
-if(WIN32)
+if(WIN32 AND MSVC)
# too long decorated names
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4503")
# int cast to bool in CGAL
@@ -52,7 +55,7 @@ if(WIN32)
endif()
# Debugging - if you uncomment, use nmake -f Makefile > log.txt (the log is big)
-if(WIN32)
+if(WIN32 AND MSVC)
# Linker debugging
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -VERBOSE")
@@ -60,47 +63,76 @@ if(WIN32)
# you have to pass -DCMAKE_VERBOSE_MAKEFILE=ON to cmake when you run it.
endif()
+if(WIN32 AND CMAKE_COMPILER_IS_GNUCXX)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -frounding-math")
+endif()
+
#
# Build test apps
#
+function(inclusion user_set_path found_paths)
+ # If user_set_path indicates an env. variable was specifically
+ # set by the user, then found_paths become an include priority (prepend);
+ # otherwise found_paths are stuck on the end of the include flags (append).
+
+ # message(STATUS "inclusion ${user_set_path} ${found_paths}")
+ # message(STATUS "inclusion ${${user_set_path}} ${${found_paths}}")
+ set( inclusion_match 0 )
+ foreach( found_path ${${found_paths}} )
+ if (${found_path} MATCHES ${${user_set_path}}.*)
+ set( inclusion_match 1 )
+ endif()
+ endforeach()
+ if (user_set_path AND inclusion_match)
+ include_directories(BEFORE ${${found_paths}})
+ # message(STATUS "inclusion prepend ${${found_paths}} for ${user_set_path}")
+ else()
+ include_directories(AFTER ${${found_paths}})
+ # message(STATUS "inclusion append ${${found_paths}} for ${user_set_path}")
+ endif()
+ set( inclusion_match 0 )
+endfunction()
+
# Boost
+#
+# FindBoost.cmake has been included from Cmake's GIT circa the end of 2011
+# because most existing installs of cmake had a buggy older version.
+#
+# Update this if FindBoost.cmake gets out of sync with the current boost release
+# set(Boost_ADDITIONAL_VERSIONS "1.47.0" "1.46.0")
+
+if (WIN32)
+ set(Boost_USE_STATIC_LIBS TRUE)
+ set(BOOST_STATIC TRUE)
+ set(BOOST_THREAD_USE_LIB TRUE)
+endif()
+
if (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
set(BOOST_ROOT "$ENV{OPENSCAD_LIBRARIES}")
+ if (EXISTS ${BOOST_ROOT}/include/boost)
+ # if boost is under OPENSCAD_LIBRARIES, then
+ # don't look in the system paths (workaround FindBoost.cmake bug)
+ set(Boost_NO_SYSTEM_PATHS "TRUE")
+ message(STATUS "BOOST_ROOT: " ${BOOST_ROOT})
+ endif()
endif()
if (NOT $ENV{BOOSTDIR} STREQUAL "")
- set(BOOST_DIR "$ENV{BOOSTDIR}")
-endif()
-
-if (NOT ${BOOST_DIR} STREQUAL "")
- set(BOOST_ROOT ${BOOST_DIR})
- message(STATUS "BOOST_ROOT: " ${BOOST_ROOT})
+ set(BOOST_ROOT "$ENV{BOOSTDIR}")
set(Boost_NO_SYSTEM_PATHS "TRUE")
set(Boost_DEBUG TRUE)
+ message(STATUS "BOOST_ROOT: " ${BOOST_ROOT})
endif()
-
-if (WIN32)
- set(Boost_USE_STATIC_LIBS TRUE)
- set(BOOST_STATIC TRUE)
- set(BOOST_THREAD_USE_LIB TRUE)
-endif()
-
-# Update this if FindBoost.cmake gets out of sync with the current boost release
-# set(Boost_ADDITIONAL_VERSIONS "1.47.0" "1.46.0")
find_package( Boost 1.35.0 COMPONENTS thread program_options REQUIRED)
-if(Boost_FOUND)
- message(STATUS "Boost includes found: " ${Boost_INCLUDE_DIRS})
- message(STATUS "Boost libraries found:")
- foreach(boostlib ${Boost_LIBRARIES})
- message(STATUS " " ${boostlib})
- endforeach()
- include_directories(${Boost_INCLUDE_DIRS})
-else()
- message(STATUS "BOOST_ROOT: ${BOOST_ROOT}")
- message(FATAL_ERROR "Boost not found.")
-endif()
+message(STATUS "Boost includes found: " ${Boost_INCLUDE_DIRS})
+message(STATUS "Boost libraries found:")
+foreach(boostlib ${Boost_LIBRARIES})
+ message(STATUS " " ${boostlib})
+endforeach()
+
+inclusion(BOOST_ROOT Boost_INCLUDE_DIRS)
# Mac OS X
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
@@ -109,19 +141,21 @@ endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# Qt4
-if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
- # make /usr/local/include/qt4 come before /usr/local/include (QT4 vs QT3)
- set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
-endif()
-
+set(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
find_package(OpenGL REQUIRED)
-find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED)
-include(${QT_USE_FILE})
-if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
- set(CMAKE_INCLUDE_DIRECTORIES_BEFORE OFF)
+if (MINGW_CROSS_ENV_DIR)
+ mingw_cross_env_find_qt()
+ mingw_cross_env_info()
+ include_directories( ${QT_INCLUDE_DIRS} )
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${QT_CFLAGS_OTHER}")
+else()
+ find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED)
+ include(${QT_USE_FILE})
endif()
+set(CMAKE_INCLUDE_DIRECTORIES_BEFORE OFF)
+
# Eigen2
# Turn off Eigen SIMD optimization
@@ -131,24 +165,34 @@ if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
endif()
endif()
+if (NOT $ENV{EIGEN2DIR} STREQUAL "")
+ set(EIGEN2_DIR "$ENV{EIGEN2DIR}")
+elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
+ set(EIGEN2_DIR "$ENV{OPENSCAD_LIBRARIES}")
+endif()
+
if (NOT EIGEN2_INCLUDE_DIR)
+ if (EIGEN2_DIR)
+ set(EIGEN2_FIND_HINTS "${EIGEN2_DIR}/include/eigen2")
+ endif()
+ if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
+ set(EIGEN2_FIND_PATHS /usr/local/include/eigen2)
+ elseif (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
+ set(EIGEN2_FIND_PATHS /usr/pkg/include/eigen2)
+ else()
+ set(EIGEN2_FIND_PATHS /opt/local/include/eigen2 /usr/include/eigen2)
+ endif()
find_path(EIGEN2_INCLUDE_DIR
Eigen/Core
- HINTS $ENV{EIGEN2DIR}
- PATHS /opt/local/include/eigen2 /usr/include/eigen2)
- if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
- find_path(EIGEN2_INCLUDE_DIR
- Eigen/Core
- HINTS $ENV{EIGEN2DIR}
- PATHS /usr/local/include/eigen2 )
- endif()
+ HINTS ${EIGEN2_FIND_HINTS}
+ PATHS ${EIGEN2_FIND_PATHS})
if (NOT EIGEN2_INCLUDE_DIR)
message(FATAL_ERROR "Eigen2 not found")
else()
message(STATUS "Eigen2 found in " ${EIGEN2_INCLUDE_DIR})
endif()
endif()
-include_directories(${EIGEN2_INCLUDE_DIR})
+inclusion(EIGEN2_DIR EIGEN2_INCLUDE_DIR)
# OpenCSG
if (NOT $ENV{OPENCSGDIR} STREQUAL "")
@@ -171,10 +215,14 @@ if (NOT OPENCSG_INCLUDE_DIR)
message(STATUS "OpenCSG library found in " ${OPENCSG_LIBRARY})
endif()
endif()
-include_directories(${OPENCSG_INCLUDE_DIR})
+inclusion(OPENCSG_DIR OPENCSG_INCLUDE_DIR)
# GLEW
+if(WIN32_STATIC_BUILD)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLEW_STATIC")
+endif()
+
if (NOT $ENV{GLEWDIR} STREQUAL "")
set(GLEW_DIR "$ENV{GLEWDIR}")
elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
@@ -182,11 +230,8 @@ elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
endif()
find_package(GLEW REQUIRED)
-include_directories(${GLEW_INCLUDE_PATH})
-if(WIN32_STATIC_BUILD)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLEW_STATIC")
-endif()
+inclusion( GLEW_DIR GLEW_INCLUDE_PATH )
# Flex/Bison
find_package(BISON REQUIRED)
@@ -196,6 +241,11 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
set(FLEX_EXECUTABLE /usr/local/bin/flex)
endif()
+if(${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
+ include_directories( /usr/pkg/include /usr/X11R7/include )
+ set(FLEX_EXECUTABLE /usr/pkg/bin/flex)
+endif()
+
find_package(FLEX REQUIRED)
# The COMPILE_FLAGS and forced C++ compiler is just to be compatible with qmake
if (WIN32)
@@ -211,8 +261,13 @@ set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c PROPERTIES
if (NOT $ENV{CGALDIR} STREQUAL "")
set(CGAL_DIR "$ENV{CGALDIR}")
elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "")
- set(CGAL_DIR "$ENV{OPENSCAD_LIBRARIES}/lib/CGAL")
- set(CMAKE_MODULE_PATH "${CGAL_DIR}")
+ if (EXISTS "$ENV{OPENSCAD_LIBRARIES}/lib/CGAL")
+ set(CGAL_DIR "$ENV{OPENSCAD_LIBRARIES}/lib/CGAL")
+ set(CMAKE_MODULE_PATH "${CGAL_DIR}")
+ elseif (EXISTS "$ENV{OPENSCAD_LIBRARIES}/include/CGAL")
+ set(CGAL_DIR "$ENV{OPENSCAD_LIBRARIES}")
+ set(CMAKE_MODULE_PATH "${CGAL_DIR}")
+ endif()
endif()
message(STATUS "CGAL_DIR: " ${CGAL_DIR})
find_package(CGAL REQUIRED)
@@ -224,15 +279,17 @@ message(STATUS "CGAL libraries found in " ${CGAL_LIBRARIES_DIR} )
if("${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}" VERSION_LESS 3.6)
message(FATAL_ERROR "CGAL >= 3.6 required")
endif()
-include_directories(${CGAL_INCLUDE_DIRS})
+inclusion(CGAL_DIR CGAL_INCLUDE_DIRS)
# Imagemagick
-find_package(ImageMagick COMPONENTS convert)
-if (ImageMagick_convert_FOUND)
- message(STATUS "ImageMagick convert executable found: " ${ImageMagick_convert_EXECUTABLE})
-else()
- message(FATAL_ERROR "Couldn't find imagemagick 'convert' program")
+if (NOT SKIP_IMAGEMAGICK)
+ find_package(ImageMagick COMPONENTS convert)
+ if (ImageMagick_convert_FOUND)
+ message(STATUS "ImageMagick convert executable found: " ${ImageMagick_convert_EXECUTABLE})
+ else()
+ message(FATAL_ERROR "Couldn't find imagemagick 'convert' program")
+ endif()
endif()
# Internal includes
@@ -253,6 +310,7 @@ set(CORE_SOURCES
../src/node.cc
../src/context.cc
../src/csgterm.cc
+ ../src/csgtermnormalizer.cc
../src/polyset.cc
../src/csgops.cc
../src/transform.cc
@@ -319,6 +377,7 @@ set(OFFSCREEN_SOURCES
system-gl.cc)
add_library(tests-core STATIC ${CORE_SOURCES})
+target_link_libraries(tests-core ${OPENGL_LIBRARY})
add_library(tests-common STATIC ${COMMON_SOURCES})
target_link_libraries(tests-common tests-core)
add_library(tests-cgal STATIC ${CGAL_SOURCES})
@@ -453,8 +512,8 @@ endfunction()
# comparison method to use
if (NOT $ENV{COMPARATOR} STREQUAL "")
set(COMPARATOR "$ENV{COMPARATOR}")
+ message(STATUS "ImageMagick method modified with COMPARATOR: " ${COMPARATOR})
endif()
-message(STATUS "COMPARATOR: " ${COMPARATOR})
#
# This functions adds cmd-line tests given files.
@@ -486,7 +545,10 @@ macro(add_cmdline_test TESTCMD TESTSUFFIX)
set(CONFARG CONFIGURATIONS)
set(CONFVAL ${FOUNDCONFIGS})
- add_test(NAME ${TEST_FULLNAME} ${CONFARG} ${CONFVAL} COMMAND ${PYTHON_EXECUTABLE} ${tests_SOURCE_DIR}/test_cmdline_tool.py --comparator=${COMPARATOR} -c ${ImageMagick_convert_EXECUTABLE} -s ${TESTSUFFIX} ${CMAKE_BINARY_DIR}/${TESTCMD} "${SCADFILE}")
+ if (MINGW_CROSS_ENV_DIR)
+ set( MINGW_CROSS_ARG "--mingw-cross-env" )
+ endif()
+ add_test(NAME ${TEST_FULLNAME} ${CONFARG} ${CONFVAL} COMMAND ${PYTHON_EXECUTABLE} ${tests_SOURCE_DIR}/test_cmdline_tool.py ${MINGW_CROSS_ARG} --comparator=${COMPARATOR} -c ${ImageMagick_convert_EXECUTABLE} -s ${TESTSUFFIX} ${CMAKE_BINARY_DIR}/${TESTCMD} "${SCADFILE}")
endif()
endforeach()
endmacro()
@@ -496,6 +558,9 @@ enable_testing()
# set up custom pretty printing of results
set(INFOCMD "execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/opencsgtest --info OUTPUT_FILE sysinfo.txt)")
+if (MINGW_CROSS_ENV_DIR)
+ set(INFOCMD "execute_process(COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/opencsgtest --info OUTPUT_FILE sysinfo.txt)")
+endif()
set(PRETTYCMD "\"${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_pretty_print.py --builddir=${CMAKE_CURRENT_BINARY_DIR}\"")
set(CTEST_CUSTOM_FILE ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake)
set(CTEST_CUSTOM_TXT "\n
@@ -518,7 +583,9 @@ file(GLOB FEATURES_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/*.scad)
# Remove included files not to be used as tests
list(REMOVE_ITEM FEATURES_FILES
${CMAKE_SOURCE_DIR}/../testdata/scad/features/include\ test6.scad
- ${CMAKE_SOURCE_DIR}/../testdata/scad/features/include-test5.scad)
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/include-test5.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/use\ test6.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/use-test5.scad)
file(GLOB BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/*.scad)
file(GLOB SCAD_DXF_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/dxf/*.scad)
file(GLOB FUNCTION_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/functions/*.scad)
@@ -548,15 +615,20 @@ list(APPEND CGALSTLSANITYTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/no
# Once we're capable of comparing these across platforms, we can put these back in
disable_tests(dumptest_transform-tests
dumptest_render-tests
+ dumptest_difference-tests
+ dumptest_intersection-tests
dumptest_example001
dumptest_example005
dumptest_example006
dumptest_example007
dumptest_example008
dumptest_example012
+ dumptest_example013
dumptest_example016
+ dumptest_example017
dumptest_example020
- dumptest_example021)
+ dumptest_example021
+ dumptest_example022)
# FIXME: This test illustrates a weakness in child() combined with modifiers.
# Reenable it when this is improved
diff --git a/tests/CMingw-cross-env.cmake b/tests/CMingw-cross-env.cmake
new file mode 100644
index 0000000..09ec1d1
--- /dev/null
+++ b/tests/CMingw-cross-env.cmake
@@ -0,0 +1,144 @@
+#
+# CMake Toolchain file for cross compiling OpenSCAD tests linux->mingw-win32
+# --------------------------------------------------------------------------
+#
+# Prerequisites: mingw-cross-env, ImageMagick 6.5.9.3 or newer, wine
+#
+# Usage:
+#
+# - follow Brad Pitcher's mingw-cross-env for OpenSCAD setup:
+# http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Cross-compiling_for_Windows_on_Linux_or_Mac_OS_X
+# - cross-compile openscad.exe, to verify your installation works properly.
+# - cd openscad/tests && mkdir build-mingw32 && cd build-mingw32
+# - cmake .. -DCMAKE_TOOLCHAIN_FILE=CMingw-cross-env.cmake \
+# -DMINGW_CROSS_ENV_DIR=<where mingw-cross-env is installed>
+# - make should proceed as normal.
+# - now run 'ctest' on your *nix machine.
+# The test .exe programs should run under Wine.
+#
+# See also:
+#
+# http://lists.gnu.org/archive/html/mingw-cross-env-list/2010-11/threads.html#00078
+# (thread "Qt with Cmake")
+# http://lists.gnu.org/archive/html/mingw-cross-env-list/2011-01/threads.html#00012
+# (thread "Qt: pkg-config files?")
+# http://mingw-cross-env.nongnu.org/#requirements
+# http://www.vtk.org/Wiki/CMake_Cross_Compiling
+# https://bitbucket.org/muellni/mingw-cross-env-cmake/src/2067fcf2d52e/src/cmake-1-toolchain-file.patch
+# http://code.google.com/p/qtlobby/source/browse/trunk/toolchain-mingw.cmake
+# http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Link-Options.html
+# Makefile.Release generated by qmake
+# cmake's FindQt4.cmake & Qt4ConfigDependentSettings.cmake files
+# mingw-cross-env's qmake.conf and *.prl files
+# mingw-cross-env's pkg-config files in usr/i686-pc-mingw32/lib/pkgconfig
+# http://www.vtk.org/Wiki/CMake:How_To_Find_Libraries
+#
+
+#
+# Notes:
+#
+# To debug the build process run "make VERBOSE=1". 'strace -f' is also useful.
+#
+# This file is actually called multiple times by cmake, so various 'if NOT set'
+# guards are used to keep programs from running twice.
+#
+# The test will not currently run under win32 because the ctest harness
+# is created by cmake on the machine that it is called on, not on the
+# machine it is targeting.
+#
+
+#
+# Part 1. Find *nix-ImageMagick
+#
+# The tests run under Wine under *nix. Therefore we need to find the
+# ImageMagick comparison program on the *nix machine. It must be
+# searched before the 'cross-compile' environment is setup.
+#
+
+if (NOT imagemagick_cross_set)
+ find_package(ImageMagick COMPONENTS convert REQUIRED)
+ message(STATUS "ImageMagick convert executable found: " ${ImageMagick_convert_EXECUTABLE})
+ set( SKIP_IMAGEMAGICK TRUE )
+ set( imagemagick_cross_set )
+endif()
+
+#
+# Part 2. cross-compiler setup
+#
+
+set(MINGW_CROSS_ENV_DIR $ENV{MINGW_CROSS_ENV_DIR})
+
+set(BUILD_SHARED_LIBS OFF)
+set(CMAKE_SYSTEM_NAME Windows)
+set(MSYS 1)
+set(CMAKE_FIND_ROOT_PATH ${MINGW_CROSS_ENV_DIR}/usr/i686-pc-mingw32)
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+
+set(CMAKE_C_COMPILER ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-gcc)
+set(CMAKE_CXX_COMPILER ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-g++)
+set(QT_QMAKE_EXECUTABLE ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-qmake)
+set(PKG_CONFIG_EXECUTABLE ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-pkg-config)
+set(CMAKE_BUILD_TYPE RelWithDebInfo)
+
+#
+# Part 3. library settings for mingw-cross-env
+#
+
+set( Boost_USE_STATIC_LIBS ON )
+set( Boost_USE_MULTITHREADED ON )
+set( Boost_COMPILER "_win32" )
+# set( Boost_DEBUG TRUE ) # for debugging cmake's FindBoost, not boost itself
+
+set( OPENSCAD_LIBRARIES ${CMAKE_FIND_ROOT_PATH} )
+set( EIGEN2_DIR ${CMAKE_FIND_ROOT_PATH} )
+set( CGAL_DIR ${CMAKE_FIND_ROOT_PATH}/lib/CGAL )
+set( GLEW_DIR ${CMAKE_FIND_ROOT_PATH} )
+
+#
+# Qt4
+#
+# To workaround problems with CMake's FindQt4.cmake when combined with
+# mingw-cross-env (circa early 2012), we here instead use pkg-config. To
+# workaround Cmake's insertion of -bdynamic, we stick 'static' on the
+# end of QT_LIBRARIES
+#
+
+set(QT_QMAKE_EXECUTABLE ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-qmake)
+set(QT_MOC_EXECUTABLE ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-moc)
+set(QT_UIC_EXECUTABLE ${MINGW_CROSS_ENV_DIR}/usr/bin/i686-pc-mingw32-uic)
+
+function(mingw_cross_env_find_qt)
+ # called from CMakeLists.txt
+ find_package( PkgConfig )
+ pkg_check_modules( QTCORE QtCore )
+ pkg_check_modules( QTGUI QtGui )
+ pkg_check_modules( QTOPENGL QtOpenGL )
+
+ set(QT_INCLUDE_DIRS ${QTCORE_INCLUDE_DIRS} ${QTGUI_INCLUDE_DIRS} ${QTOPENGL_INCLUDE_DIRS})
+ set(QT_CFLAGS_OTHER "${QTCORE_CFLAGS_OTHER} ${QTGUI_CFLAGS_OTHER} ${QTOPENGL_CFLAGS_OTHER}")
+ set(QT_LIBRARIES "${QTCORE_STATIC_LDFLAGS} ${QTGUI_STATIC_LDFLAGS} ${QTOPENGL_STATIC_LDFLAGS};-static")
+
+ set(QT_INCLUDE_DIRS ${QT_INCLUDE_DIRS} PARENT_SCOPE)
+ set(QT_CFLAGS_OTHER ${QT_CFLAGS_OTHER} PARENT_SCOPE)
+ set(QT_LIBRARIES ${QT_LIBRARIES} PARENT_SCOPE)
+endfunction()
+
+function(mingw_cross_env_info)
+ message(STATUS "QT INCLUDE_DIRS: ${QT_INCLUDE_DIRS}")
+ message(STATUS "QT LIBRARIES: ${QT_LIBRARIES}")
+ message(STATUS "QT_CFLAGS_OTHER: ${QT_CFLAGS_OTHER}")
+endfunction()
+
+#
+# Part 4. -D definitions
+#
+
+if( NOT cross_defs_set )
+ add_definitions( -DGLEW_STATIC ) # FindGLEW.cmake needs this
+ add_definitions( -DBOOST_STATIC )
+ add_definitions( -DBOOST_THREAD_USE_LIB )
+ add_definitions( -DUNICODE ) # because qmake does it
+ set(cross_defs_set 1)
+endif()
diff --git a/tests/FindGLEW.cmake b/tests/FindGLEW.cmake
index fa3071f..1b0cac4 100644
--- a/tests/FindGLEW.cmake
+++ b/tests/FindGLEW.cmake
@@ -11,13 +11,17 @@
# http://openlibraries.org/browser/trunk/FindGLEW.cmake?rev=1383
-IF (WIN32)
+IF (WIN32 AND MSVC)
IF (WIN32_STATIC_BUILD) # passed from caller
SET(GLEW_LIB_SEARCH_NAME glew32s.lib) # static, non-debug (Release)
ELSE ()
SET(GLEW_LIB_SEARCH_NAME glew32.lib) # other. untested with OpenSCAD
ENDIF()
+ELSE () # GCC
+ SET(GLEW_LIB_SEARCH_NAME "libglew32s.a")
+ENDIF ()
+IF (WIN32)
FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
$ENV{PROGRAMFILES}/GLEW/include
${PROJECT_SOURCE_DIR}/src/nvgl/glew/include
@@ -33,13 +37,13 @@ ELSE (WIN32)
message(STATUS "GLEW_DIR: " ${GLEW_DIR})
FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
HINTS ${GLEW_DIR}/include
- PATHS /usr/include /usr/local/include
+ PATHS /usr/include /usr/local/include /usr/pkg/include
NO_DEFAULT_PATH
DOC "The directory where GL/glew.h resides")
FIND_LIBRARY( GLEW_LIBRARY
NAMES GLEW glew
HINTS ${GLEW_DIR}/lib
- PATHS /usr/lib /usr/local/lib
+ PATHS /usr/lib /usr/local/lib /usr/pkg/lib
NO_DEFAULT_PATH
DOC "The GLEW library")
ENDIF (WIN32)
diff --git a/tests/OffscreenContextWGL.cc b/tests/OffscreenContextWGL.cc
index f36671c..75a7ed2 100644
--- a/tests/OffscreenContextWGL.cc
+++ b/tests/OffscreenContextWGL.cc
@@ -105,10 +105,10 @@ bool create_wgl_dummy_context(OffscreenContext &ctx)
wc.style = CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.hInstance = inst;
- wc.lpszClassName = "OpenSCAD";
+ wc.lpszClassName = (LPCWSTR)"OpenSCAD";
RegisterClass( &wc );
- HWND window = CreateWindow( "OpenSCAD", "OpenSCAD",
+ HWND window = CreateWindow( (LPCWSTR)"OpenSCAD", (LPCWSTR)"OpenSCAD",
WS_CAPTION | WS_POPUPWINDOW, //| WS_VISIBLE,
0, 0, ctx.width, ctx.height, NULL, NULL, inst, NULL );
diff --git a/tests/csgtestcore.cc b/tests/csgtestcore.cc
index c2be326..e8a6878 100644
--- a/tests/csgtestcore.cc
+++ b/tests/csgtestcore.cc
@@ -19,6 +19,7 @@
#include "ThrownTogetherRenderer.h"
#include "csgterm.h"
+#include "csgtermnormalizer.h"
#include "OffscreenView.h"
#include <QApplication>
@@ -315,12 +316,8 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)
}
// CSG normalization
- csgInfo.root_norm_term = root_raw_term;
- while (1) {
- shared_ptr<CSGTerm> n = CSGTerm::normalize(csgInfo.root_norm_term);
- if (csgInfo.root_norm_term == n) break;
- csgInfo.root_norm_term = n;
- }
+ CSGTermNormalizer normalizer;
+ csgInfo.root_norm_term = normalizer.normalize(root_raw_term);
assert(csgInfo.root_norm_term);
@@ -333,11 +330,7 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)
csgInfo.highlights_chain = new CSGChain();
for (unsigned int i = 0; i < csgInfo.highlight_terms.size(); i++) {
- while (1) {
- shared_ptr<CSGTerm> n = CSGTerm::normalize(csgInfo.highlight_terms[i]);
- if (csgInfo.highlight_terms[i] == n) break;
- csgInfo.highlight_terms[i] = n;
- }
+ csgInfo.highlight_terms[i] = normalizer.normalize(csgInfo.highlight_terms[i]);
csgInfo.highlights_chain->import(csgInfo.highlight_terms[i]);
}
}
@@ -347,11 +340,7 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)
csgInfo.background_chain = new CSGChain();
for (unsigned int i = 0; i < csgInfo.background_terms.size(); i++) {
- while (1) {
- shared_ptr<CSGTerm> n = CSGTerm::normalize(csgInfo.background_terms[i]);
- if (csgInfo.background_terms[i] == n) break;
- csgInfo.background_terms[i] = n;
- }
+ csgInfo.background_terms[i] = normalizer.normalize(csgInfo.background_terms[i]);
csgInfo.background_chain->import(csgInfo.background_terms[i]);
}
}
diff --git a/tests/dumptest.cc b/tests/dumptest.cc
index 22dd96c..f83a993 100644
--- a/tests/dumptest.cc
+++ b/tests/dumptest.cc
@@ -65,10 +65,9 @@ string dumptree(const Tree &tree, const AbstractNode &node)
int main(int argc, char **argv)
{
-#ifdef WIN32
+#ifdef _MSC_VER
_set_output_format(_TWO_DIGIT_EXPONENT);
#endif
-
if (argc != 3) {
fprintf(stderr, "Usage: %s <file.scad> <output.txt>\n", argv[0]);
exit(1);
diff --git a/tests/echotest.cc b/tests/echotest.cc
index afa3d03..8f145b0 100644
--- a/tests/echotest.cc
+++ b/tests/echotest.cc
@@ -59,7 +59,7 @@ static void outfile_handler(const std::string &msg, void *userdata) {
int main(int argc, char **argv)
{
-#ifdef WIN32
+#ifdef _MSC_VER
_set_output_format(_TWO_DIGIT_EXPONENT);
#endif
diff --git a/tests/regression/cgalpngtest/cylinder-tests-expected.png b/tests/regression/cgalpngtest/cylinder-tests-expected.png
index 9d96df2..843d70f 100644
--- a/tests/regression/cgalpngtest/cylinder-tests-expected.png
+++ b/tests/regression/cgalpngtest/cylinder-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/intersection-tests-expected.png b/tests/regression/cgalpngtest/intersection-tests-expected.png
index 6d004b0..d287e5f 100644
--- a/tests/regression/cgalpngtest/intersection-tests-expected.png
+++ b/tests/regression/cgalpngtest/intersection-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/use-tests-expected.png b/tests/regression/cgalpngtest/use-tests-expected.png
new file mode 100644
index 0000000..21747cc
--- /dev/null
+++ b/tests/regression/cgalpngtest/use-tests-expected.png
Binary files differ
diff --git a/tests/regression/dumptest/cylinder-tests-expected.txt b/tests/regression/dumptest/cylinder-tests-expected.txt
index 2ac2549..b1e8b6e 100644
--- a/tests/regression/dumptest/cylinder-tests-expected.txt
+++ b/tests/regression/dumptest/cylinder-tests-expected.txt
@@ -29,4 +29,7 @@
multmatrix([[1, 0, 0, 22], [0, 1, 0, 11], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cylinder($fn = 0, $fa = 12, $fs = 2, h = 15, r1 = 5, r2 = 5, center = false);
}
+ multmatrix([[1, 0, 0, -10], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ cylinder($fn = 6, $fa = 12, $fs = 2, h = 2, r1 = 3, r2 = 3, center = false);
+ }
diff --git a/tests/regression/dumptest/intersection-tests-expected.txt b/tests/regression/dumptest/intersection-tests-expected.txt
index e6bbf32..a9dba29 100644
--- a/tests/regression/dumptest/intersection-tests-expected.txt
+++ b/tests/regression/dumptest/intersection-tests-expected.txt
@@ -24,7 +24,7 @@
multmatrix([[1, 0, 0, 12], [0, 1, 0, 12], [0, 0, 1, 0], [0, 0, 0, 1]]) {
intersection() {
cube(size = [10, 10, 10], center = true);
- multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 7], [0, 0, 0, 1]]) {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 7.01], [0, 0, 0, 1]]) {
cylinder($fn = 0, $fa = 12, $fs = 2, h = 4, r1 = 4, r2 = 4, center = true);
}
}
diff --git a/tests/regression/dumptest/testcolornames-expected.txt b/tests/regression/dumptest/testcolornames-expected.txt
index 56e664f..63b5e70 100644
--- a/tests/regression/dumptest/testcolornames-expected.txt
+++ b/tests/regression/dumptest/testcolornames-expected.txt
@@ -49,7 +49,7 @@
}
}
multmatrix([[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]]) {
- color([1, 0.713725, 0.756863, 1]) {
+ color([1, 0.713726, 0.756863, 1]) {
sphere($fn = 5, $fa = 12, $fs = 2, r = 0.8);
}
}
@@ -79,7 +79,7 @@
}
}
multmatrix([[1, 0, 0, 8], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]]) {
- color([1, 0.498039, 0.313725, 1]) {
+ color([1, 0.498039, 0.313726, 1]) {
sphere($fn = 5, $fa = 12, $fs = 2, r = 0.8);
}
}
diff --git a/tests/regression/dumptest/use-tests-expected.txt b/tests/regression/dumptest/use-tests-expected.txt
new file mode 100644
index 0000000..7ba3ac5
--- /dev/null
+++ b/tests/regression/dumptest/use-tests-expected.txt
@@ -0,0 +1,34 @@
+ group() {
+ group() {
+ multmatrix([[1, 0, 0, 2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 0.7, r2 = 0.2, center = true);
+ }
+ }
+ multmatrix([[1, 0, 0, 2], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ cylinder($fn = 10, $fa = 12, $fs = 2, h = 1, r1 = 0.5, r2 = 0.5, center = true);
+ }
+ }
+ cube(size = [1, 1, 1], center = true);
+ }
+ multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
+ multmatrix([[1, 0, 0, 4], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]);
+ multmatrix([[1, 0, 0, -2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ sphere($fn = 8, $fa = 12, $fs = 2, r = 0.5);
+ }
+ }
+ multmatrix([[1, 0, 0, -2], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ difference() {
+ cube(size = [1, 1, 1], center = true);
+ cylinder($fn = 0, $fa = 12, $fs = 2, h = 2, r1 = 0.4, r2 = 0.4, center = true);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ sphere($fn = 16, $fa = 12, $fs = 2, r = 1);
+ }
+ }
+
diff --git a/tests/regression/opencsgtest/color-tests-expected.png b/tests/regression/opencsgtest/color-tests-expected.png
index 82ba36a..5b35312 100644
--- a/tests/regression/opencsgtest/color-tests-expected.png
+++ b/tests/regression/opencsgtest/color-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/cylinder-tests-expected.png b/tests/regression/opencsgtest/cylinder-tests-expected.png
index 17c10b8..4c7ab79 100644
--- a/tests/regression/opencsgtest/cylinder-tests-expected.png
+++ b/tests/regression/opencsgtest/cylinder-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/example010-expected.png b/tests/regression/opencsgtest/example010-expected.png
index 3a4ba27..0616f87 100644
--- a/tests/regression/opencsgtest/example010-expected.png
+++ b/tests/regression/opencsgtest/example010-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/example015-expected.png b/tests/regression/opencsgtest/example015-expected.png
index 1a1c869..78ec3d7 100644
--- a/tests/regression/opencsgtest/example015-expected.png
+++ b/tests/regression/opencsgtest/example015-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/example021-expected.png b/tests/regression/opencsgtest/example021-expected.png
index 675e57b..bf3a281 100644
--- a/tests/regression/opencsgtest/example021-expected.png
+++ b/tests/regression/opencsgtest/example021-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/intersection-tests-expected.png b/tests/regression/opencsgtest/intersection-tests-expected.png
index fc23560..772e2dc 100644
--- a/tests/regression/opencsgtest/intersection-tests-expected.png
+++ b/tests/regression/opencsgtest/intersection-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/use-tests-expected.png b/tests/regression/opencsgtest/use-tests-expected.png
new file mode 100644
index 0000000..8a85ad5
--- /dev/null
+++ b/tests/regression/opencsgtest/use-tests-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/color-tests-expected.png b/tests/regression/throwntogethertest/color-tests-expected.png
index 5d4ed89..8fb69b1 100644
--- a/tests/regression/throwntogethertest/color-tests-expected.png
+++ b/tests/regression/throwntogethertest/color-tests-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/cylinder-tests-expected.png b/tests/regression/throwntogethertest/cylinder-tests-expected.png
index 0a3ed33..4c7ab79 100644
--- a/tests/regression/throwntogethertest/cylinder-tests-expected.png
+++ b/tests/regression/throwntogethertest/cylinder-tests-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/example008-expected.png b/tests/regression/throwntogethertest/example008-expected.png
index 880844b..f825047 100644
--- a/tests/regression/throwntogethertest/example008-expected.png
+++ b/tests/regression/throwntogethertest/example008-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/example010-expected.png b/tests/regression/throwntogethertest/example010-expected.png
index 854eea8..87271eb 100644
--- a/tests/regression/throwntogethertest/example010-expected.png
+++ b/tests/regression/throwntogethertest/example010-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/example014-expected.png b/tests/regression/throwntogethertest/example014-expected.png
index 562ce74..4721663 100644
--- a/tests/regression/throwntogethertest/example014-expected.png
+++ b/tests/regression/throwntogethertest/example014-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/example015-expected.png b/tests/regression/throwntogethertest/example015-expected.png
index 6e16e33..85374b5 100644
--- a/tests/regression/throwntogethertest/example015-expected.png
+++ b/tests/regression/throwntogethertest/example015-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/example021-expected.png b/tests/regression/throwntogethertest/example021-expected.png
index 1e1576c..cfe303a 100644
--- a/tests/regression/throwntogethertest/example021-expected.png
+++ b/tests/regression/throwntogethertest/example021-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/intersection-tests-expected.png b/tests/regression/throwntogethertest/intersection-tests-expected.png
index f6cf6af..f6cc56f 100644
--- a/tests/regression/throwntogethertest/intersection-tests-expected.png
+++ b/tests/regression/throwntogethertest/intersection-tests-expected.png
Binary files differ
diff --git a/tests/regression/throwntogethertest/use-tests-expected.png b/tests/regression/throwntogethertest/use-tests-expected.png
new file mode 100644
index 0000000..e5bf382
--- /dev/null
+++ b/tests/regression/throwntogethertest/use-tests-expected.png
Binary files differ
diff --git a/tests/test_cmdline_tool.py b/tests/test_cmdline_tool.py
index 967e334..f29acc0 100755
--- a/tests/test_cmdline_tool.py
+++ b/tests/test_cmdline_tool.py
@@ -61,7 +61,11 @@ def execute_and_redirect(cmd, params, outfile):
else: return retval
def get_normalized_text(filename):
- text = open(filename).read()
+ try:
+ f = open(filename)
+ text = f.read()
+ except:
+ text = ''
return text.strip("\r\n").replace("\r\n", "\n") + "\n"
def compare_text(expected, actual):
@@ -71,8 +75,9 @@ def compare_default(resultfilename):
print >> sys.stderr, 'diff text compare: '
print >> sys.stderr, ' expected textfile: ', expectedfilename
print >> sys.stderr, ' actual textfile: ', resultfilename
- if not compare_text(expectedfilename, resultfilename):
- execute_and_redirect("diff", [expectedfilename, resultfilename], sys.stderr)
+ if not compare_text(expectedfilename, resultfilename):
+ if resultfilename:
+ execute_and_redirect("diff", [expectedfilename, resultfilename], sys.stderr)
return False
return True
@@ -110,7 +115,7 @@ def compare_png(resultfilename):
elif compare_method=='NCC':
thresh = 0.95
ncc_err = float(output.strip())
- if ncc_err > thresh: return True
+ if ncc_err > thresh or ncc_err==0.0: return True
else: print >> sys.stderr, ncc_err, ' Images differ: NCC comparison < ', thresh
return False
@@ -136,8 +141,13 @@ def run_test(testname, cmd, args):
outputname = os.path.normpath( outputname )
outfile = open(outputname, "wb")
+
try:
- proc = subprocess.Popen([cmd] + args + [outputname], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ if os.path.isfile(cmd+'.exe') and options.mingw_cross_env:
+ cmdline = ['wine']+[cmd+'.exe'] + args + [outputname]
+ else:
+ cmdline = [cmd] + args + [outputname]
+ proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
errtext = proc.communicate()[1]
if errtext != None and len(errtext) > 0:
print >> sys.stderr, "Error output: " + errtext
@@ -166,11 +176,11 @@ def usage():
print >> sys.stderr, " -s, --suffix=<suffix> Write -expected and -actual files with the given suffix instead of .txt"
print >> sys.stderr, " -t, --test=<name> Specify test name instead of deducting it from the argument"
print >> sys.stderr, " -c, --convexec=<name> Path to ImageMagick 'convert' executable"
-
+ print >> sys.stderr, " -x, --mingw-cross-env Mingw-cross-env cross compilation"
if __name__ == '__main__':
# Handle command-line arguments
try:
- opts, args = getopt.getopt(sys.argv[1:], "gs:c:t:m:", ["generate", "convexec=", "suffix=", "test=", "comparator="])
+ opts, args = getopt.getopt(sys.argv[1:], "gs:c:t:m:x", ["generate", "convexec=", "suffix=", "test=", "comparator=", "mingw-cross-env"])
except getopt.GetoptError, err:
usage()
sys.exit(2)
@@ -192,6 +202,8 @@ if __name__ == '__main__':
options.convert_exec = os.path.normpath( a )
elif o in ("-m", "--comparator"):
options.comparator = a
+ elif o in ("-x", "--mingw-cross-env"):
+ options.mingw_cross_env = True
# <cmdline-tool> and <argument>
if len(args) < 2:
diff --git a/version.pri b/version.pri
index c94ab82..6b91ecd 100644
--- a/version.pri
+++ b/version.pri
@@ -1,7 +1,7 @@
# get VERSION from system date
isEmpty(VERSION) {
- win32-msvc*: {
+ win32-msvc*:!mingw-cross-env {
#
# Windows XP date command only has one argument, /t
# and it can print the date in various localized formats.
@@ -51,17 +51,18 @@ isEmpty(VERSION) {
} else {
# Unix/Mac
VERSION = $$system(date "+%Y.%m.%d")
- VERSION_SPLIT=$$split(VERSION, ".")
- VERSION_YEAR=$$member(VERSION_SPLIT, 0)
- VERSION_MONTH=$$member(VERSION_SPLIT, 1)
- VERSION_DAY=$$member(VERSION_SPLIT, 2)
}
- # Fix for problem with integers with leading zeros
- # being interpreted by C++ as octals. Now they're doubles.
- VERSION_YEAR=$${VERSION_YEAR}.0
- VERSION_MONTH=$${VERSION_MONTH}.0
- VERSION_DAY=$${VERSION_DAY}.0
}
+VERSION_SPLIT=$$split(VERSION, ".")
+VERSION_YEAR=$$member(VERSION_SPLIT, 0)
+VERSION_MONTH=$$member(VERSION_SPLIT, 1)
+VERSION_DAY=$$member(VERSION_SPLIT, 2)
+# Fix for problem with integers with leading zeros
+# being interpreted by C++ as octals. Now they're doubles.
+VERSION_YEAR=$${VERSION_YEAR}.0
+VERSION_MONTH=$${VERSION_MONTH}.0
+VERSION_DAY=$${VERSION_DAY}.0
+
DEFINES += OPENSCAD_VERSION=$$VERSION OPENSCAD_YEAR=$$VERSION_YEAR OPENSCAD_MONTH=$$VERSION_MONTH
!isEmpty(VERSION_DAY): DEFINES += OPENSCAD_DAY=$$VERSION_DAY
contact: Jan Huwald // Impressum