summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/CMakeLists.txt246
-rw-r--r--tests/CSGTextCache.cc27
-rw-r--r--tests/CSGTextCache.h27
-rw-r--r--tests/CSGTextRenderer.cc185
-rw-r--r--tests/CSGTextRenderer.h40
-rw-r--r--tests/FindGLEW.cmake40
-rw-r--r--tests/OffscreenContext.h14
-rw-r--r--tests/OffscreenContext.mm207
-rw-r--r--tests/OffscreenView.cc239
-rw-r--r--tests/OffscreenView.h39
-rw-r--r--tests/cgalpngtest.cc234
-rw-r--r--tests/cgaltest.cc180
-rwxr-xr-xtests/compare-bitmaps.sh31
-rw-r--r--tests/csgtermtest.cc172
-rw-r--r--tests/csgtexttest.cc158
-rw-r--r--tests/dumptest.cc155
-rw-r--r--tests/opencsgtest.cc251
-rw-r--r--tests/regression/cgalpngtest/2d-3d-expected.pngbin0 -> 7842 bytes
-rw-r--r--tests/regression/cgalpngtest/assign-tests-expected.pngbin0 -> 9420 bytes
-rw-r--r--tests/regression/cgalpngtest/background-modifier-expected.pngbin0 -> 14578 bytes
-rw-r--r--tests/regression/cgalpngtest/circle-tests-expected.pngbin0 -> 8435 bytes
-rw-r--r--tests/regression/cgalpngtest/color-tests-expected.pngbin0 -> 9554 bytes
-rw-r--r--tests/regression/cgalpngtest/cube-tests-expected.pngbin0 -> 8008 bytes
-rw-r--r--tests/regression/cgalpngtest/cylinder-tests-expected.pngbin0 -> 12498 bytes
-rw-r--r--tests/regression/cgalpngtest/difference-tests-expected.pngbin0 -> 11151 bytes
-rw-r--r--tests/regression/cgalpngtest/disable-modifier-expected.pngbin0 -> 7433 bytes
-rw-r--r--tests/regression/cgalpngtest/for-nested-tests-expected.pngbin0 -> 23800 bytes
-rw-r--r--tests/regression/cgalpngtest/for-tests-expected.pngbin0 -> 10995 bytes
-rw-r--r--tests/regression/cgalpngtest/highlight-modifier-expected.pngbin0 -> 13772 bytes
-rw-r--r--tests/regression/cgalpngtest/hull2-tests-expected.pngbin0 -> 7531 bytes
-rw-r--r--tests/regression/cgalpngtest/import_dxf-tests-expected.pngbin0 -> 9919 bytes
-rw-r--r--tests/regression/cgalpngtest/intersection-tests-expected.pngbin0 -> 8295 bytes
-rw-r--r--tests/regression/cgalpngtest/intersection_for-tests-expected.pngbin0 -> 8314 bytes
-rw-r--r--tests/regression/cgalpngtest/linear_extrude-tests-expected.pngbin0 -> 12143 bytes
-rw-r--r--tests/regression/cgalpngtest/minkowski2-tests-expected.pngbin0 -> 7538 bytes
-rw-r--r--tests/regression/cgalpngtest/minkowski3-tests-expected.pngbin0 -> 8602 bytes
-rw-r--r--tests/regression/cgalpngtest/polygon-tests-expected.pngbin0 -> 8240 bytes
-rw-r--r--tests/regression/cgalpngtest/projection-tests-expected.pngbin0 -> 9159 bytes
-rw-r--r--tests/regression/cgalpngtest/render-tests-expected.pngbin0 -> 10002 bytes
-rw-r--r--tests/regression/cgalpngtest/root-modifier-expected.pngbin0 -> 7433 bytes
-rw-r--r--tests/regression/cgalpngtest/rotate_extrude-tests-expected.pngbin0 -> 20273 bytes
-rw-r--r--tests/regression/cgalpngtest/sphere-tests-expected.pngbin0 -> 17379 bytes
-rw-r--r--tests/regression/cgalpngtest/square-tests-expected.pngbin0 -> 7820 bytes
-rw-r--r--tests/regression/cgalpngtest/surface-tests-expected.pngbin0 -> 36682 bytes
-rw-r--r--tests/regression/cgalpngtest/transform-tests-expected.pngbin0 -> 16015 bytes
-rw-r--r--tests/regression/cgalpngtest/union-tests-expected.pngbin0 -> 9818 bytes
-rw-r--r--tests/regression/csgtermtest/allfunctions-expected.txt1
-rw-r--r--tests/regression/csgtermtest/allmodules-expected.txt1
-rw-r--r--tests/regression/csgtermtest/assign-expected.txt1
-rw-r--r--tests/regression/csgtermtest/child-expected.txt1
-rw-r--r--tests/regression/csgtermtest/circle-expected.txt1
-rw-r--r--tests/regression/csgtermtest/color-expected.txt1
-rw-r--r--tests/regression/csgtermtest/cube-expected.txt1
-rw-r--r--tests/regression/csgtermtest/cylinder-expected.txt1
-rw-r--r--tests/regression/csgtermtest/difference-expected.txt1
-rw-r--r--tests/regression/csgtermtest/dxf_linear_extrude-expected.txt1
-rw-r--r--tests/regression/csgtermtest/dxf_rotate_extrude-expected.txt1
-rw-r--r--tests/regression/csgtermtest/echo-expected.txt1
-rw-r--r--tests/regression/csgtermtest/for-expected.txt1
-rw-r--r--tests/regression/csgtermtest/glide-expected.txt1
-rw-r--r--tests/regression/csgtermtest/group-expected.txt1
-rw-r--r--tests/regression/csgtermtest/hull-expected.txt1
-rw-r--r--tests/regression/csgtermtest/if-expected.txt1
-rw-r--r--tests/regression/csgtermtest/import-expected.txt1
-rw-r--r--tests/regression/csgtermtest/import_dxf-expected.txt1
-rw-r--r--tests/regression/csgtermtest/import_off-expected.txt1
-rw-r--r--tests/regression/csgtermtest/import_stl-expected.txt1
-rw-r--r--tests/regression/csgtermtest/intersection-expected.txt1
-rw-r--r--tests/regression/csgtermtest/intersection_for-expected.txt1
-rw-r--r--tests/regression/csgtermtest/linear_extrude-expected.txt1
-rw-r--r--tests/regression/csgtermtest/minkowski-expected.txt1
-rw-r--r--tests/regression/csgtermtest/mirror-expected.txt1
-rw-r--r--tests/regression/csgtermtest/multmatrix-expected.txt1
-rw-r--r--tests/regression/csgtermtest/polygon-expected.txt1
-rw-r--r--tests/regression/csgtermtest/polyhedron-expected.txt1
-rw-r--r--tests/regression/csgtermtest/projection-expected.txt1
-rw-r--r--tests/regression/csgtermtest/render-expected.txt1
-rw-r--r--tests/regression/csgtermtest/rotate-expected.txt1
-rw-r--r--tests/regression/csgtermtest/rotate_extrude-expected.txt1
-rw-r--r--tests/regression/csgtermtest/scale-expected.txt1
-rw-r--r--tests/regression/csgtermtest/sphere-expected.txt1
-rw-r--r--tests/regression/csgtermtest/square-expected.txt1
-rw-r--r--tests/regression/csgtermtest/subdiv-expected.txt1
-rw-r--r--tests/regression/csgtermtest/surface-expected.txt1
-rw-r--r--tests/regression/csgtermtest/transform-insert-expected.txt1
-rw-r--r--tests/regression/csgtermtest/translate-expected.txt1
-rw-r--r--tests/regression/csgtermtest/union-expected.txt1
-rw-r--r--tests/regression/csgtexttest/allfunctions-expected.txt1
-rw-r--r--tests/regression/csgtexttest/allmodules-expected.txt1
-rw-r--r--tests/regression/csgtexttest/assign-expected.txt1
-rw-r--r--tests/regression/csgtexttest/child-expected.txt1
-rw-r--r--tests/regression/csgtexttest/circle-expected.txt1
-rw-r--r--tests/regression/csgtexttest/color-expected.txt1
-rw-r--r--tests/regression/csgtexttest/cube-expected.txt1
-rw-r--r--tests/regression/csgtexttest/cylinder-expected.txt1
-rw-r--r--tests/regression/csgtexttest/difference-expected.txt1
-rw-r--r--tests/regression/csgtexttest/difference-tests-expected.txt1
-rw-r--r--tests/regression/csgtexttest/dim-all-expected.txt1
-rw-r--r--tests/regression/csgtexttest/dxf_linear_extrude-expected.txt1
-rw-r--r--tests/regression/csgtexttest/dxf_rotate_extrude-expected.txt1
-rw-r--r--tests/regression/csgtexttest/echo-expected.txt1
-rw-r--r--tests/regression/csgtexttest/for-expected.txt1
-rw-r--r--tests/regression/csgtexttest/glide-expected.txt1
-rw-r--r--tests/regression/csgtexttest/group-expected.txt1
-rw-r--r--tests/regression/csgtexttest/hull-expected.txt1
-rw-r--r--tests/regression/csgtexttest/if-expected.txt1
-rw-r--r--tests/regression/csgtexttest/import-expected.txt1
-rw-r--r--tests/regression/csgtexttest/import_dxf-expected.txt1
-rw-r--r--tests/regression/csgtexttest/import_off-expected.txt1
-rw-r--r--tests/regression/csgtexttest/import_stl-expected.txt1
-rw-r--r--tests/regression/csgtexttest/import_stl-tests-expected.txt1
-rw-r--r--tests/regression/csgtexttest/intersection-expected.txt1
-rw-r--r--tests/regression/csgtexttest/intersection-tests-expected.txt1
-rw-r--r--tests/regression/csgtexttest/intersection_for-expected.txt1
-rw-r--r--tests/regression/csgtexttest/linear_extrude-expected.txt1
-rw-r--r--tests/regression/csgtexttest/linear_extrude-tests-expected.txt1
-rw-r--r--tests/regression/csgtexttest/minkowski-expected.txt1
-rw-r--r--tests/regression/csgtexttest/mirror-expected.txt1
-rw-r--r--tests/regression/csgtexttest/multmatrix-expected.txt1
-rw-r--r--tests/regression/csgtexttest/null-polygons-expected.txt1
-rw-r--r--tests/regression/csgtexttest/polygon-expected.txt1
-rw-r--r--tests/regression/csgtexttest/polygon-illegal-winding-expected.txt1
-rw-r--r--tests/regression/csgtexttest/polyhedron-expected.txt1
-rw-r--r--tests/regression/csgtexttest/polyset-reduce-crash-expected.txt1
-rw-r--r--tests/regression/csgtexttest/projection-expected.txt1
-rw-r--r--tests/regression/csgtexttest/projection-tests-expected.txt1
-rw-r--r--tests/regression/csgtexttest/render-expected.txt1
-rw-r--r--tests/regression/csgtexttest/rotate-expected.txt1
-rw-r--r--tests/regression/csgtexttest/rotate_extrude-expected.txt1
-rw-r--r--tests/regression/csgtexttest/rotate_extrude-tests-expected.txt1
-rw-r--r--tests/regression/csgtexttest/scale-expected.txt1
-rw-r--r--tests/regression/csgtexttest/sphere-expected.txt1
-rw-r--r--tests/regression/csgtexttest/sphere-tests-expected.txt1
-rw-r--r--tests/regression/csgtexttest/square-expected.txt1
-rw-r--r--tests/regression/csgtexttest/subdiv-expected.txt1
-rw-r--r--tests/regression/csgtexttest/surface-expected.txt1
-rw-r--r--tests/regression/csgtexttest/surface-tests-expected.txt1
-rw-r--r--tests/regression/csgtexttest/transform-insert-expected.txt1
-rw-r--r--tests/regression/csgtexttest/translate-expected.txt1
-rw-r--r--tests/regression/csgtexttest/union-expected.txt1
-rw-r--r--tests/regression/dumptest/allfunctions-expected.txt1
-rw-r--r--tests/regression/dumptest/allmodules-expected.txt39
-rw-r--r--tests/regression/dumptest/assign-expected.txt3
-rw-r--r--tests/regression/dumptest/child-expected.txt1
-rw-r--r--tests/regression/dumptest/circle-expected.txt3
-rw-r--r--tests/regression/dumptest/color-expected.txt3
-rw-r--r--tests/regression/dumptest/cube-expected.txt3
-rw-r--r--tests/regression/dumptest/cylinder-expected.txt3
-rw-r--r--tests/regression/dumptest/difference-expected.txt3
-rw-r--r--tests/regression/dumptest/difference-tests-expected.txt6
-rw-r--r--tests/regression/dumptest/dim-all-expected.txt10
-rw-r--r--tests/regression/dumptest/dxf-export-expected.txt17
-rw-r--r--tests/regression/dumptest/dxf_linear_extrude-expected.txt3
-rw-r--r--tests/regression/dumptest/dxf_rotate_extrude-expected.txt3
-rw-r--r--tests/regression/dumptest/echo-expected.txt3
-rw-r--r--tests/regression/dumptest/for-expected.txt3
-rw-r--r--tests/regression/dumptest/glide-expected.txt3
-rw-r--r--tests/regression/dumptest/group-expected.txt3
-rw-r--r--tests/regression/dumptest/hull-expected.txt3
-rw-r--r--tests/regression/dumptest/hull-tests-expected.txt46
-rw-r--r--tests/regression/dumptest/if-expected.txt3
-rw-r--r--tests/regression/dumptest/import-expected.txt3
-rw-r--r--tests/regression/dumptest/import_dxf-expected.txt3
-rw-r--r--tests/regression/dumptest/import_off-expected.txt3
-rw-r--r--tests/regression/dumptest/import_stl-expected.txt3
-rw-r--r--tests/regression/dumptest/import_stl-tests-expected.txt3
-rw-r--r--tests/regression/dumptest/include-test-expected.txt20
-rw-r--r--tests/regression/dumptest/intersection-expected.txt3
-rw-r--r--tests/regression/dumptest/intersection-tests-expected.txt6
-rw-r--r--tests/regression/dumptest/intersection_for-expected.txt3
-rw-r--r--tests/regression/dumptest/linear_extrude-expected.txt3
-rw-r--r--tests/regression/dumptest/linear_extrude-tests-expected.txt30
-rw-r--r--tests/regression/dumptest/minkowski-expected.txt3
-rw-r--r--tests/regression/dumptest/minkowski-tests-expected.txt66
-rw-r--r--tests/regression/dumptest/mirror-expected.txt3
-rw-r--r--tests/regression/dumptest/multmatrix-expected.txt3
-rw-r--r--tests/regression/dumptest/null-polygons-expected.txt6
-rw-r--r--tests/regression/dumptest/polygon-expected.txt3
-rw-r--r--tests/regression/dumptest/polygon-illegal-winding-expected.txt3
-rw-r--r--tests/regression/dumptest/polyhedron-expected.txt3
-rw-r--r--tests/regression/dumptest/polyset-reduce-crash-expected.txt17
-rw-r--r--tests/regression/dumptest/projection-expected.txt3
-rw-r--r--tests/regression/dumptest/projection-tests-expected.txt25
-rw-r--r--tests/regression/dumptest/render-expected.txt3
-rw-r--r--tests/regression/dumptest/rotate-expected.txt3
-rw-r--r--tests/regression/dumptest/rotate_extrude-expected.txt3
-rw-r--r--tests/regression/dumptest/rotate_extrude-tests-expected.txt7
-rw-r--r--tests/regression/dumptest/scale-expected.txt3
-rw-r--r--tests/regression/dumptest/sphere-expected.txt3
-rw-r--r--tests/regression/dumptest/sphere-tests-expected.txt12
-rw-r--r--tests/regression/dumptest/square-expected.txt3
-rw-r--r--tests/regression/dumptest/string-test-expected.txt3
-rw-r--r--tests/regression/dumptest/subdiv-expected.txt3
-rw-r--r--tests/regression/dumptest/surface-expected.txt3
-rw-r--r--tests/regression/dumptest/surface-tests-expected.txt3
-rw-r--r--tests/regression/dumptest/transform-insert-expected.txt3
-rw-r--r--tests/regression/dumptest/translate-expected.txt3
-rw-r--r--tests/regression/dumptest/union-expected.txt3
-rw-r--r--tests/regression/opencsgtest/2d-3d-expected.pngbin0 -> 8246 bytes
-rw-r--r--tests/regression/opencsgtest/assign-tests-expected.pngbin0 -> 9990 bytes
-rw-r--r--tests/regression/opencsgtest/background-modifier-expected.pngbin0 -> 17699 bytes
-rw-r--r--tests/regression/opencsgtest/circle-tests-expected.pngbin0 -> 9537 bytes
-rw-r--r--tests/regression/opencsgtest/color-tests-expected.pngbin0 -> 11055 bytes
-rw-r--r--tests/regression/opencsgtest/cube-tests-expected.pngbin0 -> 7965 bytes
-rw-r--r--tests/regression/opencsgtest/cylinder-tests-expected.pngbin0 -> 13165 bytes
-rw-r--r--tests/regression/opencsgtest/difference-tests-expected.pngbin0 -> 12383 bytes
-rw-r--r--tests/regression/opencsgtest/disable-modifier-expected.pngbin0 -> 7440 bytes
-rw-r--r--tests/regression/opencsgtest/for-nested-tests-expected.pngbin0 -> 25755 bytes
-rw-r--r--tests/regression/opencsgtest/for-tests-expected.pngbin0 -> 11584 bytes
-rw-r--r--tests/regression/opencsgtest/highlight-modifier-expected.pngbin0 -> 15502 bytes
-rw-r--r--tests/regression/opencsgtest/hull2-tests-expected.pngbin0 -> 8078 bytes
-rw-r--r--tests/regression/opencsgtest/import_dxf-tests-expected.pngbin0 -> 9289 bytes
-rw-r--r--tests/regression/opencsgtest/intersection-tests-expected.pngbin0 -> 8069 bytes
-rw-r--r--tests/regression/opencsgtest/intersection_for-tests-expected.pngbin0 -> 6642 bytes
-rw-r--r--tests/regression/opencsgtest/linear_extrude-tests-expected.pngbin0 -> 12466 bytes
-rw-r--r--tests/regression/opencsgtest/minkowski2-tests-expected.pngbin0 -> 8177 bytes
-rw-r--r--tests/regression/opencsgtest/minkowski3-tests-expected.pngbin0 -> 8820 bytes
-rw-r--r--tests/regression/opencsgtest/polygon-tests-expected.pngbin0 -> 9057 bytes
-rw-r--r--tests/regression/opencsgtest/projection-tests-expected.pngbin0 -> 9661 bytes
-rw-r--r--tests/regression/opencsgtest/render-tests-expected.pngbin0 -> 10392 bytes
-rw-r--r--tests/regression/opencsgtest/root-modifier-expected.pngbin0 -> 7440 bytes
-rw-r--r--tests/regression/opencsgtest/rotate_extrude-tests-expected.pngbin0 -> 21093 bytes
-rw-r--r--tests/regression/opencsgtest/sphere-tests-expected.pngbin0 -> 18276 bytes
-rw-r--r--tests/regression/opencsgtest/square-tests-expected.pngbin0 -> 8237 bytes
-rw-r--r--tests/regression/opencsgtest/surface-tests-expected.pngbin0 -> 41120 bytes
-rw-r--r--tests/regression/opencsgtest/transform-tests-expected.pngbin0 -> 16911 bytes
-rw-r--r--tests/regression/opencsgtest/union-tests-expected.pngbin0 -> 10539 bytes
-rwxr-xr-xtests/test_cmdline_tool.py163
228 files changed, 2937 insertions, 0 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..f7fd320
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,246 @@
+cmake_minimum_required(VERSION 2.8)
+project(tests)
+
+set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}")
+
+# Build debug build as default
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE Debug)
+endif()
+
+#
+# Build test apps
+#
+
+# Mac OS X
+if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ FIND_LIBRARY(COCOA_LIBRARY Cocoa)
+endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+
+# Qt4
+find_package(OpenGL)
+find_package(Qt4 COMPONENTS QtCore QtGui QtOpenGL REQUIRED)
+include(${QT_USE_FILE})
+
+# Eigen2
+if (NOT EIGEN2_INCLUDE_DIR)
+ find_path(EIGEN2_INCLUDE_DIR
+ Eigen/Core
+ PATHS ENV EIGEN2DIR /opt/local/include/eigen2 /usr/include/eigen2)
+ 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})
+
+# OpenCSG
+if (NOT $ENV{OPENCSG_DIR} STREQUAL "")
+ set(OPENCSG_DIR "$ENV{OPENCSG_DIR}")
+elseif (NOT $ENV{MACOSX_DEPLOY_DIR} STREQUAL "")
+ set(OPENCSG_DIR "$ENV{MACOSX_DEPLOY_DIR}")
+endif()
+if (NOT OPENCSG_INCLUDE_DIR)
+ message(STATUS ${OPENCSG_DIR})
+ find_path(OPENCSG_INCLUDE_DIR
+ opencsg.h
+ PATHS ${OPENCSG_DIR}/include)
+ find_library(OPENCSG_LIBRARY
+ opencsg
+ PATHS ${OPENCSG_DIR}/lib)
+ if (NOT OPENCSG_INCLUDE_DIR OR NOT OPENCSG_LIBRARY)
+ message(FATAL_ERROR "OpenCSG not found")
+ else()
+ message(STATUS "OpenCSG found in " ${OPENCSG_LIBRARY})
+ endif()
+endif()
+include_directories(${OPENCSG_INCLUDE_DIR})
+
+if (NOT $ENV{MACOSX_DEPLOY_DIR} STREQUAL "")
+ set(GLEW_DIR "$ENV{MACOSX_DEPLOY_DIR}")
+endif()
+find_package(GLEW REQUIRED)
+include_directories(${GLEW_INCLUDE_PATH})
+
+# Flex/Bison
+find_package(BISON)
+find_package(FLEX)
+# The COMPILE_FLAGS and forced C++ compiler is just to be compatible with qmake
+FLEX_TARGET(OpenSCADlexer ../src/lexer.l ${CMAKE_CURRENT_BINARY_DIR}/lexer.cpp COMPILE_FLAGS "-Plexer")
+BISON_TARGET(OpenSCADparser ../src/parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c COMPILE_FLAGS "-p parser")
+ADD_FLEX_BISON_DEPENDENCY(OpenSCADlexer OpenSCADparser)
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/parser_yacc.c PROPERTIES LANGUAGE "CXX")
+
+
+# Internal includes
+include_directories(../src)
+
+add_definitions(-DOPENSCAD_VERSION=test)
+
+set(COMMON_SOURCES
+ ../src/handle_dep.cc
+ ../src/qhash.cc
+ ../src/export.cc
+ ../src/value.cc
+ ../src/expr.cc
+ ../src/func.cc
+ ../src/module.cc
+ ../src/node.cc
+ ../src/context.cc
+ ../src/csgterm.cc
+ ../src/polyset.cc
+ ../src/csgops.cc
+ ../src/transform.cc
+ ../src/color.cc
+ ../src/primitives.cc
+ ../src/projection.cc
+ ../src/cgaladv.cc
+ ../src/surface.cc
+ ../src/control.cc
+ ../src/render.cc
+ ../src/import.cc
+ ../src/dxfdata.cc
+ ../src/dxftess.cc
+ ../src/dxfdim.cc
+ ../src/dxflinextrude.cc
+ ../src/dxfrotextrude.cc
+ ../src/printutils.cc
+ ../src/progress.cc
+ ../src/nodedumper.cc
+ ../src/traverser.cc
+ ../src/PolySetEvaluator.cc
+ ../src/Tree.cc
+ ${FLEX_OpenSCADlexer_OUTPUTS}
+ ${BISON_OpenSCADparser_OUTPUTS})
+
+#
+# dumptest
+#
+add_executable(dumptest dumptest.cc ${COMMON_SOURCES})
+target_link_libraries(dumptest ${QT_LIBRARIES} ${OPENGL_LIBRARY})
+
+#
+# csgtexttest
+#
+add_executable(csgtexttest csgtexttest.cc CSGTextRenderer.cc CSGTextCache.cc ../src/qhash.cc ${COMMON_SOURCES})
+target_link_libraries(csgtexttest ${QT_LIBRARIES} ${OPENGL_LIBRARY})
+
+#
+# csgtermtest
+#
+add_executable(csgtermtest csgtermtest.cc ../src/CSGTermEvaluator.cc ${COMMON_SOURCES})
+target_link_libraries(csgtermtest ${QT_LIBRARIES} ${OPENGL_LIBRARY})
+
+if (NOT $ENV{MACOSX_DEPLOY_DIR} STREQUAL "")
+ set(CGAL_DIR "$ENV{MACOSX_DEPLOY_DIR}/lib/CGAL")
+ set(CMAKE_MODULE_PATH "${CGAL_DIR}")
+endif()
+find_package(CGAL REQUIRED)
+include_directories(${CGAL_INCLUDE_DIRS})
+
+#
+# cgaltest
+#
+add_executable(cgaltest cgaltest.cc ../src/CGAL_Nef_polyhedron.cc ../src/cgalutils.cc ../src/CSGTermEvaluator.cc
+ ../src/CGALEvaluator.cc ../src/PolySetCGALEvaluator.cc ../src/qhash.cc
+ ../src/CGAL_Nef_polyhedron_DxfData.cc ../src/cgaladv_minkowski2.cc ../src/cgaladv_convexhull2.cc
+ ${COMMON_SOURCES})
+set_target_properties(cgaltest PROPERTIES COMPILE_FLAGS "-DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")
+target_link_libraries(cgaltest ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES} ${QT_LIBRARIES} ${OPENGL_LIBRARY})
+
+#
+# cgalpngtest
+#
+add_executable(cgalpngtest cgalpngtest.cc OffscreenView.cc OffscreenContext.mm
+ ../src/CGALRenderer.cc ../src/CGAL_Nef_polyhedron.cc ../src/cgalutils.cc
+ ../src/CSGTermEvaluator.cc ../src/CGALEvaluator.cc
+ ../src/PolySetCGALEvaluator.cc ../src/qhash.cc
+ ../src/CGAL_Nef_polyhedron_DxfData.cc ../src/cgaladv_minkowski2.cc ../src/cgaladv_convexhull2.cc
+ ${COMMON_SOURCES})
+set_target_properties(cgalpngtest PROPERTIES COMPILE_FLAGS "-DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")
+target_link_libraries(cgalpngtest ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES} ${QT_LIBRARIES} ${GLEW_LIBRARY} ${COCOA_LIBRARY} ${OPENGL_LIBRARY})
+
+#
+# opencsgtest
+#
+add_executable(opencsgtest opencsgtest.cc OffscreenView.cc OffscreenContext.mm
+ ../src/OpenCSGRenderer.cc ../src/ThrownTogetherRenderer.cc
+ ../src/CSGTermEvaluator.cc ../src/CGAL_Nef_polyhedron.cc ../src/cgalutils.cc
+ ../src/CGALEvaluator.cc ../src/PolySetCGALEvaluator.cc ../src/qhash.cc
+ ../src/CGAL_Nef_polyhedron_DxfData.cc ../src/cgaladv_minkowski2.cc ../src/cgaladv_convexhull2.cc
+ ${COMMON_SOURCES})
+set_target_properties(opencsgtest PROPERTIES COMPILE_FLAGS "-DENABLE_OPENCSG -DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}")
+target_link_libraries(opencsgtest ${CGAL_LIBRARY} ${CGAL_3RD_PARTY_LIBRARIES} ${QT_LIBRARIES} ${OPENCSG_LIBRARY} ${GLEW_LIBRARY} ${COCOA_LIBRARY} ${OPENGL_LIBRARY})
+
+#
+# This functions adds cmd-line tests given files.
+# Files are sent as the parameters following TESTSUFFIX
+#
+function(add_cmdline_test TESTCMD TESTSUFFIX)
+ get_filename_component(TESTCMD_NAME ${TESTCMD} NAME_WE)
+ foreach (SCADFILE ${ARGN})
+ get_filename_component(TESTNAME ${SCADFILE} NAME_WE)
+ string(REPLACE " " "_" TESTNAME ${TESTNAME}) # Test names cannot include spaces
+ add_test("${TESTCMD_NAME}_${TESTNAME}" ${tests_SOURCE_DIR}/test_cmdline_tool.py -s ${TESTSUFFIX} ${CMAKE_BINARY_DIR}/${TESTCMD} "${SCADFILE}")
+ endforeach()
+endfunction()
+
+enable_testing()
+
+# Find all scad files
+file(GLOB MINIMAL_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/minimal/*.scad)
+file(GLOB FEATURES_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/*.scad)
+file(GLOB BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/*.scad)
+
+# Add dumptest tests to CTest
+add_cmdline_test(dumptest txt ${MINIMAL_FILES})
+# Add csgtexttest tests to CTest
+add_cmdline_test(csgtexttest txt ${MINIMAL_FILES})
+# Add csgtermtest tests to CTest
+add_cmdline_test(csgtermtest txt ${MINIMAL_FILES})
+
+# Add cgaltest tests to CTest
+add_cmdline_test(cgaltest stl ${CGALTEST_FILES})
+
+# Add cgalpngtest tests to CTest
+LIST(APPEND CGALPNGTEST_FILES
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/2d-3d.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/circle-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/square-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/polygon-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/cube-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/sphere-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/cylinder-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/union-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/difference-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/intersection-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/linear_extrude-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/rotate_extrude-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/minkowski2-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/minkowski3-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/hull2-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/surface-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/import_dxf-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/transform-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/color-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/background-modifier.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/highlight-modifier.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/root-modifier.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/disable-modifier.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/for-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/for-nested-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/intersection_for-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/render-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/projection-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/assign-tests.scad
+ ${CMAKE_SOURCE_DIR}/../testdata/scad/features/include-tests.scad)
+#LIST(APPEND CGALPNGTEST_FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad)
+add_cmdline_test(cgalpngtest png ${CGALPNGTEST_FILES})
+
+# Add opencsg tests to CTest
+LIST(APPEND OPENCSGTEST_FILES ${CGALPNGTEST_FILES})
+add_cmdline_test(opencsgtest png ${OPENCSGTEST_FILES})
+
+# Add dxfexport tests to CTest
+#add_cmdline_test(${CMAKE_SOURCE_DIR}/../test-code/exportdxf dxf ${SCAD_FILES})
diff --git a/tests/CSGTextCache.cc b/tests/CSGTextCache.cc
new file mode 100644
index 0000000..4234c63
--- /dev/null
+++ b/tests/CSGTextCache.cc
@@ -0,0 +1,27 @@
+#include "CSGTextCache.h"
+
+bool CSGTextCache::contains(const AbstractNode &node) const
+{
+ return this->cache.contains(this->tree.getString(node));
+}
+
+// We cannot return a reference since the [] operator returns a temporary value
+string CSGTextCache::operator[](const AbstractNode &node) const
+{
+ return this->cache[this->tree.getString(node)];
+}
+
+void CSGTextCache::insert(const class AbstractNode &node, const string & value)
+{
+ this->cache.insert(this->tree.getString(node), value);
+}
+
+void CSGTextCache::remove(const class AbstractNode &node)
+{
+ this->cache.remove(this->tree.getString(node));
+}
+
+void CSGTextCache::clear()
+{
+ this->cache.clear();
+}
diff --git a/tests/CSGTextCache.h b/tests/CSGTextCache.h
new file mode 100644
index 0000000..57a6972
--- /dev/null
+++ b/tests/CSGTextCache.h
@@ -0,0 +1,27 @@
+#ifndef CSGTEXTCACHE_H_
+#define CSGTEXTCACHE_H_
+
+#include "myqhash.h"
+#include "Tree.h"
+#include <string>
+
+using std::string;
+
+class CSGTextCache
+{
+public:
+ CSGTextCache(const Tree &tree) : tree(tree) {}
+ ~CSGTextCache() {}
+
+ bool contains(const AbstractNode &node) const;
+ string operator[](const AbstractNode &node) const;
+ void insert(const class AbstractNode &node, const string & value);
+ void remove(const class AbstractNode &node);
+ void clear();
+
+private:
+ QHash<string, string> cache;
+ const Tree &tree;
+};
+
+#endif
diff --git a/tests/CSGTextRenderer.cc b/tests/CSGTextRenderer.cc
new file mode 100644
index 0000000..b55c88f
--- /dev/null
+++ b/tests/CSGTextRenderer.cc
@@ -0,0 +1,185 @@
+#include "CSGTextRenderer.h"
+
+#include <string>
+#include <map>
+#include <list>
+#include "visitor.h"
+#include "state.h"
+#include "module.h" // FIXME: Temporarily for ModuleInstantiation
+
+#include "csgnode.h"
+#include "transformnode.h"
+
+#include <sstream>
+#include <iostream>
+#include <assert.h>
+#include <QRegExp>
+
+bool CSGTextRenderer::isCached(const AbstractNode &node)
+{
+ return this->cache.contains(node);
+}
+
+/*!
+ Modifies target by applying op to target and src:
+ target = target [op] src
+ */
+void
+CSGTextRenderer::process(string &target, const string &src, CSGTextRenderer::CsgOp op)
+{
+// if (target.dim != 2 && target.dim != 3) {
+// assert(false && "Dimension of Nef polyhedron must be 2 or 3");
+// }
+
+ switch (op) {
+ case UNION:
+ target += "+" + src;
+ break;
+ case INTERSECTION:
+ target += "*" + src;
+ break;
+ case DIFFERENCE:
+ target += "-" + src;
+ break;
+ case MINKOWSKI:
+ target += "M" + src;
+ break;
+ }
+}
+
+void CSGTextRenderer::applyToChildren(const AbstractNode &node, CSGTextRenderer::CsgOp op)
+{
+ std::stringstream stream;
+ stream << node.name() << node.index();
+ string N = stream.str();
+ if (this->visitedchildren[node.index()].size() > 0) {
+ // FIXME: assert that cache contains nodes in code below
+ bool first = true;
+ for (ChildList::const_iterator iter = this->visitedchildren[node.index()].begin();
+ iter != this->visitedchildren[node.index()].end();
+ iter++) {
+ const AbstractNode *chnode = *iter;
+ assert(this->cache.contains(*chnode));
+ // FIXME: Don't use deep access to modinst members
+ if (chnode->modinst->tag_background) continue;
+ if (first) {
+ N += "(" + this->cache[*chnode];
+// if (N.dim != 0) first = false; // FIXME: when can this happen?
+ first = false;
+ } else {
+ process(N, this->cache[*chnode], op);
+ }
+ chnode->progress_report();
+ }
+ N += ")";
+ }
+ this->cache.insert(node, N);
+}
+
+/*
+ Typical visitor behavior:
+ o In prefix: Check if we're cached -> prune
+ o In postfix: Check if we're cached -> don't apply operator to children
+ o In postfix: addToParent()
+ */
+
+Response CSGTextRenderer::visit(State &state, const AbstractNode &node)
+{
+ if (state.isPrefix() && isCached(node)) return PruneTraversal;
+ if (state.isPostfix()) {
+ if (!isCached(node)) applyToChildren(node, UNION);
+ addToParent(state, node);
+ }
+ return ContinueTraversal;
+}
+
+Response CSGTextRenderer::visit(State &state, const AbstractIntersectionNode &node)
+{
+ if (state.isPrefix() && isCached(node)) return PruneTraversal;
+ if (state.isPostfix()) {
+ if (!isCached(node)) applyToChildren(node, INTERSECTION);
+ addToParent(state, node);
+ }
+ return ContinueTraversal;
+}
+
+Response CSGTextRenderer::visit(State &state, const CsgNode &node)
+{
+ if (state.isPrefix() && isCached(node)) return PruneTraversal;
+ if (state.isPostfix()) {
+ if (!isCached(node)) {
+ CsgOp op;
+ switch (node.type) {
+ case CSG_TYPE_UNION:
+ op = UNION;
+ break;
+ case CSG_TYPE_DIFFERENCE:
+ op = DIFFERENCE;
+ break;
+ case CSG_TYPE_INTERSECTION:
+ op = INTERSECTION;
+ break;
+ }
+ applyToChildren(node, op);
+ }
+ addToParent(state, node);
+ }
+ return ContinueTraversal;
+}
+
+Response CSGTextRenderer::visit(State &state, const TransformNode &node)
+{
+ if (state.isPrefix() && isCached(node)) return PruneTraversal;
+ if (state.isPostfix()) {
+ if (!isCached(node)) {
+ // First union all children
+ applyToChildren(node, UNION);
+ // FIXME: Then apply transform
+ }
+ addToParent(state, node);
+ }
+ return ContinueTraversal;
+}
+
+// FIXME: RenderNode: Union over children + some magic
+// FIXME: CgaladvNode: Iterate over children. Special operation
+
+// FIXME: Subtypes of AbstractPolyNode:
+// ProjectionNode
+// DxfLinearExtrudeNode
+// DxfRotateExtrudeNode
+// (SurfaceNode)
+// (PrimitiveNode)
+Response CSGTextRenderer::visit(State &state, const AbstractPolyNode &node)
+{
+ if (state.isPrefix() && isCached(node)) return PruneTraversal;
+ if (state.isPostfix()) {
+ if (!isCached(node)) {
+
+ // FIXME: Manage caching
+ // FIXME: Will generate one single Nef polyhedron (no csg ops necessary)
+
+ string N = node.name();
+ this->cache.insert(node, N);
+
+// std::cout << "Insert: " << N << "\n";
+// std::cout << "Node: " << cacheid.toStdString() << "\n\n";
+ }
+ addToParent(state, node);
+ }
+
+ return ContinueTraversal;
+}
+
+/*!
+ Adds ourself to out parent's list of traversed children.
+ Call this for _every_ node which affects output during the postfix traversal.
+*/
+void CSGTextRenderer::addToParent(const State &state, const AbstractNode &node)
+{
+ assert(state.isPostfix());
+ this->visitedchildren.erase(node.index());
+ if (state.parent()) {
+ this->visitedchildren[state.parent()->index()].push_back(&node);
+ }
+}
diff --git a/tests/CSGTextRenderer.h b/tests/CSGTextRenderer.h
new file mode 100644
index 0000000..79a8a96
--- /dev/null
+++ b/tests/CSGTextRenderer.h
@@ -0,0 +1,40 @@
+#ifndef CSGTEXTRENDERER_H_
+#define CSGTEXTRENDERER_H_
+
+#include "visitor.h"
+#include "CSGTextCache.h"
+
+#include <map>
+#include <list>
+
+using std::string;
+using std::map;
+using std::list;
+
+class CSGTextRenderer : public Visitor
+{
+public:
+ CSGTextRenderer(CSGTextCache &cache) : cache(cache) {}
+ virtual ~CSGTextRenderer() {}
+
+ virtual Response visit(State &state, const AbstractNode &node);
+ virtual Response visit(State &state, const AbstractIntersectionNode &node);
+ virtual Response visit(State &state, const CsgNode &node);
+ virtual Response visit(State &state, const TransformNode &node);
+ virtual Response visit(State &state, const AbstractPolyNode &node);
+
+private:
+ enum CsgOp {UNION, INTERSECTION, DIFFERENCE, MINKOWSKI};
+ void addToParent(const State &state, const AbstractNode &node);
+ bool isCached(const AbstractNode &node);
+ void process(string &target, const string &src, CSGTextRenderer::CsgOp op);
+ void applyToChildren(const AbstractNode &node, CSGTextRenderer::CsgOp op);
+
+ string currindent;
+ typedef list<const AbstractNode *> ChildList;
+ map<int, ChildList> visitedchildren;
+
+ CSGTextCache &cache;
+};
+
+#endif
diff --git a/tests/FindGLEW.cmake b/tests/FindGLEW.cmake
new file mode 100644
index 0000000..e058e8c
--- /dev/null
+++ b/tests/FindGLEW.cmake
@@ -0,0 +1,40 @@
+#
+# Try to find GLEW library and include path.
+# Once done this will define
+#
+# GLEW_FOUND
+# GLEW_INCLUDE_PATH
+# GLEW_LIBRARY
+#
+
+IF (WIN32)
+ FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
+ $ENV{PROGRAMFILES}/GLEW/include
+ ${PROJECT_SOURCE_DIR}/src/nvgl/glew/include
+ DOC "The directory where GL/glew.h resides")
+ FIND_LIBRARY( GLEW_LIBRARY
+ NAMES glew GLEW glew32 glew32s
+ PATHS
+ $ENV{PROGRAMFILES}/GLEW/lib
+ ${PROJECT_SOURCE_DIR}/src/nvgl/glew/bin
+ ${PROJECT_SOURCE_DIR}/src/nvgl/glew/lib
+ DOC "The GLEW library")
+ELSE (WIN32)
+ message("GLEW_DIR: " ${GLEW_DIR})
+ FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h
+ PATHS ${GLEW_DIR}/include /usr/include /usr/local/include
+ NO_DEFAULT_PATH
+ DOC "The directory where GL/glew.h resides")
+ FIND_LIBRARY( GLEW_LIBRARY
+ NAMES GLEW glew
+ PATHS ${GLEW_DIR}/lib /usr/lib /usr/local/lib
+ NO_DEFAULT_PATH
+ DOC "The GLEW library")
+ENDIF (WIN32)
+
+IF (GLEW_INCLUDE_PATH)
+ SET( GLEW_FOUND 1 CACHE STRING "Set to 1 if GLEW is found, 0 otherwise")
+ MESSAGE(STATUS "GLEW found in " ${GLEW_INCLUDE_PATH} " " ${GLEW_LIBRARY})
+ELSE (GLEW_INCLUDE_PATH)
+ SET( GLEW_FOUND 0 CACHE STRING "Set to 1 if GLEW is found, 0 otherwise")
+ENDIF (GLEW_INCLUDE_PATH)
diff --git a/tests/OffscreenContext.h b/tests/OffscreenContext.h
new file mode 100644
index 0000000..0300bcb
--- /dev/null
+++ b/tests/OffscreenContext.h
@@ -0,0 +1,14 @@
+#ifndef OFFSCREENCONTEXT_H_
+#define OFFSCREENCONTEXT_H_
+
+#include <OpenGL/OpenGL.h>
+#include <iostream> // for error output
+
+#define REPORTGLERROR(task) { GLenum tGLErr = glGetError(); if (tGLErr != GL_NO_ERROR) { std::cout << "OpenGL error " << tGLErr << " while " << task << "\n"; } }
+
+struct OffscreenContext *create_offscreen_context(int w, int h);
+void bind_offscreen_context(OffscreenContext *ctx);
+bool teardown_offscreen_context(OffscreenContext *ctx);
+bool save_framebuffer(OffscreenContext *ctx, const char *filename);
+
+#endif
diff --git a/tests/OffscreenContext.mm b/tests/OffscreenContext.mm
new file mode 100644
index 0000000..9a6a5e2
--- /dev/null
+++ b/tests/OffscreenContext.mm
@@ -0,0 +1,207 @@
+#include "OffscreenContext.h"
+
+#import <OpenGL/OpenGL.h>
+#import <OpenGL/glu.h> // for gluCheckExtension
+#import <AppKit/AppKit.h> // for NSOpenGL...
+
+// Simple error reporting macros to help keep the sample code clean
+#define REPORT_ERROR_AND_EXIT(desc) { std::cout << desc << "\n"; return false; }
+#define NULL_ERROR_EXIT(test, desc) { if (!test) REPORT_ERROR_AND_EXIT(desc); }
+
+struct OffscreenContext
+{
+ NSOpenGLContext *openGLContext;
+ NSAutoreleasePool *pool;
+ int width;
+ int height;
+ GLuint fbo;
+};
+
+
+OffscreenContext *create_offscreen_context(int w, int h)
+{
+ OffscreenContext *ctx = new OffscreenContext;
+ ctx->width = w;
+ ctx->height = h;
+
+ ctx->pool = [NSAutoreleasePool new];
+
+ /*
+ * Create an OpenGL context just so that OpenGL calls will work. I'm not
+ using it for actual rendering.
+ */
+
+ NSOpenGLPixelFormatAttribute attributes[] = {
+ NSOpenGLPFAPixelBuffer,
+ NSOpenGLPFANoRecovery,
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFADepthSize, 24,
+ (NSOpenGLPixelFormatAttribute) 0
+ };
+ NSOpenGLPixelFormat* pixFormat = [[[NSOpenGLPixelFormat
+ alloc] initWithAttributes:attributes] autorelease];
+ // Create the OpenGL context to render with (with color and depth buffers)
+ ctx->openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixFormat
+ shareContext:nil];
+ NULL_ERROR_EXIT(ctx->openGLContext, "Unable to create NSOpenGLContext");
+
+ [ctx->openGLContext makeCurrentContext];
+
+ /*
+ * Test if framebuffer objects are supported
+ */
+ const GLubyte* strExt = glGetString(GL_EXTENSIONS);
+ GLboolean fboSupported = gluCheckExtension((const GLubyte*)"GL_EXT_framebuffer_object", strExt);
+ if (!fboSupported)
+ REPORT_ERROR_AND_EXIT("Your system does not support framebuffer extension - unable to render scene");
+ /*
+ * Create an FBO
+ */
+ GLuint renderBuffer = 0;
+ GLuint depthBuffer = 0;
+ // Depth buffer to use for depth testing - optional if you're not using depth testing
+ glGenRenderbuffersEXT(1, &depthBuffer);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, w, h);
+ REPORTGLERROR("creating depth render buffer");
+
+ // Render buffer to use for imaging
+ glGenRenderbuffersEXT(1, &renderBuffer);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderBuffer);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, w, h);
+ REPORTGLERROR("creating color render buffer");
+ ctx->fbo = 0;
+ glGenFramebuffersEXT(1, &ctx->fbo);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->fbo);
+ REPORTGLERROR("binding framebuffer");
+
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT, renderBuffer);
+ REPORTGLERROR("specifying color render buffer");
+
+ if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) !=
+ GL_FRAMEBUFFER_COMPLETE_EXT)
+ REPORT_ERROR_AND_EXIT("Problem with OpenGL framebuffer after specifying color render buffer.");
+
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT, depthBuffer);
+ REPORTGLERROR("specifying depth render buffer");
+
+ if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) !=
+ GL_FRAMEBUFFER_COMPLETE_EXT)
+ REPORT_ERROR_AND_EXIT("Problem with OpenGL framebuffer after specifying depth render buffer.");
+
+ return ctx;
+}
+
+bool teardown_offscreen_context(OffscreenContext *ctx)
+{
+ // "un"bind my FBO
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ /*
+ * Cleanup
+ */
+ [ctx->openGLContext clearDrawable];
+ [ctx->openGLContext release];
+
+ [ctx->pool release];
+ return true;
+}
+
+bool save_framebuffer(OffscreenContext *ctx, const char *filename)
+{
+ /*
+ * Extract the resulting rendering as an image
+ */
+
+ int samplesPerPixel = 4; // R, G, B and A
+ int rowBytes = samplesPerPixel * ctx->width;
+ char* bufferData = (char*)malloc(rowBytes * ctx->height);
+ if (!bufferData) {
+ std::cerr << "Unable to allocate buffer for image extraction.";
+ return 1;
+ }
+ glReadPixels(0, 0, ctx->width, ctx->height, GL_BGRA, GL_UNSIGNED_BYTE,
+ bufferData);
+ REPORTGLERROR("reading pixels from framebuffer");
+
+ // Flip it vertically - images read from OpenGL buffers are upside-down
+ char* flippedBuffer = (char*)malloc(rowBytes * ctx->height);
+ if (!flippedBuffer) {
+ std::cout << "Unable to allocate flipped buffer for corrected image.";
+ return 1;
+ }
+ for (int i = 0 ; i < ctx->height ; i++) {
+ bcopy(bufferData + i * rowBytes, flippedBuffer + (ctx->height - i - 1) *
+ rowBytes, rowBytes);
+ }
+
+ /*
+ * Output the image to a file
+ */
+ CGColorSpaceRef colorSpace =
+ CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ CGBitmapInfo bitmapInfo = kCGImageAlphaNoneSkipFirst |
+ kCGBitmapByteOrder32Little; // XRGB Little Endian
+ int bitsPerComponent = 8;
+ CGContextRef contextRef = CGBitmapContextCreate(flippedBuffer,
+ ctx->width, ctx->height, bitsPerComponent, rowBytes,
+ colorSpace, bitmapInfo);
+ if (!contextRef) {
+ std::cerr << "Unable to create CGContextRef.";
+ return false;
+ }
+
+ CGImageRef imageRef = CGBitmapContextCreateImage(contextRef);
+ if (!imageRef) {
+ std::cerr << "Unable to create CGImageRef.";
+ return false;
+ }
+ Boolean isDirectory = false;
+ CFStringRef fname = CFStringCreateWithCString(kCFAllocatorDefault, filename, kCFStringEncodingUTF8);
+ CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
+ fname, kCFURLPOSIXPathStyle, isDirectory);
+ if (!fileURL) {
+ std::cerr << "Unable to create file URL ref.";
+ return false;
+ }
+ CGDataConsumerRef dataconsumer = CGDataConsumerCreateWithURL(fileURL);
+
+ CFIndex fileImageIndex = 1;
+ CFMutableDictionaryRef fileDict = NULL;
+ CFStringRef fileUTType = kUTTypePNG;
+ // Create an image destination opaque reference for authoring an image file
+ CGImageDestinationRef imageDest = CGImageDestinationCreateWithDataConsumer(dataconsumer,
+ fileUTType,
+ fileImageIndex,
+ fileDict);
+ if (!imageDest) {
+ std::cerr << "Unable to create CGImageDestinationRef.";
+ return false;
+ }
+ CFIndex capacity = 1;
+ CFMutableDictionaryRef imageProps =
+ CFDictionaryCreateMutable(kCFAllocatorDefault,
+ capacity,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CGImageDestinationAddImage(imageDest, imageRef, imageProps);
+ CGImageDestinationFinalize(imageDest);
+
+ free(flippedBuffer);
+ free(bufferData);
+ CFRelease(imageDest);
+ CFRelease(dataconsumer);
+ CFRelease(fileURL);
+ CFRelease(fname);
+ CFRelease(imageProps);
+ CGColorSpaceRelease(colorSpace);
+ CGImageRelease(imageRef);
+ return true;
+}
+
+void bind_offscreen_context(OffscreenContext *ctx)
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->fbo);
+}
diff --git a/tests/OffscreenView.cc b/tests/OffscreenView.cc
new file mode 100644
index 0000000..447a78c
--- /dev/null
+++ b/tests/OffscreenView.cc
@@ -0,0 +1,239 @@
+#include <GL/glew.h>
+#include "OffscreenView.h"
+#include <opencsg.h>
+#include "Renderer.h"
+#include <math.h>
+
+#define FAR_FAR_AWAY 100000.0
+
+OffscreenView::OffscreenView(size_t width, size_t height)
+ : orthomode(false), showaxes(false), showfaces(true), showedges(false),
+ object_rot(35, 0, 25), camera_eye(0, 0, 0), camera_center(0, 0, 0)
+{
+ for (int i = 0; i < 10; i++) this->shaderinfo[i] = 0;
+ this->ctx = create_offscreen_context(width, height);
+ initializeGL();
+ resizeGL(width, height);
+}
+
+OffscreenView::~OffscreenView()
+{
+ teardown_offscreen_context(this->ctx);
+}
+
+void OffscreenView::setRenderer(Renderer* r)
+{
+ this->renderer = r;
+}
+
+void OffscreenView::initializeGL()
+{
+ glEnable(GL_DEPTH_TEST);
+ glDepthRange(-FAR_FAR_AWAY, +FAR_FAR_AWAY);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
+ GLfloat light_position0[] = {-1.0, -1.0, +1.0, 0.0};
+ GLfloat light_position1[] = {+1.0, +1.0, -1.0, 0.0};
+
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+ glEnable(GL_LIGHT0);
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+ glEnable(GL_LIGHT1);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_NORMALIZE);
+
+ glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
+ glEnable(GL_COLOR_MATERIAL);
+
+#ifdef ENABLE_OPENCSG
+ const char *openscad_disable_gl20_env = getenv("OPENSCAD_DISABLE_GL20");
+ if (openscad_disable_gl20_env && !strcmp(openscad_disable_gl20_env, "0"))
+ openscad_disable_gl20_env = NULL;
+ if (glewIsSupported("GL_VERSION_2_0") && openscad_disable_gl20_env == NULL)
+ {
+ const char *vs_source =
+ "uniform float xscale, yscale;\n"
+ "attribute vec3 pos_b, pos_c;\n"
+ "attribute vec3 trig, mask;\n"
+ "varying vec3 tp, tr;\n"
+ "varying float shading;\n"
+ "void main() {\n"
+ " vec4 p0 = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
+ " vec4 p1 = gl_ModelViewProjectionMatrix * vec4(pos_b, 1.0);\n"
+ " vec4 p2 = gl_ModelViewProjectionMatrix * vec4(pos_c, 1.0);\n"
+ " float a = distance(vec2(xscale*p1.x/p1.w, yscale*p1.y/p1.w), vec2(xscale*p2.x/p2.w, yscale*p2.y/p2.w));\n"
+ " float b = distance(vec2(xscale*p0.x/p0.w, yscale*p0.y/p0.w), vec2(xscale*p1.x/p1.w, yscale*p1.y/p1.w));\n"
+ " float c = distance(vec2(xscale*p0.x/p0.w, yscale*p0.y/p0.w), vec2(xscale*p2.x/p2.w, yscale*p2.y/p2.w));\n"
+ " float s = (a + b + c) / 2.0;\n"
+ " float A = sqrt(s*(s-a)*(s-b)*(s-c));\n"
+ " float ha = 2.0*A/a;\n"
+ " gl_Position = p0;\n"
+ " tp = mask * ha;\n"
+ " tr = trig;\n"
+ " vec3 normal, lightDir;\n"
+ " normal = normalize(gl_NormalMatrix * gl_Normal);\n"
+ " lightDir = normalize(vec3(gl_LightSource[0].position));\n"
+ " shading = abs(dot(normal, lightDir));\n"
+ "}\n";
+
+ const char *fs_source =
+ "uniform vec4 color1, color2;\n"
+ "varying vec3 tp, tr, tmp;\n"
+ "varying float shading;\n"
+ "void main() {\n"
+ " gl_FragColor = vec4(color1.r * shading, color1.g * shading, color1.b * shading, color1.a);\n"
+ " if (tp.x < tr.x || tp.y < tr.y || tp.z < tr.z)\n"
+ " gl_FragColor = color2;\n"
+ "}\n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, (const GLchar**)&vs_source, NULL);
+ glCompileShader(vs);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, (const GLchar**)&fs_source, NULL);
+ glCompileShader(fs);
+
+ GLuint edgeshader_prog = glCreateProgram();
+ glAttachShader(edgeshader_prog, vs);
+ glAttachShader(edgeshader_prog, fs);
+ glLinkProgram(edgeshader_prog);
+
+ shaderinfo[0] = edgeshader_prog;
+ shaderinfo[1] = glGetUniformLocation(edgeshader_prog, "color1");
+ shaderinfo[2] = glGetUniformLocation(edgeshader_prog, "color2");
+ shaderinfo[3] = glGetAttribLocation(edgeshader_prog, "trig");
+ shaderinfo[4] = glGetAttribLocation(edgeshader_prog, "pos_b");
+ shaderinfo[5] = glGetAttribLocation(edgeshader_prog, "pos_c");
+ shaderinfo[6] = glGetAttribLocation(edgeshader_prog, "mask");
+ shaderinfo[7] = glGetUniformLocation(edgeshader_prog, "xscale");
+ shaderinfo[8] = glGetUniformLocation(edgeshader_prog, "yscale");
+
+ GLenum err = glGetError();
+ if (err != GL_NO_ERROR) {
+ fprintf(stderr, "OpenGL Error: %s\n", gluErrorString(err));
+ }
+
+ GLint status;
+ glGetProgramiv(edgeshader_prog, GL_LINK_STATUS, &status);
+ if (status == GL_FALSE) {
+ int loglen;
+ char logbuffer[1000];
+ glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer);
+ fprintf(stderr, "OpenGL Program Linker Error:\n%.*s", loglen, logbuffer);
+ } else {
+ int loglen;
+ char logbuffer[1000];
+ glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer);
+ if (loglen > 0) {
+ fprintf(stderr, "OpenGL Program Link OK:\n%.*s", loglen, logbuffer);
+ }
+ glValidateProgram(edgeshader_prog);
+ glGetProgramInfoLog(edgeshader_prog, sizeof(logbuffer), &loglen, logbuffer);
+ if (loglen > 0) {
+ fprintf(stderr, "OpenGL Program Validation results:\n%.*s", loglen, logbuffer);
+ }
+ }
+ }
+#endif /* ENABLE_OPENCSG */
+}
+
+void OffscreenView::resizeGL(int w, int h)
+{
+#ifdef ENABLE_OPENCSG
+ shaderinfo[9] = w;
+ shaderinfo[10] = h;
+#endif
+ glViewport(0, 0, w, h);
+ w_h_ratio = sqrt((double)w / (double)h);
+}
+
+void OffscreenView::setupPerspective()
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ double dist = (this->camera_center - this->camera_eye).norm();
+ gluPerspective(45, w_h_ratio, 0.1*dist, 100*dist);
+}
+
+void OffscreenView::setupOrtho(bool offset)
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ if (offset) glTranslated(-0.8, -0.8, 0);
+ double l = (this->camera_center - this->camera_eye).norm() / 10;
+ glOrtho(-w_h_ratio*l, +w_h_ratio*l,
+ -(1/w_h_ratio)*l, +(1/w_h_ratio)*l,
+ -FAR_FAR_AWAY, +FAR_FAR_AWAY);
+}
+
+void OffscreenView::paintGL()
+{
+ glEnable(GL_LIGHTING);
+
+ if (orthomode) setupOrtho();
+ else setupPerspective();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glClearColor(1.0, 1.0, 0.92, 0.0);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ gluLookAt(this->camera_eye[0], this->camera_eye[1], this->camera_eye[2],
+ this->camera_center[0], this->camera_center[1], this->camera_center[2],
+ 0.0, 0.0, 1.0);
+
+ // glRotated(object_rot[0], 1.0, 0.0, 0.0);
+ // glRotated(object_rot[1], 0.0, 1.0, 0.0);
+ // glRotated(object_rot[2], 0.0, 0.0, 1.0);
+
+ // Large gray axis cross inline with the model
+ // FIXME: This is always gray - adjust color to keep contrast with background
+ if (showaxes)
+ {
+ glLineWidth(1);
+ glColor3d(0.5, 0.5, 0.5);
+ glBegin(GL_LINES);
+ double l = 3*(this->camera_center - this->camera_eye).norm();
+ glVertex3d(-l, 0, 0);
+ glVertex3d(+l, 0, 0);
+ glVertex3d(0, -l, 0);
+ glVertex3d(0, +l, 0);
+ glVertex3d(0, 0, -l);
+ glVertex3d(0, 0, +l);
+ glEnd();
+ }
+
+ glDepthFunc(GL_LESS);
+ glCullFace(GL_BACK);
+ glDisable(GL_CULL_FACE);
+
+ glLineWidth(2);
+ glColor3d(1.0, 0.0, 0.0);
+
+ if (this->renderer) {
+#ifdef ENABLE_OPENCSG
+ OpenCSG::setContext(0);
+#endif
+ this->renderer->draw(showfaces, showedges);
+ }
+}
+
+bool OffscreenView::save(const char *filename)
+{
+ return save_framebuffer(this->ctx, filename);
+}
+
+void OffscreenView::setCamera(const Eigen::Vector3d &pos, const Eigen::Vector3d &center)
+{
+ this->camera_eye = pos;
+ this->camera_center = center;
+}
+
diff --git a/tests/OffscreenView.h b/tests/OffscreenView.h
new file mode 100644
index 0000000..587255a
--- /dev/null
+++ b/tests/OffscreenView.h
@@ -0,0 +1,39 @@
+#ifndef OFFSCREENVIEW_H_
+#define OFFSCREENVIEW_H_
+
+#include "OffscreenContext.h"
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+#include <stdint.h>
+
+class OffscreenView
+{
+public:
+ OffscreenView(size_t width, size_t height);
+ ~OffscreenView();
+ void setRenderer(class Renderer* r);
+
+ void setCamera(const Eigen::Vector3d &pos, const Eigen::Vector3d &center);
+ void initializeGL();
+ void resizeGL(int w, int h);
+ void setupPerspective();
+ void setupOrtho(bool offset=false);
+ void paintGL();
+ bool save(const char *filename);
+
+ GLint shaderinfo[11];
+ OffscreenContext *ctx;
+private:
+ Renderer *renderer;
+ double w_h_ratio;
+ Eigen::Vector3d object_rot;
+ Eigen::Vector3d camera_eye;
+ Eigen::Vector3d camera_center;
+
+ bool orthomode;
+ bool showaxes;
+ bool showfaces;
+ bool showedges;
+};
+
+#endif
diff --git a/tests/cgalpngtest.cc b/tests/cgalpngtest.cc
new file mode 100644
index 0000000..8e3859b
--- /dev/null
+++ b/tests/cgalpngtest.cc
@@ -0,0 +1,234 @@
+/*
+ * OpenSCAD (www.openscad.at)
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * As a special exception, you have permission to link this program
+ * with the CGAL library and distribute executables, as long as you
+ * follow the requirements of the GNU GPL in regard to all of the
+ * software in the executable aside from CGAL.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "myqhash.h"
+#include "openscad.h"
+#include "node.h"
+#include "module.h"
+#include "polyset.h"
+#include "context.h"
+#include "value.h"
+#include "export.h"
+#include "builtin.h"
+#include "Tree.h"
+#include "CGAL_Nef_polyhedron.h"
+#include "CGALEvaluator.h"
+#include "PolySetCGALEvaluator.h"
+#include "CGALRenderer.h"
+#include "CGAL_renderer.h"
+#include "cgal.h"
+#include "OffscreenView.h"
+#include "handle_dep.h"
+
+#include <QApplication>
+#include <QFile>
+#include <QDir>
+#include <QSet>
+#include <QTextStream>
+#include <getopt.h>
+#include <iostream>
+#include <assert.h>
+#include <sstream>
+
+std::string commandline_commands;
+QString currentdir;
+QString examplesdir;
+QString librarydir;
+
+using std::string;
+
+// FIXME: enforce some maximum cache size (old version had 100K vertices as limit)
+QHash<std::string, CGAL_Nef_polyhedron> cache;
+
+void cgalTree(Tree &tree)
+{
+ assert(tree.root());
+
+ CGALEvaluator evaluator(cache, tree);
+ Traverser evaluate(evaluator, *tree.root(), Traverser::PRE_AND_POSTFIX);
+ evaluate.execute();
+}
+
+AbstractNode *find_root_tag(AbstractNode *n)
+{
+ foreach(AbstractNode *v, n->children) {
+ if (v->modinst->tag_root) return v;
+ if (AbstractNode *vroot = find_root_tag(v)) return vroot;
+ }
+ return NULL;
+}
+
+struct CsgInfo
+{
+ OffscreenView *glview;
+};
+
+int main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <file.scad>\n", argv[0]);
+ exit(1);
+ }
+
+ const char *filename = argv[1];
+
+ initialize_builtin_functions();
+ initialize_builtin_modules();
+
+ QApplication app(argc, argv, false);
+ QDir original_path = QDir::current();
+
+ currentdir = QDir::currentPath();
+
+ QDir libdir(QApplication::instance()->applicationDirPath());
+#ifdef Q_WS_MAC
+ libdir.cd("../Resources"); // Libraries can be bundled
+ if (!libdir.exists("libraries")) libdir.cd("../../..");
+#elif defined(Q_OS_UNIX)
+ if (libdir.cd("../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../libraries")) {
+ librarydir = libdir.path();
+ } else
+#endif
+ if (libdir.cd("libraries")) {
+ librarydir = libdir.path();
+ }
+
+ Context root_ctx;
+ root_ctx.functions_p = &builtin_functions;
+ root_ctx.modules_p = &builtin_modules;
+ root_ctx.set_variable("$fn", Value(0.0));
+ root_ctx.set_variable("$fs", Value(1.0));
+ root_ctx.set_variable("$fa", Value(12.0));
+ root_ctx.set_variable("$t", Value(0.0));
+
+ Value zero3;
+ zero3.type = Value::VECTOR;
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ root_ctx.set_variable("$vpt", zero3);
+ root_ctx.set_variable("$vpr", zero3);
+
+
+ AbstractModule *root_module;
+ ModuleInstantiation root_inst;
+
+ QFileInfo fileInfo(filename);
+ handle_dep(filename);
+ FILE *fp = fopen(filename, "rt");
+ if (!fp) {
+ fprintf(stderr, "Can't open input file `%s'!\n", filename);
+ exit(1);
+ } else {
+ std::stringstream text;
+ char buffer[513];
+ int ret;
+ while ((ret = fread(buffer, 1, 512, fp)) > 0) {
+ buffer[ret] = 0;
+ text << buffer;
+ }
+ fclose(fp);
+ text << commandline_commands;
+ root_module = parse(text.str().c_str(), fileInfo.absolutePath().toLocal8Bit(), false);
+ if (!root_module) {
+ exit(1);
+ }
+ }
+
+ QDir::setCurrent(fileInfo.absolutePath());
+
+ AbstractNode::resetIndexCounter();
+ AbstractNode *absolute_root_node = root_module->evaluate(&root_ctx, &root_inst);
+ AbstractNode *root_node;
+ // Do we have an explicit root node (! modifier)?
+ if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node;
+
+ Tree tree(root_node);
+
+ CsgInfo csgInfo;
+ QHash<std::string, CGAL_Nef_polyhedron> cache;
+ CGALEvaluator cgalevaluator(cache, tree);
+ PolySetCGALEvaluator psevaluator(cgalevaluator);
+
+ CGAL_Nef_polyhedron N = cgalevaluator.evaluateCGALMesh(*root_node);
+
+ QDir::setCurrent(original_path.absolutePath());
+
+ csgInfo.glview = new OffscreenView(512,512);
+
+ glewInit();
+#ifdef DEBUG
+ cout << "GLEW version " << glewGetString(GLEW_VERSION) << "\n";
+ cout << (const char *)glGetString(GL_RENDERER) << "(" << (const char *)glGetString(GL_VENDOR) << ")\n"
+ << "OpenGL version " << (const char *)glGetString(GL_VERSION) << "\n";
+ cout << "Extensions: " << (const char *)glGetString(GL_EXTENSIONS) << "\n";
+
+
+ if (GLEW_ARB_framebuffer_object) {
+ cout << "ARB_FBO supported\n";
+ }
+ if (GLEW_EXT_framebuffer_object) {
+ cout << "EXT_FBO supported\n";
+ }
+ if (GLEW_EXT_packed_depth_stencil) {
+ cout << "EXT_packed_depth_stencil\n";
+ }
+#endif
+
+ CGALRenderer cgalRenderer(N);
+
+ BoundingBox bbox;
+ if (cgalRenderer.polyhedron) {
+ CGAL::Bbox_3 cgalbbox = cgalRenderer.polyhedron->bbox();
+ bbox = BoundingBox(Vector3d(cgalbbox.xmin(), cgalbbox.ymin(), cgalbbox.zmin()),
+ Vector3d(cgalbbox.xmax(), cgalbbox.ymax(), cgalbbox.zmax()));
+ }
+ else if (cgalRenderer.polyset) {
+ bbox = cgalRenderer.polyset->getBoundingBox();
+ }
+ Vector3d center = (bbox.min() + bbox.max()) / 2;
+ double radius = (bbox.max() - bbox.min()).norm() / 2;
+
+
+ Vector3d cameradir(1, 1, -0.5);
+ Vector3d camerapos = center - radius*2*cameradir;
+ csgInfo.glview->setCamera(camerapos, center);
+
+
+ csgInfo.glview->setRenderer(&cgalRenderer);
+ csgInfo.glview->paintGL();
+ csgInfo.glview->save("/dev/stdout");
+
+ destroy_builtin_functions();
+ destroy_builtin_modules();
+
+ return 0;
+}
diff --git a/tests/cgaltest.cc b/tests/cgaltest.cc
new file mode 100644
index 0000000..029fcfc
--- /dev/null
+++ b/tests/cgaltest.cc
@@ -0,0 +1,180 @@
+/*
+ * OpenSCAD (www.openscad.at)
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * As a special exception, you have permission to link this program
+ * with the CGAL library and distribute executables, as long as you
+ * follow the requirements of the GNU GPL in regard to all of the
+ * software in the executable aside from CGAL.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "myqhash.h"
+#include "openscad.h"
+#include "handle_dep.h"
+#include "node.h"
+#include "module.h"
+#include "context.h"
+#include "value.h"
+#include "export.h"
+#include "builtin.h"
+#include "Tree.h"
+#include "CGAL_Nef_polyhedron.h"
+#include "CGALEvaluator.h"
+#include "PolySetCGALEvaluator.h"
+
+#include <QApplication>
+#include <QFile>
+#include <QDir>
+#include <QSet>
+#include <QTextStream>
+#include <getopt.h>
+#include <iostream>
+#include <assert.h>
+#include <sstream>
+
+std::string commandline_commands;
+QString currentdir;
+QString examplesdir;
+QString librarydir;
+
+using std::string;
+
+// FIXME: enforce some maximum cache size (old version had 100K vertices as limit)
+QHash<std::string, CGAL_Nef_polyhedron> cache;
+
+void cgalTree(Tree &tree)
+{
+ assert(tree.root());
+
+ CGALEvaluator evaluator(cache, tree);
+ Traverser evaluate(evaluator, *tree.root(), Traverser::PRE_AND_POSTFIX);
+ evaluate.execute();
+}
+
+AbstractNode *find_root_tag(AbstractNode *n)
+{
+ foreach(AbstractNode *v, n->children) {
+ if (v->modinst->tag_root) return v;
+ if (AbstractNode *vroot = find_root_tag(v)) return vroot;
+ }
+ return NULL;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <file.scad>\n", argv[0]);
+ exit(1);
+ }
+
+ const char *filename = argv[1];
+
+ initialize_builtin_functions();
+ initialize_builtin_modules();
+
+ QApplication app(argc, argv, false);
+ QDir original_path = QDir::current();
+
+ currentdir = QDir::currentPath();
+
+ QDir libdir(QApplication::instance()->applicationDirPath());
+#ifdef Q_WS_MAC
+ libdir.cd("../Resources"); // Libraries can be bundled
+ if (!libdir.exists("libraries")) libdir.cd("../../..");
+#elif defined(Q_OS_UNIX)
+ if (libdir.cd("../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../libraries")) {
+ librarydir = libdir.path();
+ } else
+#endif
+ if (libdir.cd("libraries")) {
+ librarydir = libdir.path();
+ }
+
+ Context root_ctx;
+ root_ctx.functions_p = &builtin_functions;
+ root_ctx.modules_p = &builtin_modules;
+ root_ctx.set_variable("$fn", Value(0.0));
+ root_ctx.set_variable("$fs", Value(1.0));
+ root_ctx.set_variable("$fa", Value(12.0));
+ root_ctx.set_variable("$t", Value(0.0));
+
+ Value zero3;
+ zero3.type = Value::VECTOR;
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ root_ctx.set_variable("$vpt", zero3);
+ root_ctx.set_variable("$vpr", zero3);
+
+
+ AbstractModule *root_module;
+ ModuleInstantiation root_inst;
+
+ QFileInfo fileInfo(filename);
+ handle_dep(filename);
+ FILE *fp = fopen(filename, "rt");
+ if (!fp) {
+ fprintf(stderr, "Can't open input file `%s'!\n", filename);
+ exit(1);
+ } else {
+ std::stringstream text;
+ char buffer[513];
+ int ret;
+ while ((ret = fread(buffer, 1, 512, fp)) > 0) {
+ buffer[ret] = 0;
+ text << buffer;
+ }
+ fclose(fp);
+ text << commandline_commands;
+ root_module = parse(text.str().c_str(), fileInfo.absolutePath().toLocal8Bit(), false);
+ if (!root_module) {
+ exit(1);
+ }
+ }
+
+ QDir::setCurrent(fileInfo.absolutePath());
+
+ AbstractNode::resetIndexCounter();
+ AbstractNode *absolute_root_node = root_module->evaluate(&root_ctx, &root_inst);
+ AbstractNode *root_node;
+ // Do we have an explicit root node (! modifier)?
+ if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node;
+
+ Tree tree(root_node);
+
+ QHash<std::string, CGAL_Nef_polyhedron> cache;
+ CGALEvaluator cgalevaluator(cache, tree);
+ PolySetCGALEvaluator psevaluator(cgalevaluator);
+
+ CGAL_Nef_polyhedron N = cgalevaluator.evaluateCGALMesh(*root_node);
+
+ QDir::setCurrent(original_path.absolutePath());
+ if (!N.empty()) {
+ export_stl(&N, std::cout, NULL);
+ }
+ destroy_builtin_functions();
+ destroy_builtin_modules();
+
+ return 0;
+}
diff --git a/tests/compare-bitmaps.sh b/tests/compare-bitmaps.sh
new file mode 100755
index 0000000..590d0b5
--- /dev/null
+++ b/tests/compare-bitmaps.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+
+while getopts 'v' c
+do
+ case $c in
+ v) set -x ;;
+ esac
+done
+
+shift $(($OPTIND - 1))
+
+# FIXME: Sometimes, compare fails when comparing very small images (e.g. 40 x 10 pixels).
+# It's unknown why this happens..
+pixelerror=`compare -fuzz 10% -metric AE $1 $2 null: 2>&1`
+if [ $? -ne 0 ]; then
+ echo "General error: Ouch"
+ exit 1 # Compare failed to read image
+else
+ # Check if $pixelerror contains an integer (it sometimes outputs things like '0 @ 0,0')
+ if [ $pixelerror -eq $pixelerror 2> /dev/null ]; then
+ if [ $pixelerror == 0 ]; then
+ exit 0
+ fi
+ echo "Pixel error: $pixelerror"
+ else
+ echo "Pixel error: Err"
+ fi
+ exit 1
+fi
+exit 0
diff --git a/tests/csgtermtest.cc b/tests/csgtermtest.cc
new file mode 100644
index 0000000..26b809a
--- /dev/null
+++ b/tests/csgtermtest.cc
@@ -0,0 +1,172 @@
+/*
+ * OpenSCAD (www.openscad.at)
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * As a special exception, you have permission to link this program
+ * with the CGAL library and distribute executables, as long as you
+ * follow the requirements of the GNU GPL in regard to all of the
+ * software in the executable aside from CGAL.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "myqhash.h"
+#include "CSGTermEvaluator.h"
+#include "CSGTextCache.h"
+#include "openscad.h"
+#include "handle_dep.h"
+#include "node.h"
+#include "module.h"
+#include "context.h"
+#include "value.h"
+#include "export.h"
+#include "builtin.h"
+#include "Tree.h"
+#include "csgterm.h"
+
+#include <QApplication>
+#include <QFile>
+#include <QDir>
+#include <QSet>
+#include <getopt.h>
+#include <assert.h>
+#include <iostream>
+#include <sstream>
+
+using std::cout;
+
+std::string commandline_commands;
+QString currentdir;
+QString examplesdir;
+QString librarydir;
+
+int main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <file.scad>\n", argv[0]);
+ exit(1);
+ }
+
+ const char *filename = argv[1];
+
+ int rc = 0;
+
+ initialize_builtin_functions();
+ initialize_builtin_modules();
+
+ QApplication app(argc, argv, false);
+ QDir original_path = QDir::current();
+
+ currentdir = QDir::currentPath();
+
+ QDir libdir(QApplication::instance()->applicationDirPath());
+#ifdef Q_WS_MAC
+ libdir.cd("../Resources"); // Libraries can be bundled
+ if (!libdir.exists("libraries")) libdir.cd("../../..");
+#elif defined(Q_OS_UNIX)
+ if (libdir.cd("../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../libraries")) {
+ librarydir = libdir.path();
+ } else
+#endif
+ if (libdir.cd("libraries")) {
+ librarydir = libdir.path();
+ }
+
+ Context root_ctx;
+ root_ctx.functions_p = &builtin_functions;
+ root_ctx.modules_p = &builtin_modules;
+ root_ctx.set_variable("$fn", Value(0.0));
+ root_ctx.set_variable("$fs", Value(1.0));
+ root_ctx.set_variable("$fa", Value(12.0));
+ root_ctx.set_variable("$t", Value(0.0));
+
+ Value zero3;
+ zero3.type = Value::VECTOR;
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ root_ctx.set_variable("$vpt", zero3);
+ root_ctx.set_variable("$vpr", zero3);
+
+
+ AbstractModule *root_module;
+ ModuleInstantiation root_inst;
+ AbstractNode *root_node;
+
+ QFileInfo fileInfo(filename);
+ handle_dep(filename);
+ FILE *fp = fopen(filename, "rt");
+ if (!fp) {
+ fprintf(stderr, "Can't open input file `%s'!\n", filename);
+ exit(1);
+ } else {
+ std::stringstream text;
+ char buffer[513];
+ int ret;
+ while ((ret = fread(buffer, 1, 512, fp)) > 0) {
+ buffer[ret] = 0;
+ text << buffer;
+ }
+ fclose(fp);
+ text << commandline_commands;
+ root_module = parse(text.str().c_str(), fileInfo.absolutePath().toLocal8Bit(), false);
+ if (!root_module) {
+ exit(1);
+ }
+ }
+
+ QDir::setCurrent(fileInfo.absolutePath());
+
+ AbstractNode::resetIndexCounter();
+ root_node = root_module->evaluate(&root_ctx, &root_inst);
+
+ Tree tree(root_node);
+
+// cout << tree.getString(*root_node) << "\n";
+
+ vector<CSGTerm*> highlights;
+ vector<CSGTerm*> background;
+ CSGTermEvaluator evaluator(tree);
+ CSGTerm *root_term = evaluator.evaluateCSGTerm(*root_node, highlights, background);
+
+ // cout << "Stored terms: " << evaluator.stored_term.size() << "\n";
+ // for (map<int, class CSGTerm*>::iterator iter = evaluator.stored_term.begin();
+ // iter != evaluator.stored_term.end();
+ // iter++) {
+ // cout << iter->first << ":" << (iter->second ? iter->second->label : "NULL") << "\n";
+ // }
+
+ // if (evaluator.background) cout << "Background terms: " << evaluator.background->size() << "\n";
+ // if (evaluator.highlights) cout << "Highlights terms: " << evaluator.highlights->size() << "\n";
+
+ if (root_term) {
+ cout << root_term->dump() << "\n";
+ }
+ else {
+ cout << "No top-level CSG object\n";
+ }
+
+ destroy_builtin_functions();
+ destroy_builtin_modules();
+
+ return rc;
+}
diff --git a/tests/csgtexttest.cc b/tests/csgtexttest.cc
new file mode 100644
index 0000000..3c4451d
--- /dev/null
+++ b/tests/csgtexttest.cc
@@ -0,0 +1,158 @@
+/*
+ * OpenSCAD (www.openscad.at)
+ * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * As a special exception, you have permission to link this program
+ * with the CGAL library and distribute executables, as long as you
+ * follow the requirements of the GNU GPL in regard to all of the
+ * software in the executable aside from CGAL.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "CSGTextRenderer.h"
+#include "CSGTextCache.h"
+#include "openscad.h"
+#include "handle_dep.h"
+#include "node.h"
+#include "module.h"
+#include "context.h"
+#include "value.h"
+#include "export.h"
+#include "builtin.h"
+#include "Tree.h"
+
+#include <QApplication>
+#include <QFile>
+#include <QDir>
+#include <QSet>
+#include <getopt.h>
+#include <assert.h>
+#include <iostream>
+#include <sstream>
+
+std::string commandline_commands;
+QString currentdir;
+QString examplesdir;
+QString librarydir;
+
+void csgTree(CSGTextCache &cache, const AbstractNode &root)
+{
+ CSGTextRenderer renderer(cache);
+ Traverser render(renderer, root, Traverser::PRE_AND_POSTFIX);
+ render.execute();
+}
+
+int main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <file.scad>\n", argv[0]);
+ exit(1);
+ }
+
+ const char *filename = argv[1];
+
+ int rc = 0;
+
+ initialize_builtin_functions();
+ initialize_builtin_modules();
+
+ QApplication app(argc, argv, false);
+ QDir original_path = QDir::current();
+
+ currentdir = QDir::currentPath();
+
+ QDir libdir(QApplication::instance()->applicationDirPath());
+#ifdef Q_WS_MAC
+ libdir.cd("../Resources"); // Libraries can be bundled
+ if (!libdir.exists("libraries")) libdir.cd("../../..");
+#elif defined(Q_OS_UNIX)
+ if (libdir.cd("../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../libraries")) {
+ librarydir = libdir.path();
+ } else
+#endif
+ if (libdir.cd("libraries")) {
+ librarydir = libdir.path();
+ }
+
+ Context root_ctx;
+ root_ctx.functions_p = &builtin_functions;
+ root_ctx.modules_p = &builtin_modules;
+ root_ctx.set_variable("$fn", Value(0.0));
+ root_ctx.set_variable("$fs", Value(1.0));
+ root_ctx.set_variable("$fa", Value(12.0));
+ root_ctx.set_variable("$t", Value(0.0));
+
+ Value zero3;
+ zero3.type = Value::VECTOR;
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ root_ctx.set_variable("$vpt", zero3);
+ root_ctx.set_variable("$vpr", zero3);
+
+
+ AbstractModule *root_module;
+ ModuleInstantiation root_inst;
+ AbstractNode *root_node;
+
+ QFileInfo fileInfo(filename);
+ handle_dep(filename);
+ FILE *fp = fopen(filename, "rt");
+ if (!fp) {
+ fprintf(stderr, "Can't open input file `%s'!\n", filename);
+ exit(1);
+ } else {
+ std::stringstream text;
+ char buffer[513];
+ int ret;
+ while ((ret = fread(buffer, 1, 512, fp)) > 0) {
+ buffer[ret] = 0;
+ text << buffer;
+ }
+ fclose(fp);
+ text << commandline_commands;
+ root_module = parse(text.str().c_str(), fileInfo.absolutePath().toLocal8Bit(), false);
+ if (!root_module) {
+ exit(1);
+ }
+ }
+
+ QDir::setCurrent(fileInfo.absolutePath());
+
+ AbstractNode::resetIndexCounter();
+ root_node = root_module->evaluate(&root_ctx, &root_inst);
+
+ Tree tree;
+ tree.setRoot(root_node);
+ CSGTextCache csgcache(tree);
+
+ csgTree(csgcache, *root_node);
+// std::cout << tree.getString(*root_node) << "\n";
+
+ std::cout << csgcache[*root_node] << "\n";
+
+ destroy_builtin_functions();
+ destroy_builtin_modules();
+
+ return rc;
+}
diff --git a/tests/dumptest.cc b/tests/dumptest.cc
new file mode 100644
index 0000000..9af7154
--- /dev/null
+++ b/tests/dumptest.cc
@@ -0,0 +1,155 @@
+/*
+ * OpenSCAD (www.openscad.org)
+ * Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
+ * Marius Kintel <marius@kintel.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * As a special exception, you have permission to link this program
+ * with the CGAL library and distribute executables, as long as you
+ * follow the requirements of the GNU GPL in regard to all of the
+ * software in the executable aside from CGAL.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "openscad.h"
+#include "handle_dep.h"
+#include "node.h"
+#include "module.h"
+#include "context.h"
+#include "value.h"
+#include "export.h"
+#include "builtin.h"
+#include "nodedumper.h"
+#include "Tree.h"
+
+#include <QApplication>
+#include <QFile>
+#include <QDir>
+#include <QSet>
+#include <getopt.h>
+#include <assert.h>
+#include <iostream>
+#include <sstream>
+
+using std::string;
+
+std::string commandline_commands;
+QString currentdir;
+QString examplesdir;
+QString librarydir;
+
+int main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <file.scad>\n", argv[0]);
+ exit(1);
+ }
+
+ const char *filename = argv[1];
+
+ int rc = 0;
+
+ initialize_builtin_functions();
+ initialize_builtin_modules();
+
+ QApplication app(argc, argv, false);
+ QDir original_path = QDir::current();
+
+ currentdir = QDir::currentPath();
+
+ QDir libdir(QApplication::instance()->applicationDirPath());
+#ifdef Q_WS_MAC
+ libdir.cd("../Resources"); // Libraries can be bundled
+ if (!libdir.exists("libraries")) libdir.cd("../../..");
+#elif defined(Q_OS_UNIX)
+ if (libdir.cd("../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../libraries")) {
+ librarydir = libdir.path();
+ } else
+#endif
+ if (libdir.cd("libraries")) {
+ librarydir = libdir.path();
+ }
+
+ Context root_ctx;
+ root_ctx.functions_p = &builtin_functions;
+ root_ctx.modules_p = &builtin_modules;
+ root_ctx.set_variable("$fn", Value(0.0));
+ root_ctx.set_variable("$fs", Value(1.0));
+ root_ctx.set_variable("$fa", Value(12.0));
+ root_ctx.set_variable("$t", Value(0.0));
+
+ Value zero3;
+ zero3.type = Value::VECTOR;
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ root_ctx.set_variable("$vpt", zero3);
+ root_ctx.set_variable("$vpr", zero3);
+
+
+ AbstractModule *root_module;
+ ModuleInstantiation root_inst;
+ AbstractNode *root_node;
+
+ QFileInfo fileInfo(filename);
+ handle_dep(filename);
+ FILE *fp = fopen(filename, "rt");
+ if (!fp) {
+ fprintf(stderr, "Can't open input file `%s'!\n", filename);
+ exit(1);
+ } else {
+ std::stringstream text;
+ char buffer[513];
+ int ret;
+ while ((ret = fread(buffer, 1, 512, fp)) > 0) {
+ buffer[ret] = 0;
+ text << buffer;
+ }
+ fclose(fp);
+ text << commandline_commands;
+ root_module = parse(text.str().c_str(), fileInfo.absolutePath().toLocal8Bit(), false);
+ if (!root_module) {
+ exit(1);
+ }
+ }
+
+ QDir::setCurrent(fileInfo.absolutePath());
+
+ AbstractNode::resetIndexCounter();
+ root_node = root_module->evaluate(&root_ctx, &root_inst);
+
+ // Cache test
+ QString teststr("test");
+ Tree tree;
+ tree.setRoot(root_node);
+
+ string dumpstdstr = tree.getString(*root_node);
+ string dumpstdstr_cached = tree.getString(*root_node);
+ if (dumpstdstr != dumpstdstr_cached) rc = 1;
+
+ std::cout << dumpstdstr << "\n";
+
+ destroy_builtin_functions();
+ destroy_builtin_modules();
+
+ return rc;
+}
diff --git a/tests/opencsgtest.cc b/tests/opencsgtest.cc
new file mode 100644
index 0000000..72f7488
--- /dev/null
+++ b/tests/opencsgtest.cc
@@ -0,0 +1,251 @@
+#include <GL/glew.h>
+#include "openscad.h"
+#include "handle_dep.h"
+#include "builtin.h"
+#include "context.h"
+#include "node.h"
+#include "module.h"
+#include "polyset.h"
+#include "Tree.h"
+#include "CSGTermEvaluator.h"
+#include "CGALEvaluator.h"
+#include "PolySetCGALEvaluator.h"
+
+#include "OpenCSGRenderer.h"
+#include "ThrownTogetherRenderer.h"
+
+#include "csgterm.h"
+#include "OffscreenView.h"
+
+#include <QApplication>
+#include <QFile>
+#include <QDir>
+#include <QSet>
+#include <QTimer>
+#include <sstream>
+
+using std::cerr;
+using std::cout;
+
+std::string commandline_commands;
+QString librarydir;
+
+//#define DEBUG
+
+struct CsgInfo
+{
+ CSGTerm *root_norm_term; // Normalized CSG products
+ class CSGChain *root_chain;
+ std::vector<CSGTerm*> highlight_terms;
+ CSGChain *highlights_chain;
+ std::vector<CSGTerm*> background_terms;
+ CSGChain *background_chain;
+ OffscreenView *glview;
+};
+
+AbstractNode *find_root_tag(AbstractNode *n)
+{
+ foreach(AbstractNode *v, n->children) {
+ if (v->modinst->tag_root) return v;
+ if (AbstractNode *vroot = find_root_tag(v)) return vroot;
+ }
+ return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <file.scad>\n", argv[0]);
+ exit(1);
+ }
+
+ const char *filename = argv[1];
+
+ initialize_builtin_functions();
+ initialize_builtin_modules();
+
+ QApplication app(argc, argv);
+
+ QDir original_path = QDir::current();
+
+ QString currentdir = QDir::currentPath();
+
+ QDir libdir(QApplication::instance()->applicationDirPath());
+#ifdef Q_WS_MAC
+ libdir.cd("../Resources"); // Libraries can be bundled
+ if (!libdir.exists("libraries")) libdir.cd("../../..");
+#elif defined(Q_OS_UNIX)
+ if (libdir.cd("../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../share/openscad/libraries")) {
+ librarydir = libdir.path();
+ } else
+ if (libdir.cd("../../libraries")) {
+ librarydir = libdir.path();
+ } else
+#endif
+ if (libdir.cd("libraries")) {
+ librarydir = libdir.path();
+ }
+
+ Context root_ctx;
+ root_ctx.functions_p = &builtin_functions;
+ root_ctx.modules_p = &builtin_modules;
+ root_ctx.set_variable("$fn", Value(0.0));
+ root_ctx.set_variable("$fs", Value(1.0));
+ root_ctx.set_variable("$fa", Value(12.0));
+ root_ctx.set_variable("$t", Value(0.0));
+
+ Value zero3;
+ zero3.type = Value::VECTOR;
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ zero3.append(new Value(0.0));
+ root_ctx.set_variable("$vpt", zero3);
+ root_ctx.set_variable("$vpr", zero3);
+
+
+ AbstractModule *root_module;
+ ModuleInstantiation root_inst;
+
+ QFileInfo fileInfo(filename);
+ handle_dep(filename);
+ FILE *fp = fopen(filename, "rt");
+ if (!fp) {
+ fprintf(stderr, "Can't open input file `%s'!\n", filename);
+ exit(1);
+ } else {
+ std::stringstream text;
+ char buffer[513];
+ int ret;
+ while ((ret = fread(buffer, 1, 512, fp)) > 0) {
+ buffer[ret] = 0;
+ text << buffer;
+ }
+ fclose(fp);
+ text << commandline_commands;
+ root_module = parse(text.str().c_str(), fileInfo.absolutePath().toLocal8Bit(), false);
+ if (!root_module) {
+ exit(1);
+ }
+ }
+
+ QDir::setCurrent(fileInfo.absolutePath());
+
+ AbstractNode::resetIndexCounter();
+ AbstractNode *absolute_root_node = root_module->evaluate(&root_ctx, &root_inst);
+ AbstractNode *root_node;
+ // Do we have an explicit root node (! modifier)?
+ if (!(root_node = find_root_tag(absolute_root_node))) root_node = absolute_root_node;
+
+ Tree tree(root_node);
+
+ CsgInfo csgInfo;
+ QHash<std::string, CGAL_Nef_polyhedron> cache;
+ CGALEvaluator cgalevaluator(cache, tree);
+ PolySetCGALEvaluator psevaluator(cgalevaluator);
+ CSGTermEvaluator evaluator(tree, &psevaluator);
+ CSGTerm *root_raw_term = evaluator.evaluateCSGTerm(*root_node,
+ csgInfo.highlight_terms,
+ csgInfo.background_terms);
+
+ if (!root_raw_term) {
+ cerr << "Error: CSG generation failed! (no top level object found)\n";
+ return 1;
+ }
+
+ // CSG normalization
+ csgInfo.root_norm_term = root_raw_term->link();
+ while (1) {
+ CSGTerm *n = csgInfo.root_norm_term->normalize();
+ csgInfo.root_norm_term->unlink();
+ if (csgInfo.root_norm_term == n)
+ break;
+ csgInfo.root_norm_term = n;
+ }
+
+ assert(csgInfo.root_norm_term);
+
+ csgInfo.root_chain = new CSGChain();
+ csgInfo.root_chain->import(csgInfo.root_norm_term);
+ fprintf(stderr, "Normalized CSG tree has %d elements\n", csgInfo.root_chain->polysets.size());
+
+ if (csgInfo.highlight_terms.size() > 0) {
+ cerr << "Compiling highlights (" << csgInfo.highlight_terms.size() << " CSG Trees)...\n";
+
+ csgInfo.highlights_chain = new CSGChain();
+ for (unsigned int i = 0; i < csgInfo.highlight_terms.size(); i++) {
+ while (1) {
+ CSGTerm *n = csgInfo.highlight_terms[i]->normalize();
+ csgInfo.highlight_terms[i]->unlink();
+ if (csgInfo.highlight_terms[i] == n)
+ break;
+ csgInfo.highlight_terms[i] = n;
+ }
+ csgInfo.highlights_chain->import(csgInfo.highlight_terms[i]);
+ }
+ }
+
+ if (csgInfo.background_terms.size() > 0) {
+ cerr << "Compiling background (" << csgInfo.background_terms.size() << " CSG Trees)...\n";
+
+ csgInfo.background_chain = new CSGChain();
+ for (unsigned int i = 0; i < csgInfo.background_terms.size(); i++) {
+ while (1) {
+ CSGTerm *n = csgInfo.background_terms[i]->normalize();
+ csgInfo.background_terms[i]->unlink();
+ if (csgInfo.background_terms[i] == n)
+ break;
+ csgInfo.background_terms[i] = n;
+ }
+ csgInfo.background_chain->import(csgInfo.background_terms[i]);
+ }
+ }
+
+ QDir::setCurrent(original_path.absolutePath());
+
+ csgInfo.glview = new OffscreenView(512,512);
+ BoundingBox bbox = csgInfo.root_chain->getBoundingBox();
+
+ Vector3d center = (bbox.min() + bbox.max()) / 2;
+ double radius = (bbox.max() - bbox.min()).norm() / 2;
+
+
+ Vector3d cameradir(1, 1, -0.5);
+ Vector3d camerapos = center - radius*1.8*cameradir;
+ csgInfo.glview->setCamera(camerapos, center);
+
+ glewInit();
+#ifdef DEBUG
+ cout << "GLEW version " << glewGetString(GLEW_VERSION) << "\n";
+ cout << (const char *)glGetString(GL_RENDERER) << "(" << (const char *)glGetString(GL_VENDOR) << ")\n"
+ << "OpenGL version " << (const char *)glGetString(GL_VERSION) << "\n";
+ cout << "Extensions: " << (const char *)glGetString(GL_EXTENSIONS) << "\n";
+
+
+ if (GLEW_ARB_framebuffer_object) {
+ cout << "ARB_FBO supported\n";
+ }
+ if (GLEW_EXT_framebuffer_object) {
+ cout << "EXT_FBO supported\n";
+ }
+ if (GLEW_EXT_packed_depth_stencil) {
+ cout << "EXT_packed_depth_stencil\n";
+ }
+#endif
+
+ OpenCSGRenderer opencsgRenderer(csgInfo.root_chain, csgInfo.highlights_chain, csgInfo.background_chain, csgInfo.glview->shaderinfo);
+ ThrownTogetherRenderer thrownTogetherRenderer(csgInfo.root_chain, csgInfo.highlights_chain, csgInfo.background_chain);
+// csgInfo.glview->setRenderer(&thrownTogetherRenderer);
+ csgInfo.glview->setRenderer(&opencsgRenderer);
+
+ csgInfo.glview->paintGL();
+
+ csgInfo.glview->save("/dev/stdout");
+
+ destroy_builtin_functions();
+ destroy_builtin_modules();
+
+ return 0;
+}
diff --git a/tests/regression/cgalpngtest/2d-3d-expected.png b/tests/regression/cgalpngtest/2d-3d-expected.png
new file mode 100644
index 0000000..4d202ac
--- /dev/null
+++ b/tests/regression/cgalpngtest/2d-3d-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/assign-tests-expected.png b/tests/regression/cgalpngtest/assign-tests-expected.png
new file mode 100644
index 0000000..465a94d
--- /dev/null
+++ b/tests/regression/cgalpngtest/assign-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/background-modifier-expected.png b/tests/regression/cgalpngtest/background-modifier-expected.png
new file mode 100644
index 0000000..e003a87
--- /dev/null
+++ b/tests/regression/cgalpngtest/background-modifier-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/circle-tests-expected.png b/tests/regression/cgalpngtest/circle-tests-expected.png
new file mode 100644
index 0000000..0736af5
--- /dev/null
+++ b/tests/regression/cgalpngtest/circle-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/color-tests-expected.png b/tests/regression/cgalpngtest/color-tests-expected.png
new file mode 100644
index 0000000..207fc5b
--- /dev/null
+++ b/tests/regression/cgalpngtest/color-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/cube-tests-expected.png b/tests/regression/cgalpngtest/cube-tests-expected.png
new file mode 100644
index 0000000..536f220
--- /dev/null
+++ b/tests/regression/cgalpngtest/cube-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/cylinder-tests-expected.png b/tests/regression/cgalpngtest/cylinder-tests-expected.png
new file mode 100644
index 0000000..9d96df2
--- /dev/null
+++ b/tests/regression/cgalpngtest/cylinder-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/difference-tests-expected.png b/tests/regression/cgalpngtest/difference-tests-expected.png
new file mode 100644
index 0000000..e672c48
--- /dev/null
+++ b/tests/regression/cgalpngtest/difference-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/disable-modifier-expected.png b/tests/regression/cgalpngtest/disable-modifier-expected.png
new file mode 100644
index 0000000..550a71d
--- /dev/null
+++ b/tests/regression/cgalpngtest/disable-modifier-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/for-nested-tests-expected.png b/tests/regression/cgalpngtest/for-nested-tests-expected.png
new file mode 100644
index 0000000..e7178c2
--- /dev/null
+++ b/tests/regression/cgalpngtest/for-nested-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/for-tests-expected.png b/tests/regression/cgalpngtest/for-tests-expected.png
new file mode 100644
index 0000000..bf1970a
--- /dev/null
+++ b/tests/regression/cgalpngtest/for-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/highlight-modifier-expected.png b/tests/regression/cgalpngtest/highlight-modifier-expected.png
new file mode 100644
index 0000000..29a4117
--- /dev/null
+++ b/tests/regression/cgalpngtest/highlight-modifier-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/hull2-tests-expected.png b/tests/regression/cgalpngtest/hull2-tests-expected.png
new file mode 100644
index 0000000..256b349
--- /dev/null
+++ b/tests/regression/cgalpngtest/hull2-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/import_dxf-tests-expected.png b/tests/regression/cgalpngtest/import_dxf-tests-expected.png
new file mode 100644
index 0000000..7c8a63e
--- /dev/null
+++ b/tests/regression/cgalpngtest/import_dxf-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/intersection-tests-expected.png b/tests/regression/cgalpngtest/intersection-tests-expected.png
new file mode 100644
index 0000000..6d004b0
--- /dev/null
+++ b/tests/regression/cgalpngtest/intersection-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/intersection_for-tests-expected.png b/tests/regression/cgalpngtest/intersection_for-tests-expected.png
new file mode 100644
index 0000000..dc4c56a
--- /dev/null
+++ b/tests/regression/cgalpngtest/intersection_for-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/linear_extrude-tests-expected.png b/tests/regression/cgalpngtest/linear_extrude-tests-expected.png
new file mode 100644
index 0000000..4ed4361
--- /dev/null
+++ b/tests/regression/cgalpngtest/linear_extrude-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/minkowski2-tests-expected.png b/tests/regression/cgalpngtest/minkowski2-tests-expected.png
new file mode 100644
index 0000000..ebdbc74
--- /dev/null
+++ b/tests/regression/cgalpngtest/minkowski2-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/minkowski3-tests-expected.png b/tests/regression/cgalpngtest/minkowski3-tests-expected.png
new file mode 100644
index 0000000..6d74961
--- /dev/null
+++ b/tests/regression/cgalpngtest/minkowski3-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/polygon-tests-expected.png b/tests/regression/cgalpngtest/polygon-tests-expected.png
new file mode 100644
index 0000000..89aed2f
--- /dev/null
+++ b/tests/regression/cgalpngtest/polygon-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/projection-tests-expected.png b/tests/regression/cgalpngtest/projection-tests-expected.png
new file mode 100644
index 0000000..800f7ba
--- /dev/null
+++ b/tests/regression/cgalpngtest/projection-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/render-tests-expected.png b/tests/regression/cgalpngtest/render-tests-expected.png
new file mode 100644
index 0000000..8087794
--- /dev/null
+++ b/tests/regression/cgalpngtest/render-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/root-modifier-expected.png b/tests/regression/cgalpngtest/root-modifier-expected.png
new file mode 100644
index 0000000..550a71d
--- /dev/null
+++ b/tests/regression/cgalpngtest/root-modifier-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/rotate_extrude-tests-expected.png b/tests/regression/cgalpngtest/rotate_extrude-tests-expected.png
new file mode 100644
index 0000000..ee60a72
--- /dev/null
+++ b/tests/regression/cgalpngtest/rotate_extrude-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/sphere-tests-expected.png b/tests/regression/cgalpngtest/sphere-tests-expected.png
new file mode 100644
index 0000000..6ad650f
--- /dev/null
+++ b/tests/regression/cgalpngtest/sphere-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/square-tests-expected.png b/tests/regression/cgalpngtest/square-tests-expected.png
new file mode 100644
index 0000000..8c9bc60
--- /dev/null
+++ b/tests/regression/cgalpngtest/square-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/surface-tests-expected.png b/tests/regression/cgalpngtest/surface-tests-expected.png
new file mode 100644
index 0000000..cc29f66
--- /dev/null
+++ b/tests/regression/cgalpngtest/surface-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/transform-tests-expected.png b/tests/regression/cgalpngtest/transform-tests-expected.png
new file mode 100644
index 0000000..08cfce8
--- /dev/null
+++ b/tests/regression/cgalpngtest/transform-tests-expected.png
Binary files differ
diff --git a/tests/regression/cgalpngtest/union-tests-expected.png b/tests/regression/cgalpngtest/union-tests-expected.png
new file mode 100644
index 0000000..c390f42
--- /dev/null
+++ b/tests/regression/cgalpngtest/union-tests-expected.png
Binary files differ
diff --git a/tests/regression/csgtermtest/allfunctions-expected.txt b/tests/regression/csgtermtest/allfunctions-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/allfunctions-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/allmodules-expected.txt b/tests/regression/csgtermtest/allmodules-expected.txt
new file mode 100644
index 0000000..d7a04fc
--- /dev/null
+++ b/tests/regression/csgtermtest/allmodules-expected.txt
@@ -0,0 +1 @@
+(((((((((((((linear_extrude14 + linear_extrude15) + rotate_extrude16) + rotate_extrude17) + import21) + cube23) + sphere24) + cylinder25) + polyhedron26) + square27) + circle28) + polygon29) + projection30) + surface32)
diff --git a/tests/regression/csgtermtest/assign-expected.txt b/tests/regression/csgtermtest/assign-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/assign-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/child-expected.txt b/tests/regression/csgtermtest/child-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/child-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/circle-expected.txt b/tests/regression/csgtermtest/circle-expected.txt
new file mode 100644
index 0000000..b8c8161
--- /dev/null
+++ b/tests/regression/csgtermtest/circle-expected.txt
@@ -0,0 +1 @@
+circle2
diff --git a/tests/regression/csgtermtest/color-expected.txt b/tests/regression/csgtermtest/color-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/color-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/cube-expected.txt b/tests/regression/csgtermtest/cube-expected.txt
new file mode 100644
index 0000000..3393bc4
--- /dev/null
+++ b/tests/regression/csgtermtest/cube-expected.txt
@@ -0,0 +1 @@
+cube2
diff --git a/tests/regression/csgtermtest/cylinder-expected.txt b/tests/regression/csgtermtest/cylinder-expected.txt
new file mode 100644
index 0000000..f3dd1f9
--- /dev/null
+++ b/tests/regression/csgtermtest/cylinder-expected.txt
@@ -0,0 +1 @@
+cylinder2
diff --git a/tests/regression/csgtermtest/difference-expected.txt b/tests/regression/csgtermtest/difference-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/difference-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/dxf_linear_extrude-expected.txt b/tests/regression/csgtermtest/dxf_linear_extrude-expected.txt
new file mode 100644
index 0000000..bebcc7a
--- /dev/null
+++ b/tests/regression/csgtermtest/dxf_linear_extrude-expected.txt
@@ -0,0 +1 @@
+linear_extrude2
diff --git a/tests/regression/csgtermtest/dxf_rotate_extrude-expected.txt b/tests/regression/csgtermtest/dxf_rotate_extrude-expected.txt
new file mode 100644
index 0000000..318aa70
--- /dev/null
+++ b/tests/regression/csgtermtest/dxf_rotate_extrude-expected.txt
@@ -0,0 +1 @@
+rotate_extrude2
diff --git a/tests/regression/csgtermtest/echo-expected.txt b/tests/regression/csgtermtest/echo-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/echo-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/for-expected.txt b/tests/regression/csgtermtest/for-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/for-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/glide-expected.txt b/tests/regression/csgtermtest/glide-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/glide-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/group-expected.txt b/tests/regression/csgtermtest/group-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/group-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/hull-expected.txt b/tests/regression/csgtermtest/hull-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/hull-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/if-expected.txt b/tests/regression/csgtermtest/if-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/if-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/import-expected.txt b/tests/regression/csgtermtest/import-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/import-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/import_dxf-expected.txt b/tests/regression/csgtermtest/import_dxf-expected.txt
new file mode 100644
index 0000000..847d6c3
--- /dev/null
+++ b/tests/regression/csgtermtest/import_dxf-expected.txt
@@ -0,0 +1 @@
+import2
diff --git a/tests/regression/csgtermtest/import_off-expected.txt b/tests/regression/csgtermtest/import_off-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/import_off-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/import_stl-expected.txt b/tests/regression/csgtermtest/import_stl-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/import_stl-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/intersection-expected.txt b/tests/regression/csgtermtest/intersection-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/intersection-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/intersection_for-expected.txt b/tests/regression/csgtermtest/intersection_for-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/intersection_for-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/linear_extrude-expected.txt b/tests/regression/csgtermtest/linear_extrude-expected.txt
new file mode 100644
index 0000000..bebcc7a
--- /dev/null
+++ b/tests/regression/csgtermtest/linear_extrude-expected.txt
@@ -0,0 +1 @@
+linear_extrude2
diff --git a/tests/regression/csgtermtest/minkowski-expected.txt b/tests/regression/csgtermtest/minkowski-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/minkowski-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/mirror-expected.txt b/tests/regression/csgtermtest/mirror-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/mirror-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/multmatrix-expected.txt b/tests/regression/csgtermtest/multmatrix-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/multmatrix-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/polygon-expected.txt b/tests/regression/csgtermtest/polygon-expected.txt
new file mode 100644
index 0000000..b41dfc6
--- /dev/null
+++ b/tests/regression/csgtermtest/polygon-expected.txt
@@ -0,0 +1 @@
+polygon2
diff --git a/tests/regression/csgtermtest/polyhedron-expected.txt b/tests/regression/csgtermtest/polyhedron-expected.txt
new file mode 100644
index 0000000..5ccc055
--- /dev/null
+++ b/tests/regression/csgtermtest/polyhedron-expected.txt
@@ -0,0 +1 @@
+polyhedron2
diff --git a/tests/regression/csgtermtest/projection-expected.txt b/tests/regression/csgtermtest/projection-expected.txt
new file mode 100644
index 0000000..2a4c47e
--- /dev/null
+++ b/tests/regression/csgtermtest/projection-expected.txt
@@ -0,0 +1 @@
+projection2
diff --git a/tests/regression/csgtermtest/render-expected.txt b/tests/regression/csgtermtest/render-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/render-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/rotate-expected.txt b/tests/regression/csgtermtest/rotate-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/rotate-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/rotate_extrude-expected.txt b/tests/regression/csgtermtest/rotate_extrude-expected.txt
new file mode 100644
index 0000000..318aa70
--- /dev/null
+++ b/tests/regression/csgtermtest/rotate_extrude-expected.txt
@@ -0,0 +1 @@
+rotate_extrude2
diff --git a/tests/regression/csgtermtest/scale-expected.txt b/tests/regression/csgtermtest/scale-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/scale-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/sphere-expected.txt b/tests/regression/csgtermtest/sphere-expected.txt
new file mode 100644
index 0000000..f9b8d73
--- /dev/null
+++ b/tests/regression/csgtermtest/sphere-expected.txt
@@ -0,0 +1 @@
+sphere2
diff --git a/tests/regression/csgtermtest/square-expected.txt b/tests/regression/csgtermtest/square-expected.txt
new file mode 100644
index 0000000..8190c0f
--- /dev/null
+++ b/tests/regression/csgtermtest/square-expected.txt
@@ -0,0 +1 @@
+square2
diff --git a/tests/regression/csgtermtest/subdiv-expected.txt b/tests/regression/csgtermtest/subdiv-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/subdiv-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/surface-expected.txt b/tests/regression/csgtermtest/surface-expected.txt
new file mode 100644
index 0000000..d0e3459
--- /dev/null
+++ b/tests/regression/csgtermtest/surface-expected.txt
@@ -0,0 +1 @@
+surface2
diff --git a/tests/regression/csgtermtest/transform-insert-expected.txt b/tests/regression/csgtermtest/transform-insert-expected.txt
new file mode 100644
index 0000000..847d6c3
--- /dev/null
+++ b/tests/regression/csgtermtest/transform-insert-expected.txt
@@ -0,0 +1 @@
+import2
diff --git a/tests/regression/csgtermtest/translate-expected.txt b/tests/regression/csgtermtest/translate-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/translate-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtermtest/union-expected.txt b/tests/regression/csgtermtest/union-expected.txt
new file mode 100644
index 0000000..a40cf60
--- /dev/null
+++ b/tests/regression/csgtermtest/union-expected.txt
@@ -0,0 +1 @@
+No top-level CSG object
diff --git a/tests/regression/csgtexttest/allfunctions-expected.txt b/tests/regression/csgtexttest/allfunctions-expected.txt
new file mode 100644
index 0000000..331822f
--- /dev/null
+++ b/tests/regression/csgtexttest/allfunctions-expected.txt
@@ -0,0 +1 @@
+group1
diff --git a/tests/regression/csgtexttest/allmodules-expected.txt b/tests/regression/csgtexttest/allmodules-expected.txt
new file mode 100644
index 0000000..34fa5ae
--- /dev/null
+++ b/tests/regression/csgtexttest/allmodules-expected.txt
@@ -0,0 +1 @@
+group1(minkowski2+glide3+subdiv4+hull5+group6+group6+group6+intersection_for9+group6+union11+difference12+intersection13+linear_extrude+linear_extrude+rotate_extrude+rotate_extrude+import+import+import+import+group6+cube+sphere+cylinder+polyhedron+square+circle+polygon+projection+render31+surface+transform33+transform33+transform35+transform33+transform33+color38)
diff --git a/tests/regression/csgtexttest/assign-expected.txt b/tests/regression/csgtexttest/assign-expected.txt
new file mode 100644
index 0000000..a08e59e
--- /dev/null
+++ b/tests/regression/csgtexttest/assign-expected.txt
@@ -0,0 +1 @@
+group1(group2)
diff --git a/tests/regression/csgtexttest/child-expected.txt b/tests/regression/csgtexttest/child-expected.txt
new file mode 100644
index 0000000..331822f
--- /dev/null
+++ b/tests/regression/csgtexttest/child-expected.txt
@@ -0,0 +1 @@
+group1
diff --git a/tests/regression/csgtexttest/circle-expected.txt b/tests/regression/csgtexttest/circle-expected.txt
new file mode 100644
index 0000000..44ca16a
--- /dev/null
+++ b/tests/regression/csgtexttest/circle-expected.txt
@@ -0,0 +1 @@
+group1(circle)
diff --git a/tests/regression/csgtexttest/color-expected.txt b/tests/regression/csgtexttest/color-expected.txt
new file mode 100644
index 0000000..6140174
--- /dev/null
+++ b/tests/regression/csgtexttest/color-expected.txt
@@ -0,0 +1 @@
+group1(color2)
diff --git a/tests/regression/csgtexttest/cube-expected.txt b/tests/regression/csgtexttest/cube-expected.txt
new file mode 100644
index 0000000..07b688d
--- /dev/null
+++ b/tests/regression/csgtexttest/cube-expected.txt
@@ -0,0 +1 @@
+group1(cube)
diff --git a/tests/regression/csgtexttest/cylinder-expected.txt b/tests/regression/csgtexttest/cylinder-expected.txt
new file mode 100644
index 0000000..3f8a41f
--- /dev/null
+++ b/tests/regression/csgtexttest/cylinder-expected.txt
@@ -0,0 +1 @@
+group1(cylinder)
diff --git a/tests/regression/csgtexttest/difference-expected.txt b/tests/regression/csgtexttest/difference-expected.txt
new file mode 100644
index 0000000..551bb16
--- /dev/null
+++ b/tests/regression/csgtexttest/difference-expected.txt
@@ -0,0 +1 @@
+group1(difference2)
diff --git a/tests/regression/csgtexttest/difference-tests-expected.txt b/tests/regression/csgtexttest/difference-tests-expected.txt
new file mode 100644
index 0000000..6bbfe30
--- /dev/null
+++ b/tests/regression/csgtexttest/difference-tests-expected.txt
@@ -0,0 +1 @@
+group1(difference2(sphere-cube))
diff --git a/tests/regression/csgtexttest/dim-all-expected.txt b/tests/regression/csgtexttest/dim-all-expected.txt
new file mode 100644
index 0000000..6c127a8
--- /dev/null
+++ b/tests/regression/csgtexttest/dim-all-expected.txt
@@ -0,0 +1 @@
+group1(group2+group2+group2+group2+group2+group2+group2+group2)
diff --git a/tests/regression/csgtexttest/dxf_linear_extrude-expected.txt b/tests/regression/csgtexttest/dxf_linear_extrude-expected.txt
new file mode 100644
index 0000000..fa1671c
--- /dev/null
+++ b/tests/regression/csgtexttest/dxf_linear_extrude-expected.txt
@@ -0,0 +1 @@
+group1(linear_extrude)
diff --git a/tests/regression/csgtexttest/dxf_rotate_extrude-expected.txt b/tests/regression/csgtexttest/dxf_rotate_extrude-expected.txt
new file mode 100644
index 0000000..452f8e4
--- /dev/null
+++ b/tests/regression/csgtexttest/dxf_rotate_extrude-expected.txt
@@ -0,0 +1 @@
+group1(rotate_extrude)
diff --git a/tests/regression/csgtexttest/echo-expected.txt b/tests/regression/csgtexttest/echo-expected.txt
new file mode 100644
index 0000000..a08e59e
--- /dev/null
+++ b/tests/regression/csgtexttest/echo-expected.txt
@@ -0,0 +1 @@
+group1(group2)
diff --git a/tests/regression/csgtexttest/for-expected.txt b/tests/regression/csgtexttest/for-expected.txt
new file mode 100644
index 0000000..a08e59e
--- /dev/null
+++ b/tests/regression/csgtexttest/for-expected.txt
@@ -0,0 +1 @@
+group1(group2)
diff --git a/tests/regression/csgtexttest/glide-expected.txt b/tests/regression/csgtexttest/glide-expected.txt
new file mode 100644
index 0000000..a792750
--- /dev/null
+++ b/tests/regression/csgtexttest/glide-expected.txt
@@ -0,0 +1 @@
+group1(glide2)
diff --git a/tests/regression/csgtexttest/group-expected.txt b/tests/regression/csgtexttest/group-expected.txt
new file mode 100644
index 0000000..a08e59e
--- /dev/null
+++ b/tests/regression/csgtexttest/group-expected.txt
@@ -0,0 +1 @@
+group1(group2)
diff --git a/tests/regression/csgtexttest/hull-expected.txt b/tests/regression/csgtexttest/hull-expected.txt
new file mode 100644
index 0000000..dc47755
--- /dev/null
+++ b/tests/regression/csgtexttest/hull-expected.txt
@@ -0,0 +1 @@
+group1(hull2)
diff --git a/tests/regression/csgtexttest/if-expected.txt b/tests/regression/csgtexttest/if-expected.txt
new file mode 100644
index 0000000..a08e59e
--- /dev/null
+++ b/tests/regression/csgtexttest/if-expected.txt
@@ -0,0 +1 @@
+group1(group2)
diff --git a/tests/regression/csgtexttest/import-expected.txt b/tests/regression/csgtexttest/import-expected.txt
new file mode 100644
index 0000000..a673ddb
--- /dev/null
+++ b/tests/regression/csgtexttest/import-expected.txt
@@ -0,0 +1 @@
+group1(import)
diff --git a/tests/regression/csgtexttest/import_dxf-expected.txt b/tests/regression/csgtexttest/import_dxf-expected.txt
new file mode 100644
index 0000000..a673ddb
--- /dev/null
+++ b/tests/regression/csgtexttest/import_dxf-expected.txt
@@ -0,0 +1 @@
+group1(import)
diff --git a/tests/regression/csgtexttest/import_off-expected.txt b/tests/regression/csgtexttest/import_off-expected.txt
new file mode 100644
index 0000000..a673ddb
--- /dev/null
+++ b/tests/regression/csgtexttest/import_off-expected.txt
@@ -0,0 +1 @@
+group1(import)
diff --git a/tests/regression/csgtexttest/import_stl-expected.txt b/tests/regression/csgtexttest/import_stl-expected.txt
new file mode 100644
index 0000000..a673ddb
--- /dev/null
+++ b/tests/regression/csgtexttest/import_stl-expected.txt
@@ -0,0 +1 @@
+group1(import)
diff --git a/tests/regression/csgtexttest/import_stl-tests-expected.txt b/tests/regression/csgtexttest/import_stl-tests-expected.txt
new file mode 100644
index 0000000..47c4707
--- /dev/null
+++ b/tests/regression/csgtexttest/import_stl-tests-expected.txt
@@ -0,0 +1 @@
+group1(import_stl)
diff --git a/tests/regression/csgtexttest/intersection-expected.txt b/tests/regression/csgtexttest/intersection-expected.txt
new file mode 100644
index 0000000..0ce0967
--- /dev/null
+++ b/tests/regression/csgtexttest/intersection-expected.txt
@@ -0,0 +1 @@
+group1(intersection2)
diff --git a/tests/regression/csgtexttest/intersection-tests-expected.txt b/tests/regression/csgtexttest/intersection-tests-expected.txt
new file mode 100644
index 0000000..3077e22
--- /dev/null
+++ b/tests/regression/csgtexttest/intersection-tests-expected.txt
@@ -0,0 +1 @@
+group1(intersection2(sphere*cube))
diff --git a/tests/regression/csgtexttest/intersection_for-expected.txt b/tests/regression/csgtexttest/intersection_for-expected.txt
new file mode 100644
index 0000000..b503644
--- /dev/null
+++ b/tests/regression/csgtexttest/intersection_for-expected.txt
@@ -0,0 +1 @@
+group1(intersection_for2)
diff --git a/tests/regression/csgtexttest/linear_extrude-expected.txt b/tests/regression/csgtexttest/linear_extrude-expected.txt
new file mode 100644
index 0000000..fa1671c
--- /dev/null
+++ b/tests/regression/csgtexttest/linear_extrude-expected.txt
@@ -0,0 +1 @@
+group1(linear_extrude)
diff --git a/tests/regression/csgtexttest/linear_extrude-tests-expected.txt b/tests/regression/csgtexttest/linear_extrude-tests-expected.txt
new file mode 100644
index 0000000..f9639c9
--- /dev/null
+++ b/tests/regression/csgtexttest/linear_extrude-tests-expected.txt
@@ -0,0 +1 @@
+group1(linear_extrude+transform4(linear_extrude)+transform7(linear_extrude)+transform10(linear_extrude)+transform13(linear_extrude)+transform16(linear_extrude))
diff --git a/tests/regression/csgtexttest/minkowski-expected.txt b/tests/regression/csgtexttest/minkowski-expected.txt
new file mode 100644
index 0000000..e601bac
--- /dev/null
+++ b/tests/regression/csgtexttest/minkowski-expected.txt
@@ -0,0 +1 @@
+group1(minkowski2)
diff --git a/tests/regression/csgtexttest/mirror-expected.txt b/tests/regression/csgtexttest/mirror-expected.txt
new file mode 100644
index 0000000..80024d2
--- /dev/null
+++ b/tests/regression/csgtexttest/mirror-expected.txt
@@ -0,0 +1 @@
+group1(transform2)
diff --git a/tests/regression/csgtexttest/multmatrix-expected.txt b/tests/regression/csgtexttest/multmatrix-expected.txt
new file mode 100644
index 0000000..80024d2
--- /dev/null
+++ b/tests/regression/csgtexttest/multmatrix-expected.txt
@@ -0,0 +1 @@
+group1(transform2)
diff --git a/tests/regression/csgtexttest/null-polygons-expected.txt b/tests/regression/csgtexttest/null-polygons-expected.txt
new file mode 100644
index 0000000..4afd2e4
--- /dev/null
+++ b/tests/regression/csgtexttest/null-polygons-expected.txt
@@ -0,0 +1 @@
+group1(linear_extrude+linear_extrude)
diff --git a/tests/regression/csgtexttest/polygon-expected.txt b/tests/regression/csgtexttest/polygon-expected.txt
new file mode 100644
index 0000000..e308e30
--- /dev/null
+++ b/tests/regression/csgtexttest/polygon-expected.txt
@@ -0,0 +1 @@
+group1(polygon)
diff --git a/tests/regression/csgtexttest/polygon-illegal-winding-expected.txt b/tests/regression/csgtexttest/polygon-illegal-winding-expected.txt
new file mode 100644
index 0000000..994b16d
--- /dev/null
+++ b/tests/regression/csgtexttest/polygon-illegal-winding-expected.txt
@@ -0,0 +1 @@
+group1(polyhedron)
diff --git a/tests/regression/csgtexttest/polyhedron-expected.txt b/tests/regression/csgtexttest/polyhedron-expected.txt
new file mode 100644
index 0000000..994b16d
--- /dev/null
+++ b/tests/regression/csgtexttest/polyhedron-expected.txt
@@ -0,0 +1 @@
+group1(polyhedron)
diff --git a/tests/regression/csgtexttest/polyset-reduce-crash-expected.txt b/tests/regression/csgtexttest/polyset-reduce-crash-expected.txt
new file mode 100644
index 0000000..93ab028
--- /dev/null
+++ b/tests/regression/csgtexttest/polyset-reduce-crash-expected.txt
@@ -0,0 +1 @@
+group1(transform2(union3(transform4(polygon+polygon+polygon+polygon+polygon+polygon+polygon+polygon)+circle)))
diff --git a/tests/regression/csgtexttest/projection-expected.txt b/tests/regression/csgtexttest/projection-expected.txt
new file mode 100644
index 0000000..38b6abf
--- /dev/null
+++ b/tests/regression/csgtexttest/projection-expected.txt
@@ -0,0 +1 @@
+group1(projection)
diff --git a/tests/regression/csgtexttest/projection-tests-expected.txt b/tests/regression/csgtexttest/projection-tests-expected.txt
new file mode 100644
index 0000000..aa9c079
--- /dev/null
+++ b/tests/regression/csgtexttest/projection-tests-expected.txt
@@ -0,0 +1 @@
+group1(linear_extrude+transform5(linear_extrude)+transform10(linear_extrude))
diff --git a/tests/regression/csgtexttest/render-expected.txt b/tests/regression/csgtexttest/render-expected.txt
new file mode 100644
index 0000000..b53708e
--- /dev/null
+++ b/tests/regression/csgtexttest/render-expected.txt
@@ -0,0 +1 @@
+group1(render2)
diff --git a/tests/regression/csgtexttest/rotate-expected.txt b/tests/regression/csgtexttest/rotate-expected.txt
new file mode 100644
index 0000000..80024d2
--- /dev/null
+++ b/tests/regression/csgtexttest/rotate-expected.txt
@@ -0,0 +1 @@
+group1(transform2)
diff --git a/tests/regression/csgtexttest/rotate_extrude-expected.txt b/tests/regression/csgtexttest/rotate_extrude-expected.txt
new file mode 100644
index 0000000..452f8e4
--- /dev/null
+++ b/tests/regression/csgtexttest/rotate_extrude-expected.txt
@@ -0,0 +1 @@
+group1(rotate_extrude)
diff --git a/tests/regression/csgtexttest/rotate_extrude-tests-expected.txt b/tests/regression/csgtexttest/rotate_extrude-tests-expected.txt
new file mode 100644
index 0000000..452f8e4
--- /dev/null
+++ b/tests/regression/csgtexttest/rotate_extrude-tests-expected.txt
@@ -0,0 +1 @@
+group1(rotate_extrude)
diff --git a/tests/regression/csgtexttest/scale-expected.txt b/tests/regression/csgtexttest/scale-expected.txt
new file mode 100644
index 0000000..80024d2
--- /dev/null
+++ b/tests/regression/csgtexttest/scale-expected.txt
@@ -0,0 +1 @@
+group1(transform2)
diff --git a/tests/regression/csgtexttest/sphere-expected.txt b/tests/regression/csgtexttest/sphere-expected.txt
new file mode 100644
index 0000000..2bf6a72
--- /dev/null
+++ b/tests/regression/csgtexttest/sphere-expected.txt
@@ -0,0 +1 @@
+group1(sphere)
diff --git a/tests/regression/csgtexttest/sphere-tests-expected.txt b/tests/regression/csgtexttest/sphere-tests-expected.txt
new file mode 100644
index 0000000..94323fd
--- /dev/null
+++ b/tests/regression/csgtexttest/sphere-tests-expected.txt
@@ -0,0 +1 @@
+group1(sphere+transform3(sphere)+transform5(sphere)+transform7(sphere))
diff --git a/tests/regression/csgtexttest/square-expected.txt b/tests/regression/csgtexttest/square-expected.txt
new file mode 100644
index 0000000..e235806
--- /dev/null
+++ b/tests/regression/csgtexttest/square-expected.txt
@@ -0,0 +1 @@
+group1(square)
diff --git a/tests/regression/csgtexttest/subdiv-expected.txt b/tests/regression/csgtexttest/subdiv-expected.txt
new file mode 100644
index 0000000..b096229
--- /dev/null
+++ b/tests/regression/csgtexttest/subdiv-expected.txt
@@ -0,0 +1 @@
+group1(subdiv2)
diff --git a/tests/regression/csgtexttest/surface-expected.txt b/tests/regression/csgtexttest/surface-expected.txt
new file mode 100644
index 0000000..7c822d3
--- /dev/null
+++ b/tests/regression/csgtexttest/surface-expected.txt
@@ -0,0 +1 @@
+group1(surface)
diff --git a/tests/regression/csgtexttest/surface-tests-expected.txt b/tests/regression/csgtexttest/surface-tests-expected.txt
new file mode 100644
index 0000000..7c822d3
--- /dev/null
+++ b/tests/regression/csgtexttest/surface-tests-expected.txt
@@ -0,0 +1 @@
+group1(surface)
diff --git a/tests/regression/csgtexttest/transform-insert-expected.txt b/tests/regression/csgtexttest/transform-insert-expected.txt
new file mode 100644
index 0000000..a673ddb
--- /dev/null
+++ b/tests/regression/csgtexttest/transform-insert-expected.txt
@@ -0,0 +1 @@
+group1(import)
diff --git a/tests/regression/csgtexttest/translate-expected.txt b/tests/regression/csgtexttest/translate-expected.txt
new file mode 100644
index 0000000..80024d2
--- /dev/null
+++ b/tests/regression/csgtexttest/translate-expected.txt
@@ -0,0 +1 @@
+group1(transform2)
diff --git a/tests/regression/csgtexttest/union-expected.txt b/tests/regression/csgtexttest/union-expected.txt
new file mode 100644
index 0000000..1884c0f
--- /dev/null
+++ b/tests/regression/csgtexttest/union-expected.txt
@@ -0,0 +1 @@
+group1(union2)
diff --git a/tests/regression/dumptest/allfunctions-expected.txt b/tests/regression/dumptest/allfunctions-expected.txt
new file mode 100644
index 0000000..0a04719
--- /dev/null
+++ b/tests/regression/dumptest/allfunctions-expected.txt
@@ -0,0 +1 @@
+group();
diff --git a/tests/regression/dumptest/allmodules-expected.txt b/tests/regression/dumptest/allmodules-expected.txt
new file mode 100644
index 0000000..e708c43
--- /dev/null
+++ b/tests/regression/dumptest/allmodules-expected.txt
@@ -0,0 +1,39 @@
+group() {
+ minkowski(convexity = 0);
+ glide(path = undef, convexity = 0);
+ subdiv(level = 1, convexity = 0);
+ hull();
+ group();
+ group();
+ group();
+ intersection_for();
+ group();
+ union();
+ difference();
+ intersection();
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 100, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 100, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+ rotate_extrude(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+ rotate_extrude(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+ import(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+ import(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+ import(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+ import(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+ group();
+ cube(size = [1, 1, 1], center = false);
+ sphere($fn = 0, $fa = 12, $fs = 1, r = 1);
+ cylinder($fn = 0, $fa = 12, $fs = 1, h = 1, r1 = 1, r2 = 1, center = false);
+ polyhedron(points = undef, triangles = undef, convexity = 1);
+ square(size = [1, 1], center = false);
+ circle($fn = 0, $fa = 12, $fs = 1, r = 1);
+ polygon(points = undef, paths = undef, convexity = 1);
+ projection(cut = false, convexity = 0);
+ render(convexity = 1);
+ surface(file = "", center = false);
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
+ multmatrix([[-1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
+ color([-1, -1, -1, 1]);
+}
diff --git a/tests/regression/dumptest/assign-expected.txt b/tests/regression/dumptest/assign-expected.txt
new file mode 100644
index 0000000..434cc8f
--- /dev/null
+++ b/tests/regression/dumptest/assign-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ group();
+}
diff --git a/tests/regression/dumptest/child-expected.txt b/tests/regression/dumptest/child-expected.txt
new file mode 100644
index 0000000..0a04719
--- /dev/null
+++ b/tests/regression/dumptest/child-expected.txt
@@ -0,0 +1 @@
+group();
diff --git a/tests/regression/dumptest/circle-expected.txt b/tests/regression/dumptest/circle-expected.txt
new file mode 100644
index 0000000..1060d3c
--- /dev/null
+++ b/tests/regression/dumptest/circle-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ circle($fn = 0, $fa = 12, $fs = 1, r = 1);
+}
diff --git a/tests/regression/dumptest/color-expected.txt b/tests/regression/dumptest/color-expected.txt
new file mode 100644
index 0000000..ef862fc
--- /dev/null
+++ b/tests/regression/dumptest/color-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ color([-1, -1, -1, 1]);
+}
diff --git a/tests/regression/dumptest/cube-expected.txt b/tests/regression/dumptest/cube-expected.txt
new file mode 100644
index 0000000..91dc5fc
--- /dev/null
+++ b/tests/regression/dumptest/cube-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ cube(size = [1, 1, 1], center = false);
+}
diff --git a/tests/regression/dumptest/cylinder-expected.txt b/tests/regression/dumptest/cylinder-expected.txt
new file mode 100644
index 0000000..a26a533
--- /dev/null
+++ b/tests/regression/dumptest/cylinder-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ cylinder($fn = 0, $fa = 12, $fs = 1, h = 1, r1 = 1, r2 = 1, center = false);
+}
diff --git a/tests/regression/dumptest/difference-expected.txt b/tests/regression/dumptest/difference-expected.txt
new file mode 100644
index 0000000..09b977f
--- /dev/null
+++ b/tests/regression/dumptest/difference-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ difference();
+}
diff --git a/tests/regression/dumptest/difference-tests-expected.txt b/tests/regression/dumptest/difference-tests-expected.txt
new file mode 100644
index 0000000..bc59e45
--- /dev/null
+++ b/tests/regression/dumptest/difference-tests-expected.txt
@@ -0,0 +1,6 @@
+group() {
+ difference() {
+ sphere($fn = 0, $fa = 12, $fs = 1, r = 3);
+ cube(size = [3, 3, 8], center = true);
+ }
+}
diff --git a/tests/regression/dumptest/dim-all-expected.txt b/tests/regression/dumptest/dim-all-expected.txt
new file mode 100644
index 0000000..8d088d9
--- /dev/null
+++ b/tests/regression/dumptest/dim-all-expected.txt
@@ -0,0 +1,10 @@
+group() {
+ group();
+ group();
+ group();
+ group();
+ group();
+ group();
+ group();
+ group();
+}
diff --git a/tests/regression/dumptest/dxf-export-expected.txt b/tests/regression/dumptest/dxf-export-expected.txt
new file mode 100644
index 0000000..692526c
--- /dev/null
+++ b/tests/regression/dumptest/dxf-export-expected.txt
@@ -0,0 +1,17 @@
+group() {
+ circle($fn = 0, $fa = 12, $fs = 1, r = 5);
+ multmatrix([[1, 0, 0, 15], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [10, 10], center = true);
+ }
+ multmatrix([[1, 0, 0, 30], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ polygon(points = [[-5, -5], [5, -5], [0, 5]], paths = [[0, 1, 2]], convexity = 1);
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -15], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ difference() {
+ circle($fn = 0, $fa = 12, $fs = 1, r = 5);
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -6], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [12, 12], center = true);
+ }
+ }
+ }
+}
diff --git a/tests/regression/dumptest/dxf_linear_extrude-expected.txt b/tests/regression/dumptest/dxf_linear_extrude-expected.txt
new file mode 100644
index 0000000..fd6535d
--- /dev/null
+++ b/tests/regression/dumptest/dxf_linear_extrude-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 100, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+}
diff --git a/tests/regression/dumptest/dxf_rotate_extrude-expected.txt b/tests/regression/dumptest/dxf_rotate_extrude-expected.txt
new file mode 100644
index 0000000..2d65d35
--- /dev/null
+++ b/tests/regression/dumptest/dxf_rotate_extrude-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ rotate_extrude(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+}
diff --git a/tests/regression/dumptest/echo-expected.txt b/tests/regression/dumptest/echo-expected.txt
new file mode 100644
index 0000000..434cc8f
--- /dev/null
+++ b/tests/regression/dumptest/echo-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ group();
+}
diff --git a/tests/regression/dumptest/for-expected.txt b/tests/regression/dumptest/for-expected.txt
new file mode 100644
index 0000000..434cc8f
--- /dev/null
+++ b/tests/regression/dumptest/for-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ group();
+}
diff --git a/tests/regression/dumptest/glide-expected.txt b/tests/regression/dumptest/glide-expected.txt
new file mode 100644
index 0000000..67e40b8
--- /dev/null
+++ b/tests/regression/dumptest/glide-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ glide(path = undef, convexity = 0);
+}
diff --git a/tests/regression/dumptest/group-expected.txt b/tests/regression/dumptest/group-expected.txt
new file mode 100644
index 0000000..434cc8f
--- /dev/null
+++ b/tests/regression/dumptest/group-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ group();
+}
diff --git a/tests/regression/dumptest/hull-expected.txt b/tests/regression/dumptest/hull-expected.txt
new file mode 100644
index 0000000..6f777b0
--- /dev/null
+++ b/tests/regression/dumptest/hull-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ hull();
+}
diff --git a/tests/regression/dumptest/hull-tests-expected.txt b/tests/regression/dumptest/hull-tests-expected.txt
new file mode 100644
index 0000000..fd204b6
--- /dev/null
+++ b/tests/regression/dumptest/hull-tests-expected.txt
@@ -0,0 +1,46 @@
+group() {
+ group() {
+ hull() {
+ multmatrix([[1, 0, 0, 15], [0, 1, 0, 10], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ circle($fn = 0, $fa = 12, $fs = 1, r = 10);
+ }
+ difference() {
+ circle($fn = 0, $fa = 12, $fs = 1, r = 10);
+ circle($fn = 0, $fa = 12, $fs = 1, r = 5);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 40], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ hull() {
+ multmatrix([[1, 0, 0, 15], [0, 1, 0, 10], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ circle($fn = 0, $fa = 12, $fs = 1, r = 10);
+ }
+ circle($fn = 0, $fa = 12, $fs = 1, r = 10);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 40], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ hull() {
+ multmatrix([[1, 0, 0, 15], [0, 1, 0, 10], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ cylinder($fn = 0, $fa = 12, $fs = 1, h = 10, r1 = 1, r2 = 1, center = false);
+ }
+ difference() {
+ cylinder($fn = 0, $fa = 12, $fs = 1, h = 10, r1 = 1, r2 = 1, center = false);
+ cylinder($fn = 0, $fa = 12, $fs = 1, h = 5, r1 = 1, r2 = 1, center = false);
+ }
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 40], [0, 1, 0, 40], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ hull() {
+ multmatrix([[1, 0, 0, 15], [0, 1, 0, 10], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ cylinder($fn = 0, $fa = 12, $fs = 1, h = 1, r1 = 10, r2 = 10, center = false);
+ }
+ cylinder($fn = 0, $fa = 12, $fs = 1, h = 1, r1 = 10, r2 = 10, center = false);
+ }
+ }
+ }
+}
diff --git a/tests/regression/dumptest/if-expected.txt b/tests/regression/dumptest/if-expected.txt
new file mode 100644
index 0000000..434cc8f
--- /dev/null
+++ b/tests/regression/dumptest/if-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ group();
+}
diff --git a/tests/regression/dumptest/import-expected.txt b/tests/regression/dumptest/import-expected.txt
new file mode 100644
index 0000000..b424afe
--- /dev/null
+++ b/tests/regression/dumptest/import-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ import(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+}
diff --git a/tests/regression/dumptest/import_dxf-expected.txt b/tests/regression/dumptest/import_dxf-expected.txt
new file mode 100644
index 0000000..b424afe
--- /dev/null
+++ b/tests/regression/dumptest/import_dxf-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ import(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+}
diff --git a/tests/regression/dumptest/import_off-expected.txt b/tests/regression/dumptest/import_off-expected.txt
new file mode 100644
index 0000000..b424afe
--- /dev/null
+++ b/tests/regression/dumptest/import_off-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ import(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+}
diff --git a/tests/regression/dumptest/import_stl-expected.txt b/tests/regression/dumptest/import_stl-expected.txt
new file mode 100644
index 0000000..b424afe
--- /dev/null
+++ b/tests/regression/dumptest/import_stl-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ import(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+}
diff --git a/tests/regression/dumptest/import_stl-tests-expected.txt b/tests/regression/dumptest/import_stl-tests-expected.txt
new file mode 100644
index 0000000..bc27c6a
--- /dev/null
+++ b/tests/regression/dumptest/import_stl-tests-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ import_stl(file = "/Users/kintel/code/metalab/checkout/OpenSCAD/openscad-visitor/testdata/scad/import.stl", cache = "4c34b4bc.2506", convexity = 1);
+}
diff --git a/tests/regression/dumptest/include-test-expected.txt b/tests/regression/dumptest/include-test-expected.txt
new file mode 100644
index 0000000..871e45d
--- /dev/null
+++ b/tests/regression/dumptest/include-test-expected.txt
@@ -0,0 +1,20 @@
+group() {
+ group() {
+ group() {
+ group();
+ }
+ group() {
+ group();
+ }
+ group() {
+ group();
+ }
+ group() {
+ group();
+ }
+ group() {
+ group();
+ }
+ sphere($fn = 0, $fa = 12, $fs = 1, r = 1);
+ }
+}
diff --git a/tests/regression/dumptest/intersection-expected.txt b/tests/regression/dumptest/intersection-expected.txt
new file mode 100644
index 0000000..409e196
--- /dev/null
+++ b/tests/regression/dumptest/intersection-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ intersection();
+}
diff --git a/tests/regression/dumptest/intersection-tests-expected.txt b/tests/regression/dumptest/intersection-tests-expected.txt
new file mode 100644
index 0000000..90349a3
--- /dev/null
+++ b/tests/regression/dumptest/intersection-tests-expected.txt
@@ -0,0 +1,6 @@
+group() {
+ intersection() {
+ sphere($fn = 0, $fa = 12, $fs = 1, r = 3);
+ cube(size = [3, 3, 8], center = true);
+ }
+}
diff --git a/tests/regression/dumptest/intersection_for-expected.txt b/tests/regression/dumptest/intersection_for-expected.txt
new file mode 100644
index 0000000..8bb5d2d
--- /dev/null
+++ b/tests/regression/dumptest/intersection_for-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ intersection_for();
+}
diff --git a/tests/regression/dumptest/linear_extrude-expected.txt b/tests/regression/dumptest/linear_extrude-expected.txt
new file mode 100644
index 0000000..fd6535d
--- /dev/null
+++ b/tests/regression/dumptest/linear_extrude-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 100, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+}
diff --git a/tests/regression/dumptest/linear_extrude-tests-expected.txt b/tests/regression/dumptest/linear_extrude-tests-expected.txt
new file mode 100644
index 0000000..8fe9928
--- /dev/null
+++ b/tests/regression/dumptest/linear_extrude-tests-expected.txt
@@ -0,0 +1,30 @@
+group() {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 10, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1) {
+ square(size = [10, 10], center = false);
+ }
+ multmatrix([[1, 0, 0, 19], [0, 1, 0, 5], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 10, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1) {
+ circle($fn = 0, $fa = 12, $fs = 1, r = 5);
+ }
+ }
+ multmatrix([[1, 0, 0, 31.5], [0, 1, 0, 2.5], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 10, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1) {
+ polygon(points = [[-5, -2.5], [5, -2.5], [0, 2.5]], paths = undef, convexity = 1);
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, -12], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 20, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, twist = 45, slices = 3, $fn = 0, $fa = 12, $fs = 1) {
+ square(size = [10, 10], center = false);
+ }
+ }
+ multmatrix([[1, 0, 0, 19], [0, 1, 0, -7], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 20, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, twist = 90, slices = 7, $fn = 0, $fa = 12, $fs = 1) {
+ circle($fn = 0, $fa = 12, $fs = 1, r = 5);
+ }
+ }
+ multmatrix([[1, 0, 0, 31.5], [0, 1, 0, -9.5], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 20, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, twist = 180, slices = 15, $fn = 0, $fa = 12, $fs = 1) {
+ polygon(points = [[-5, -2.5], [5, -2.5], [0, 2.5]], paths = undef, convexity = 1);
+ }
+ }
+}
diff --git a/tests/regression/dumptest/minkowski-expected.txt b/tests/regression/dumptest/minkowski-expected.txt
new file mode 100644
index 0000000..ecab5f3
--- /dev/null
+++ b/tests/regression/dumptest/minkowski-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ minkowski(convexity = 0);
+}
diff --git a/tests/regression/dumptest/minkowski-tests-expected.txt b/tests/regression/dumptest/minkowski-tests-expected.txt
new file mode 100644
index 0000000..7435769
--- /dev/null
+++ b/tests/regression/dumptest/minkowski-tests-expected.txt
@@ -0,0 +1,66 @@
+group() {
+ multmatrix([[1, 0, 0, -25], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ minkowski(convexity = 0) {
+ difference() {
+ square(size = [10, 10], center = false);
+ multmatrix([[1, 0, 0, 2], [0, 1, 0, 2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ square(size = [6, 6], center = false);
+ }
+ }
+ circle($fn = 0, $fa = 12, $fs = 1, r = 2);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ minkowski(convexity = 0) {
+ difference() {
+ square(size = [10, 10], center = false);
+ square(size = [5, 5], center = false);
+ }
+ circle($fn = 0, $fa = 12, $fs = 1, r = 5);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 25], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ minkowski(convexity = 0) {
+ square(size = [10, 10], center = false);
+ circle($fn = 0, $fa = 12, $fs = 1, r = 5);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, -25], [0, 1, 0, 25], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ minkowski(convexity = 0) {
+ difference() {
+ cube(size = [10, 10, 5], center = false);
+ multmatrix([[1, 0, 0, 2], [0, 1, 0, 2], [0, 0, 1, -2], [0, 0, 0, 1]]) {
+ cube(size = [6, 6, 10], center = false);
+ }
+ }
+ cylinder($fn = 0, $fa = 12, $fs = 1, h = 1, r1 = 2, r2 = 2, center = false);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 25], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ minkowski(convexity = 0) {
+ difference() {
+ cube(size = [10, 10, 5], center = false);
+ cube(size = [5, 5, 5], center = false);
+ }
+ cylinder($fn = 0, $fa = 12, $fs = 1, h = 5, r1 = 5, r2 = 5, center = false);
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 25], [0, 1, 0, 25], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ group() {
+ minkowski(convexity = 0) {
+ cube(size = [10, 10, 5], center = false);
+ cylinder($fn = 0, $fa = 12, $fs = 1, h = 5, r1 = 5, r2 = 5, center = false);
+ }
+ }
+ }
+}
diff --git a/tests/regression/dumptest/mirror-expected.txt b/tests/regression/dumptest/mirror-expected.txt
new file mode 100644
index 0000000..3ad73cb
--- /dev/null
+++ b/tests/regression/dumptest/mirror-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ multmatrix([[-1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
+}
diff --git a/tests/regression/dumptest/multmatrix-expected.txt b/tests/regression/dumptest/multmatrix-expected.txt
new file mode 100644
index 0000000..87e28e2
--- /dev/null
+++ b/tests/regression/dumptest/multmatrix-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
+}
diff --git a/tests/regression/dumptest/null-polygons-expected.txt b/tests/regression/dumptest/null-polygons-expected.txt
new file mode 100644
index 0000000..bfceaff
--- /dev/null
+++ b/tests/regression/dumptest/null-polygons-expected.txt
@@ -0,0 +1,6 @@
+group() {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 100, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1) {
+ import_dxf(file = "/Users/kintel/code/metalab/checkout/OpenSCAD/openscad-visitor/testdata/scad/null-polygons.dxf", cache = "4c34b4bc.3124", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+ }
+ linear_extrude(file = "/Users/kintel/code/metalab/checkout/OpenSCAD/openscad-visitor/testdata/scad/null-polygons.dxf", cache = "4c34b4bc.3124", layer = "", height = 100, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+}
diff --git a/tests/regression/dumptest/polygon-expected.txt b/tests/regression/dumptest/polygon-expected.txt
new file mode 100644
index 0000000..d04aec9
--- /dev/null
+++ b/tests/regression/dumptest/polygon-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ polygon(points = undef, paths = undef, convexity = 1);
+}
diff --git a/tests/regression/dumptest/polygon-illegal-winding-expected.txt b/tests/regression/dumptest/polygon-illegal-winding-expected.txt
new file mode 100644
index 0000000..3a4c32b
--- /dev/null
+++ b/tests/regression/dumptest/polygon-illegal-winding-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ polyhedron(points = [[0, -10, 60], [0, 10, 60], [0, 10, 0], [0, -10, 0], [60, -10, 60], [60, 10, 60], [10, -10, 50], [10, 10, 50], [10, 10, 30], [10, -10, 30], [30, -10, 50], [30, 10, 50]], triangles = [[0, 2, 3], [0, 1, 2], [0, 4, 5], [0, 5, 1], [5, 4, 2], [2, 4, 3], [6, 8, 9], [6, 7, 8], [6, 10, 11], [6, 11, 7], [10, 8, 11], [10, 9, 8], [0, 3, 9], [9, 0, 6], [10, 6, 0], [0, 4, 10], [3, 9, 10], [3, 10, 4], [1, 7, 11], [1, 11, 5], [1, 7, 8], [1, 8, 2], [2, 8, 11], [2, 11, 5]], convexity = 1);
+}
diff --git a/tests/regression/dumptest/polyhedron-expected.txt b/tests/regression/dumptest/polyhedron-expected.txt
new file mode 100644
index 0000000..c37a529
--- /dev/null
+++ b/tests/regression/dumptest/polyhedron-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ polyhedron(points = undef, triangles = undef, convexity = 1);
+}
diff --git a/tests/regression/dumptest/polyset-reduce-crash-expected.txt b/tests/regression/dumptest/polyset-reduce-crash-expected.txt
new file mode 100644
index 0000000..50253ff
--- /dev/null
+++ b/tests/regression/dumptest/polyset-reduce-crash-expected.txt
@@ -0,0 +1,17 @@
+group() {
+ multmatrix([[0.809017, -0.587785, 0, 0], [0.587785, 0.809017, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ union() {
+ multmatrix([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ polygon(points = [[18.7661, -2.97225], [16.5303, -3.96857], [18.475, -4.43546]], paths = undef, convexity = 1);
+ polygon(points = [[18.7661, -2.97225], [16.7907, -2.65939], [16.5303, -3.96857]], paths = undef, convexity = 1);
+ polygon(points = [[19, 0], [17, 0], [16.7907, -2.65939]], paths = undef, convexity = 1);
+ polygon(points = [[19, 0], [16.7907, -2.65939], [18.7661, -2.97225]], paths = undef, convexity = 1);
+ polygon(points = [[19, 0], [17, 0], [16.7907, 2.65939]], paths = undef, convexity = 1);
+ polygon(points = [[19, 0], [16.7907, 2.65939], [18.7661, 2.97225]], paths = undef, convexity = 1);
+ polygon(points = [[18.7661, 2.97225], [16.7907, 2.65939], [16.5303, 3.96857]], paths = undef, convexity = 1);
+ polygon(points = [[18.7661, 2.97225], [16.5303, 3.96857], [18.475, 4.43546]], paths = undef, convexity = 1);
+ }
+ circle($fn = 0, $fa = 12, $fs = 1, r = 20);
+ }
+ }
+}
diff --git a/tests/regression/dumptest/projection-expected.txt b/tests/regression/dumptest/projection-expected.txt
new file mode 100644
index 0000000..d776c2e
--- /dev/null
+++ b/tests/regression/dumptest/projection-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ projection(cut = false, convexity = 0);
+}
diff --git a/tests/regression/dumptest/projection-tests-expected.txt b/tests/regression/dumptest/projection-tests-expected.txt
new file mode 100644
index 0000000..836c115
--- /dev/null
+++ b/tests/regression/dumptest/projection-tests-expected.txt
@@ -0,0 +1,25 @@
+group() {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 20, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1) {
+ projection(cut = false, convexity = 0) {
+ sphere($fn = 0, $fa = 12, $fs = 1, r = 10);
+ }
+ }
+ multmatrix([[1, 0, 0, 22], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 20, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1) {
+ projection(cut = true, convexity = 0) {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 9], [0, 0, 0, 1]]) {
+ sphere($fn = 0, $fa = 12, $fs = 1, r = 10);
+ }
+ }
+ }
+ }
+ multmatrix([[1, 0, 0, 44], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ linear_extrude(file = "", cache = "0.0", layer = "", height = 20, origin = [ 0 0 ], scale = 1, center = false, convexity = 1, $fn = 0, $fa = 12, $fs = 1) {
+ projection(cut = true, convexity = 0) {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 7], [0, 0, 0, 1]]) {
+ sphere($fn = 0, $fa = 12, $fs = 1, r = 10);
+ }
+ }
+ }
+ }
+}
diff --git a/tests/regression/dumptest/render-expected.txt b/tests/regression/dumptest/render-expected.txt
new file mode 100644
index 0000000..c599c6b
--- /dev/null
+++ b/tests/regression/dumptest/render-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ render(convexity = 1);
+}
diff --git a/tests/regression/dumptest/rotate-expected.txt b/tests/regression/dumptest/rotate-expected.txt
new file mode 100644
index 0000000..87e28e2
--- /dev/null
+++ b/tests/regression/dumptest/rotate-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
+}
diff --git a/tests/regression/dumptest/rotate_extrude-expected.txt b/tests/regression/dumptest/rotate_extrude-expected.txt
new file mode 100644
index 0000000..2d65d35
--- /dev/null
+++ b/tests/regression/dumptest/rotate_extrude-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ rotate_extrude(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+}
diff --git a/tests/regression/dumptest/rotate_extrude-tests-expected.txt b/tests/regression/dumptest/rotate_extrude-tests-expected.txt
new file mode 100644
index 0000000..068d32c
--- /dev/null
+++ b/tests/regression/dumptest/rotate_extrude-tests-expected.txt
@@ -0,0 +1,7 @@
+group() {
+ rotate_extrude(file = "", cache = "0.0", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1) {
+ multmatrix([[1, 0, 0, 20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ circle($fn = 0, $fa = 12, $fs = 1, r = 10);
+ }
+ }
+}
diff --git a/tests/regression/dumptest/scale-expected.txt b/tests/regression/dumptest/scale-expected.txt
new file mode 100644
index 0000000..87e28e2
--- /dev/null
+++ b/tests/regression/dumptest/scale-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
+}
diff --git a/tests/regression/dumptest/sphere-expected.txt b/tests/regression/dumptest/sphere-expected.txt
new file mode 100644
index 0000000..bc8bc7b
--- /dev/null
+++ b/tests/regression/dumptest/sphere-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ sphere($fn = 0, $fa = 12, $fs = 1, r = 1);
+}
diff --git a/tests/regression/dumptest/sphere-tests-expected.txt b/tests/regression/dumptest/sphere-tests-expected.txt
new file mode 100644
index 0000000..a672c23
--- /dev/null
+++ b/tests/regression/dumptest/sphere-tests-expected.txt
@@ -0,0 +1,12 @@
+group() {
+ sphere($fn = 0, $fa = 12, $fs = 1, r = 5);
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 12], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ sphere($fn = 0, $fa = 5, $fs = 0.5, r = 5);
+ }
+ multmatrix([[1, 0, 0, 12], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ sphere($fn = 0, $fa = 12, $fs = 1, r = 6);
+ }
+ multmatrix([[1, 0, 0, 12], [0, 1, 0, 12], [0, 0, 1, 0], [0, 0, 0, 1]]) {
+ sphere($fn = 5, $fa = 12, $fs = 1, r = 6);
+ }
+}
diff --git a/tests/regression/dumptest/square-expected.txt b/tests/regression/dumptest/square-expected.txt
new file mode 100644
index 0000000..a4a24d8
--- /dev/null
+++ b/tests/regression/dumptest/square-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ square(size = [1, 1], center = false);
+}
diff --git a/tests/regression/dumptest/string-test-expected.txt b/tests/regression/dumptest/string-test-expected.txt
new file mode 100644
index 0000000..434cc8f
--- /dev/null
+++ b/tests/regression/dumptest/string-test-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ group();
+}
diff --git a/tests/regression/dumptest/subdiv-expected.txt b/tests/regression/dumptest/subdiv-expected.txt
new file mode 100644
index 0000000..bc40dc2
--- /dev/null
+++ b/tests/regression/dumptest/subdiv-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ subdiv(level = 1, convexity = 0);
+}
diff --git a/tests/regression/dumptest/surface-expected.txt b/tests/regression/dumptest/surface-expected.txt
new file mode 100644
index 0000000..4c9b5b8
--- /dev/null
+++ b/tests/regression/dumptest/surface-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ surface(file = "", center = false);
+}
diff --git a/tests/regression/dumptest/surface-tests-expected.txt b/tests/regression/dumptest/surface-tests-expected.txt
new file mode 100644
index 0000000..9786d85
--- /dev/null
+++ b/tests/regression/dumptest/surface-tests-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ surface(file = "/Users/kintel/code/metalab/checkout/OpenSCAD/openscad-visitor/testdata/scad/surface.dat", center = false);
+}
diff --git a/tests/regression/dumptest/transform-insert-expected.txt b/tests/regression/dumptest/transform-insert-expected.txt
new file mode 100644
index 0000000..758c9e1
--- /dev/null
+++ b/tests/regression/dumptest/transform-insert-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ import_dxf(file = "/Users/kintel/code/OpenSCAD/openscad-visitor/testdata/scad/minimal/transform-insert.dxf", cache = "4e39fca1.4329", layer = "", origin = [ 0 0 ], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 1);
+}
diff --git a/tests/regression/dumptest/translate-expected.txt b/tests/regression/dumptest/translate-expected.txt
new file mode 100644
index 0000000..87e28e2
--- /dev/null
+++ b/tests/regression/dumptest/translate-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);
+}
diff --git a/tests/regression/dumptest/union-expected.txt b/tests/regression/dumptest/union-expected.txt
new file mode 100644
index 0000000..34f53c2
--- /dev/null
+++ b/tests/regression/dumptest/union-expected.txt
@@ -0,0 +1,3 @@
+group() {
+ union();
+}
diff --git a/tests/regression/opencsgtest/2d-3d-expected.png b/tests/regression/opencsgtest/2d-3d-expected.png
new file mode 100644
index 0000000..47418f0
--- /dev/null
+++ b/tests/regression/opencsgtest/2d-3d-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/assign-tests-expected.png b/tests/regression/opencsgtest/assign-tests-expected.png
new file mode 100644
index 0000000..6fe8e10
--- /dev/null
+++ b/tests/regression/opencsgtest/assign-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/background-modifier-expected.png b/tests/regression/opencsgtest/background-modifier-expected.png
new file mode 100644
index 0000000..24149d0
--- /dev/null
+++ b/tests/regression/opencsgtest/background-modifier-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/circle-tests-expected.png b/tests/regression/opencsgtest/circle-tests-expected.png
new file mode 100644
index 0000000..7066eb9
--- /dev/null
+++ b/tests/regression/opencsgtest/circle-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/color-tests-expected.png b/tests/regression/opencsgtest/color-tests-expected.png
new file mode 100644
index 0000000..b2ef8dd
--- /dev/null
+++ b/tests/regression/opencsgtest/color-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/cube-tests-expected.png b/tests/regression/opencsgtest/cube-tests-expected.png
new file mode 100644
index 0000000..8f0a361
--- /dev/null
+++ b/tests/regression/opencsgtest/cube-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/cylinder-tests-expected.png b/tests/regression/opencsgtest/cylinder-tests-expected.png
new file mode 100644
index 0000000..17c10b8
--- /dev/null
+++ b/tests/regression/opencsgtest/cylinder-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/difference-tests-expected.png b/tests/regression/opencsgtest/difference-tests-expected.png
new file mode 100644
index 0000000..d88d98b
--- /dev/null
+++ b/tests/regression/opencsgtest/difference-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/disable-modifier-expected.png b/tests/regression/opencsgtest/disable-modifier-expected.png
new file mode 100644
index 0000000..1e4b471
--- /dev/null
+++ b/tests/regression/opencsgtest/disable-modifier-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/for-nested-tests-expected.png b/tests/regression/opencsgtest/for-nested-tests-expected.png
new file mode 100644
index 0000000..c9cdb74
--- /dev/null
+++ b/tests/regression/opencsgtest/for-nested-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/for-tests-expected.png b/tests/regression/opencsgtest/for-tests-expected.png
new file mode 100644
index 0000000..968659d
--- /dev/null
+++ b/tests/regression/opencsgtest/for-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/highlight-modifier-expected.png b/tests/regression/opencsgtest/highlight-modifier-expected.png
new file mode 100644
index 0000000..78d0309
--- /dev/null
+++ b/tests/regression/opencsgtest/highlight-modifier-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/hull2-tests-expected.png b/tests/regression/opencsgtest/hull2-tests-expected.png
new file mode 100644
index 0000000..66ee6b2
--- /dev/null
+++ b/tests/regression/opencsgtest/hull2-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/import_dxf-tests-expected.png b/tests/regression/opencsgtest/import_dxf-tests-expected.png
new file mode 100644
index 0000000..6e568c7
--- /dev/null
+++ b/tests/regression/opencsgtest/import_dxf-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/intersection-tests-expected.png b/tests/regression/opencsgtest/intersection-tests-expected.png
new file mode 100644
index 0000000..fc23560
--- /dev/null
+++ b/tests/regression/opencsgtest/intersection-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/intersection_for-tests-expected.png b/tests/regression/opencsgtest/intersection_for-tests-expected.png
new file mode 100644
index 0000000..08c8e06
--- /dev/null
+++ b/tests/regression/opencsgtest/intersection_for-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/linear_extrude-tests-expected.png b/tests/regression/opencsgtest/linear_extrude-tests-expected.png
new file mode 100644
index 0000000..579479e
--- /dev/null
+++ b/tests/regression/opencsgtest/linear_extrude-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/minkowski2-tests-expected.png b/tests/regression/opencsgtest/minkowski2-tests-expected.png
new file mode 100644
index 0000000..062f1ed
--- /dev/null
+++ b/tests/regression/opencsgtest/minkowski2-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/minkowski3-tests-expected.png b/tests/regression/opencsgtest/minkowski3-tests-expected.png
new file mode 100644
index 0000000..1f0d572
--- /dev/null
+++ b/tests/regression/opencsgtest/minkowski3-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/polygon-tests-expected.png b/tests/regression/opencsgtest/polygon-tests-expected.png
new file mode 100644
index 0000000..4d88973
--- /dev/null
+++ b/tests/regression/opencsgtest/polygon-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/projection-tests-expected.png b/tests/regression/opencsgtest/projection-tests-expected.png
new file mode 100644
index 0000000..8239d3d
--- /dev/null
+++ b/tests/regression/opencsgtest/projection-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/render-tests-expected.png b/tests/regression/opencsgtest/render-tests-expected.png
new file mode 100644
index 0000000..40a1703
--- /dev/null
+++ b/tests/regression/opencsgtest/render-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/root-modifier-expected.png b/tests/regression/opencsgtest/root-modifier-expected.png
new file mode 100644
index 0000000..1e4b471
--- /dev/null
+++ b/tests/regression/opencsgtest/root-modifier-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/rotate_extrude-tests-expected.png b/tests/regression/opencsgtest/rotate_extrude-tests-expected.png
new file mode 100644
index 0000000..96452e1
--- /dev/null
+++ b/tests/regression/opencsgtest/rotate_extrude-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/sphere-tests-expected.png b/tests/regression/opencsgtest/sphere-tests-expected.png
new file mode 100644
index 0000000..06161f3
--- /dev/null
+++ b/tests/regression/opencsgtest/sphere-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/square-tests-expected.png b/tests/regression/opencsgtest/square-tests-expected.png
new file mode 100644
index 0000000..4f9db9d
--- /dev/null
+++ b/tests/regression/opencsgtest/square-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/surface-tests-expected.png b/tests/regression/opencsgtest/surface-tests-expected.png
new file mode 100644
index 0000000..2655afb
--- /dev/null
+++ b/tests/regression/opencsgtest/surface-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/transform-tests-expected.png b/tests/regression/opencsgtest/transform-tests-expected.png
new file mode 100644
index 0000000..9c763ba
--- /dev/null
+++ b/tests/regression/opencsgtest/transform-tests-expected.png
Binary files differ
diff --git a/tests/regression/opencsgtest/union-tests-expected.png b/tests/regression/opencsgtest/union-tests-expected.png
new file mode 100644
index 0000000..caa1467
--- /dev/null
+++ b/tests/regression/opencsgtest/union-tests-expected.png
Binary files differ
diff --git a/tests/test_cmdline_tool.py b/tests/test_cmdline_tool.py
new file mode 100755
index 0000000..b8a0d07
--- /dev/null
+++ b/tests/test_cmdline_tool.py
@@ -0,0 +1,163 @@
+#!/usr/bin/env python
+
+#
+# Regression test driver for cmd-line tools
+#
+# Usage: test_cmdline_tool.py [<options>] <tool> <arguments>
+#
+# If the -g option is given or the TEST_GENERATE environment variable is set to 1,
+# *-expected.<suffix> files will be generated instead of running the tests.
+#
+# Any generated output is written to the file `basename <argument`-actual.<suffix>
+# Any warning or errors are written to stderr.
+#
+# Returns 0 on passed test
+# 1 on error
+# 2 on invalid cmd-line options
+#
+# Author: Marius Kintel <marius@kintel.net>
+#
+
+import sys
+import os
+import glob
+import subprocess
+import re
+import getopt
+
+def initialize_environment():
+ if not options.generate: options.generate = bool(os.getenv("TEST_GENERATE"))
+ return True
+
+def init_expected_filename(testname, cmd):
+ global expecteddir, expectedfilename
+ expecteddir = os.path.join(options.regressiondir, os.path.split(cmd)[1])
+ expectedfilename = os.path.join(expecteddir, testname + "-expected." + options.suffix)
+
+def verify_test(testname, cmd):
+ global expectedfilename
+ if not options.generate:
+ if not os.path.isfile(expectedfilename):
+ print >> sys.stderr, "Error: test '%s' is missing expected output in %s" % (testname, expectedfilename)
+ return False
+ return True
+
+def execute_and_redirect(cmd, params, outfile):
+ proc = subprocess.Popen([cmd] + params, stdout=outfile)
+ retval = proc.wait()
+ return retval
+
+def get_normalized_text(filename):
+ text = open(filename).read()
+ return text.strip("\r\n").replace("\r\n", "\n") + "\n"
+
+def compare_text(expected, actual):
+ return get_normalized_text(expected) == get_normalized_text(actual)
+
+def compare_default(resultfilename):
+ if not compare_text(expectedfilename, resultfilename):
+ execute_and_redirect("diff", [expectedfilename, resultfilename], sys.stderr)
+ return False
+ return True
+
+def compare_png(resultfilename):
+ if execute_and_redirect("diff", [expectedfilename, resultfilename], sys.stderr) != 0:
+ return False
+ return True
+
+def compare_with_expected(resultfilename):
+ if not options.generate:
+ if "compare_" + options.suffix in globals(): return globals()["compare_" + options.suffix](resultfilename)
+ else: return compare_default(resultfilename)
+ return True
+
+def run_test(testname, cmd, args):
+ cmdname = os.path.split(options.cmd)[1]
+
+ outputdir = os.path.join(os.getcwd(), cmdname + "-output")
+ actualfilename = os.path.join(outputdir, testname + "-actual." + options.suffix)
+
+ if options.generate:
+ if not os.path.exists(expecteddir): os.makedirs(expecteddir)
+ outputname = expectedfilename
+ else:
+ if not os.path.exists(outputdir): os.makedirs(outputdir)
+ outputname = actualfilename
+ outfile = open(outputname, "wb")
+ try:
+ proc = subprocess.Popen([cmd] + args, stdout=outfile, stderr=subprocess.PIPE)
+ errtext = proc.communicate()[1]
+ if errtext != None and len(errtext) > 0:
+ print >> sys.stderr, "Error output: " + errtext
+ outfile.close()
+ if proc.returncode != 0:
+ print >> sys.stderr, "Error: %s failed with return code %d" % (cmdname, proc.returncode)
+ return None
+
+ return outputname
+ except OSError, err:
+ print >> sys.stderr, "Error: %s \"%s\"" % (err.strerror, cmd)
+ return None
+
+class Options:
+ def __init__(self):
+ self.__dict__['options'] = {}
+ def __setattr__(self, name, value):
+ self.options[name] = value
+ def __getattr__(self, name):
+ return self.options[name]
+
+def usage():
+ print >> sys.stderr, "Usage: " + sys.argv[0] + " [<options>] <cmdline-tool> <argument>"
+ print >> sys.stderr, "Options:"
+ print >> sys.stderr, " -g, --generate Generate expected output for the given tests"
+ 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"
+
+if __name__ == '__main__':
+ # Handle command-line arguments
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "gs:t:", ["generate", "suffix=", "test="])
+ except getopt.GetoptError, err:
+ usage()
+ sys.exit(2)
+
+ global options
+ options = Options()
+ options.regressiondir = os.path.join(os.path.split(sys.argv[0])[0], "regression")
+ options.generate = False
+ options.suffix = "txt"
+ for o, a in opts:
+ if o in ("-g", "--generate"): options.generate = True
+ elif o in ("-s", "--suffix"):
+ if a[0] == '.': options.suffix = a[1:]
+ else: options.suffix = a
+ elif o in ("-t", "--test"):
+ options.testname = a
+
+ # <cmdline-tool> and <argument>
+ if len(args) < 2:
+ usage()
+ sys.exit(2)
+ options.cmd = args[0]
+
+ # If only one test file, we can usually deduct the test name from the file
+ if len(args) == 2:
+ basename = os.path.splitext(args[1])[0]
+ path, options.testname = os.path.split(basename)
+
+ if not hasattr(options, "testname"):
+ print >> sys.stderr, "Test name cannot be deducted from arguments. Specify test name using the -t option"
+ sys.exit(2)
+
+ # Initialize and verify run-time environment
+ if not initialize_environment(): sys.exit(1)
+
+ init_expected_filename(options.testname, options.cmd)
+
+ # Verify test environment
+ verification = verify_test(options.testname, options.cmd)
+
+ resultfile = run_test(options.testname, options.cmd, args[1:])
+
+ if not verification or not compare_with_expected(resultfile): exit(1)
contact: Jan Huwald // Impressum