diff options
Diffstat (limited to 'tests')
122 files changed, 2574 insertions, 0 deletions
| diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..8d409f8 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,193 @@ +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/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/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/CSGTermEvaluator.cc ../src/CGALEvaluator.cc +                        ../src/PolySetCGALEvaluator.cc ../src/qhash.cc ../src/nef2dxf.cc +                        ../src/cgaladv_minkowski2.cc ../src/cgaladv_minkowski3.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}) + +# +# opencsgtest +# +add_executable(opencsgtest opencsgtest.cc OffscreenView.cc OffscreenContext.mm +                           ../src/opencsgrenderer.cc ../src/throwntogetherrenderer.cc ../src/CSGTermEvaluator.cc ../src/CGALEvaluator.cc +                           ../src/PolySetCGALEvaluator.cc ../src/qhash.cc ../src/nef2dxf.cc +                           ../src/cgaladv_minkowski2.cc ../src/cgaladv_minkowski3.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 ${SCAD_FILES}) +# Add csgtermtest tests to CTest +add_cmdline_test(csgtermtest txt ${SCAD_FILES}) +# Add cgaltest tests to CTest +LIST(APPEND CGALTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/cube.scad) +LIST(APPEND CGALTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/sphere.scad) +LIST(APPEND CGALTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/cylinder.scad) +LIST(APPEND CGALTEST_FILES ${CMAKE_SOURCE_DIR}/../examples/example001.scad) +add_cmdline_test(cgaltest stl ${CGALTEST_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..bccb20a --- /dev/null +++ b/tests/FindGLEW.cmake @@ -0,0 +1,44 @@ +# +# 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}) +	FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h +                PATHS +                ${GLEW_DIR}/include +                NO_DEFAULT_PATH +		DOC "The directory where GL/glew.h resides") +	FIND_LIBRARY( GLEW_LIBRARY +		NAMES GLEW glew +		PATHS +                ${GLEW_DIR}/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) + +MARK_AS_ADVANCED( GLEW_FOUND ) 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..c8d0df7 --- /dev/null +++ b/tests/OffscreenContext.mm @@ -0,0 +1,204 @@ +#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; +  } +  CFIndex                 fileImageIndex = 1; +  CFMutableDictionaryRef  fileDict       = NULL; +  CFStringRef             fileUTType     = kUTTypeJPEG; +  // Create an image destination opaque reference for authoring an image file +  CGImageDestinationRef imageDest = CGImageDestinationCreateWithURL(fileURL,  +                                                                    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(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..3740c69 --- /dev/null +++ b/tests/OffscreenView.cc @@ -0,0 +1,232 @@ +#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(true), showfaces(true), showedges(false), viewer_distance(500) +{ +	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); +	setupPerspective(); +} + +void OffscreenView::setupPerspective() +{ +	glMatrixMode(GL_PROJECTION); +	glLoadIdentity(); +	glFrustum(-w_h_ratio, +w_h_ratio, -(1/w_h_ratio), +(1/w_h_ratio), +10.0, +FAR_FAR_AWAY); +} + +void OffscreenView::setupOrtho(double distance, bool offset) +{ +	glMatrixMode(GL_PROJECTION); +	glLoadIdentity(); +	if(offset) +		glTranslated(-0.8, -0.8, 0); +	double l = distance/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(viewer_distance); + +	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(0.0, -viewer_distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); + +//	glTranslated(object_trans_x, object_trans_y, object_trans_z); + +	// glRotated(object_rot_x, 1.0, 0.0, 0.0); +	// glRotated(object_rot_y, 0.0, 1.0, 0.0); +	// glRotated(object_rot_z, 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 = viewer_distance/10; +		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); +} diff --git a/tests/OffscreenView.h b/tests/OffscreenView.h new file mode 100644 index 0000000..52ee3af --- /dev/null +++ b/tests/OffscreenView.h @@ -0,0 +1,34 @@ +#ifndef OFFSCREENVIEW_H_ +#define OFFSCREENVIEW_H_ + +#include "OffscreenContext.h" +#include <stdint.h> + +class OffscreenView +{ +public: +	OffscreenView(size_t width, size_t height); +	~OffscreenView(); +	void setRenderer(class Renderer* r); + +	void initializeGL(); +	void resizeGL(int w, int h); +	void setupPerspective(); +	void setupOrtho(double distance,bool offset=false); +	void paintGL(); +	bool save(const char *filename); + +	GLint shaderinfo[11]; +	OffscreenContext *ctx; +private: +	Renderer *renderer; +	double w_h_ratio; + +	bool orthomode; +	bool showaxes; +	bool showfaces; +	bool showedges; +	float viewer_distance; +}; + +#endif diff --git a/tests/cgaltest.cc b/tests/cgaltest.cc new file mode 100644 index 0000000..df03a43 --- /dev/null +++ b/tests/cgaltest.cc @@ -0,0 +1,179 @@ +/* + *  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 "context.h" +#include "value.h" +#include "export.h" +#include "builtin.h" +#include "Tree.h" +#include "CGALEvaluator.h" +#include "PolySetCGALEvaluator.h" + +#include <QApplication> +#include <QFile> +#include <QDir> +#include <QSet> +#include <QTextStream> +#include <getopt.h> +#include <iostream> + +QString commandline_commands; +const char *make_command = NULL; +QSet<QString> dependencies; +QString currentdir; +QString examplesdir; +QString librarydir; + +using std::string; + +void handle_dep(QString filename) +{ +	if (filename.startsWith("/")) +		dependencies.insert(filename); +	else +		dependencies.insert(QDir::currentPath() + QString("/") + filename); +	if (!QFile(filename).exists() && make_command) { +		char buffer[4096]; +		snprintf(buffer, 4096, "%s '%s'", make_command, filename.replace("'", "'\\''").toUtf8().data()); +		system(buffer); // FIXME: Handle error +	} +} + +// 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(); +} + +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; +	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 { +		QString text; +		char buffer[513]; +		int ret; +		while ((ret = fread(buffer, 1, 512, fp)) > 0) { +			buffer[ret] = 0; +			text += buffer; +		} +		fclose(fp); +		root_module = parse((text+commandline_commands).toAscii().data(), 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); + +	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()); +	QTextStream outstream(stdout); +	export_stl(&N, outstream, NULL); + +	destroy_builtin_functions(); +	destroy_builtin_modules(); + +	return 0; +} diff --git a/tests/csgtermtest.cc b/tests/csgtermtest.cc new file mode 100644 index 0000000..944a67a --- /dev/null +++ b/tests/csgtermtest.cc @@ -0,0 +1,181 @@ +/* + *  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 "CSGTermRenderer.h" +#include "CSGTextCache.h" +#include "openscad.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> + +using std::cout; + +QString commandline_commands; +const char *make_command = NULL; +QSet<QString> dependencies; +QString currentdir; +QString examplesdir; +QString librarydir; + +void handle_dep(QString filename) +{ +	if (filename.startsWith("/")) +		dependencies.insert(filename); +	else +		dependencies.insert(QDir::currentPath() + QString("/") + filename); +	if (!QFile(filename).exists() && make_command) { +		char buffer[4096]; +		snprintf(buffer, 4096, "%s '%s'", make_command, filename.replace("'", "'\\''").toUtf8().data()); +		system(buffer); // FIXME: Handle error +	} +} + +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 { +		QString text; +		char buffer[513]; +		int ret; +		while ((ret = fread(buffer, 1, 512, fp)) > 0) { +			buffer[ret] = 0; +			text += buffer; +		} +		fclose(fp); +		root_module = parse((text+commandline_commands).toAscii().data(), 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"; + +	CSGTermRenderer renderer(tree); +	CSGTerm *root_term = renderer.renderCSGTerm(*root_node, NULL, NULL); +	 +	// cout << "Stored terms: " << renderer.stored_term.size() << "\n"; +	// for (map<int, class CSGTerm*>::iterator iter = renderer.stored_term.begin(); +	// 		 iter != renderer.stored_term.end(); +	// 		 iter++) { +	// 	cout << iter->first << ":" << (iter->second ? iter->second->label : "NULL") << "\n"; +	// } + +	// if (renderer.background) cout << "Background terms: " << renderer.background->size() << "\n"; +	// if (renderer.highlights) cout << "Highlights terms: " << renderer.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..c259e2d --- /dev/null +++ b/tests/csgtexttest.cc @@ -0,0 +1,170 @@ +/* + *  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 "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> + +QString commandline_commands; +const char *make_command = NULL; +QSet<QString> dependencies; +QString currentdir; +QString examplesdir; +QString librarydir; + +void handle_dep(QString filename) +{ +	if (filename.startsWith("/")) +		dependencies.insert(filename); +	else +		dependencies.insert(QDir::currentPath() + QString("/") + filename); +	if (!QFile(filename).exists() && make_command) { +		char buffer[4096]; +		snprintf(buffer, 4096, "%s '%s'", make_command, filename.replace("'", "'\\''").toUtf8().data()); +		system(buffer); // FIXME: Handle error +	} +} + +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 { +		QString text; +		char buffer[513]; +		int ret; +		while ((ret = fread(buffer, 1, 512, fp)) > 0) { +			buffer[ret] = 0; +			text += buffer; +		} +		fclose(fp); +		root_module = parse((text+commandline_commands).toAscii().data(), 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..3f6068a --- /dev/null +++ b/tests/dumptest.cc @@ -0,0 +1,167 @@ +/* + *  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 "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> + +using std::string; + +QString commandline_commands; +const char *make_command = NULL; +QSet<QString> dependencies; +QString currentdir; +QString examplesdir; +QString librarydir; + +void handle_dep(QString filename) +{ +	if (filename.startsWith("/")) +		dependencies.insert(filename); +	else +		dependencies.insert(QDir::currentPath() + QString("/") + filename); +	if (!QFile(filename).exists() && make_command) { +		char buffer[4096]; +		snprintf(buffer, 4096, "%s '%s'", make_command, filename.replace("'", "'\\''").toUtf8().data()); +		system(buffer); // FIXME: Handle error +	} +} + +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 { +		QString text; +		char buffer[513]; +		int ret; +		while ((ret = fread(buffer, 1, 512, fp)) > 0) { +			buffer[ret] = 0; +			text += buffer; +		} +		fclose(fp); +		root_module = parse((text+commandline_commands).toAscii().data(), 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..7da15e8 --- /dev/null +++ b/tests/opencsgtest.cc @@ -0,0 +1,243 @@ +#include <GL/glew.h> +#include "openscad.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> + +using std::cerr; +using std::cout; + +QString commandline_commands; +QString librarydir; +QSet<QString> dependencies; +const char *make_command = NULL; + +void handle_dep(QString filename) +{ +	if (filename.startsWith("/")) +		dependencies.insert(filename); +	else +		dependencies.insert(QDir::currentPath() + QString("/") + filename); +	if (!QFile(filename).exists() && make_command) { +		char buffer[4096]; +		snprintf(buffer, 4096, "%s '%s'", make_command, filename.replace("'", "'\\''").toUtf8().data()); +		system(buffer); // FIXME: Handle error +	} +} + +// static void renderfunc(void *vp) +// { +// 	glClearColor(1.0, 0.0, 0.0, 0.0); +// 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); +// } + +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; +}; + +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; +	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 { +		QString text; +		char buffer[513]; +		int ret; +		while ((ret = fread(buffer, 1, 512, fp)) > 0) { +			buffer[ret] = 0; +			text += buffer; +		} +		fclose(fp); +		root_module = parse((text+commandline_commands).toAscii().data(), 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); + +	QHash<std::string, CGAL_Nef_polyhedron> cache; +	CGALEvaluator cgalevaluator(cache, tree); +	PolySetCGALEvaluator psevaluator(cgalevaluator); +	CSGTermEvaluator evaluator(tree); +	CSGTerm *root_raw_term = evaluator.evaluateCSGTerm(*root_node, NULL, NULL); + +	if (!root_raw_term) { +		cerr << "Error: CSG generation failed! (no top level object found)\n"; +		return 1; +	} + +	CsgInfo csgInfo; +	csgInfo.root_norm_term = root_raw_term->link(); +		 +	// CSG normalization +	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); +	 +	if (csgInfo.highlight_terms.size() > 0) { +		cerr << "Compiling highlights (" << "  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); + +	glewInit(); +	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"; +	} + +	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("out.png"); +	 +	destroy_builtin_functions(); +	destroy_builtin_modules(); + +	return 0; +} diff --git a/tests/regression/csgtexttest/allmodules-expected.txt b/tests/regression/csgtexttest/allmodules-expected.txt new file mode 100644 index 0000000..722315b --- /dev/null +++ b/tests/regression/csgtexttest/allmodules-expected.txt @@ -0,0 +1 @@ +group1(minkowski2+glide3+subdiv4+group5+group5+group5+intersection_for8+group5+union10+difference11+intersection12+linear_extrude+linear_extrude+rotate_extrude+rotate_extrude+import_stl+import_off+import_dxf+group5+cube+sphere+cylinder+polyhedron+square+circle+polygon+projection+render29+surface+transform31+transform31+transform33+transform31+transform31+transform31) 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..80024d2 --- /dev/null +++ b/tests/regression/csgtexttest/color-expected.txt @@ -0,0 +1 @@ +group1(transform2) 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/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_dxf-expected.txt b/tests/regression/csgtexttest/import_dxf-expected.txt new file mode 100644 index 0000000..ffb96fc --- /dev/null +++ b/tests/regression/csgtexttest/import_dxf-expected.txt @@ -0,0 +1 @@ +group1(import_dxf) diff --git a/tests/regression/csgtexttest/import_off-expected.txt b/tests/regression/csgtexttest/import_off-expected.txt new file mode 100644 index 0000000..8a3bafa --- /dev/null +++ b/tests/regression/csgtexttest/import_off-expected.txt @@ -0,0 +1 @@ +group1(import_off) diff --git a/tests/regression/csgtexttest/import_stl-expected.txt b/tests/regression/csgtexttest/import_stl-expected.txt new file mode 100644 index 0000000..47c4707 --- /dev/null +++ b/tests/regression/csgtexttest/import_stl-expected.txt @@ -0,0 +1 @@ +group1(import_stl) 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..ffb96fc --- /dev/null +++ b/tests/regression/csgtexttest/transform-insert-expected.txt @@ -0,0 +1 @@ +group1(import_dxf) 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/allmodules-expected.txt b/tests/regression/dumptest/allmodules-expected.txt new file mode 100644 index 0000000..b51fae3 --- /dev/null +++ b/tests/regression/dumptest/allmodules-expected.txt @@ -0,0 +1,38 @@ +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_stl(file = "", cache = "0.0", convexity = 1); +	import_off(file = "", cache = "0.0", convexity = 1); +	import_dxf(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]]); +	multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 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..87e28e2 --- /dev/null +++ b/tests/regression/dumptest/color-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/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_dxf-expected.txt b/tests/regression/dumptest/import_dxf-expected.txt new file mode 100644 index 0000000..08238d2 --- /dev/null +++ b/tests/regression/dumptest/import_dxf-expected.txt @@ -0,0 +1,3 @@ +group() { +	import_dxf(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..51293c9 --- /dev/null +++ b/tests/regression/dumptest/import_off-expected.txt @@ -0,0 +1,3 @@ +group() { +	import_off(file = "", cache = "0.0", convexity = 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..2da7d35 --- /dev/null +++ b/tests/regression/dumptest/import_stl-expected.txt @@ -0,0 +1,3 @@ +group() { +	import_stl(file = "", cache = "0.0", convexity = 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..7755901 --- /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 = "4c34b4bc.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/test_cmdline_tool.py b/tests/test_cmdline_tool.py new file mode 100755 index 0000000..8fe4890 --- /dev/null +++ b/tests/test_cmdline_tool.py @@ -0,0 +1,154 @@ +#!/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_with_expected(resultfilename): +    if not options.generate: +        if not compare_text(expectedfilename, resultfilename):  +            execute_and_redirect("diff", [expectedfilename, resultfilename], sys.stderr) +            return False +    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 = "" +            else: options.suffix = "." +            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) | 
