diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CGALEvaluator.cc | 9 | ||||
-rw-r--r-- | src/Camera.h | 13 | ||||
-rw-r--r-- | src/GLView.cc | 3 | ||||
-rw-r--r-- | src/MainWindow.h | 4 | ||||
-rw-r--r-- | src/OpenCSGRenderer.cc | 2 | ||||
-rw-r--r-- | src/PlatformUtils.cc | 81 | ||||
-rw-r--r-- | src/PlatformUtils.h | 2 | ||||
-rw-r--r-- | src/QGLView.cc | 11 | ||||
-rw-r--r-- | src/context.cc | 15 | ||||
-rw-r--r-- | src/control.cc | 1 | ||||
-rw-r--r-- | src/export.h | 1 | ||||
-rw-r--r-- | src/export_png.cc | 44 | ||||
-rw-r--r-- | src/imageutils-lodepng.cc | 7 | ||||
-rw-r--r-- | src/import.cc | 4 | ||||
-rw-r--r-- | src/mainwin.cc | 47 | ||||
-rw-r--r-- | src/mathc99.cc | 6 | ||||
-rw-r--r-- | src/mathc99.h | 1 | ||||
-rw-r--r-- | src/module.cc | 4 | ||||
-rw-r--r-- | src/openscad.cc | 707 | ||||
-rw-r--r-- | src/parser.y | 666 | ||||
-rw-r--r-- | src/parsersettings.cc | 1 | ||||
-rw-r--r-- | src/svg.cc | 110 | ||||
-rw-r--r-- | src/version_check.h | 3 |
23 files changed, 1017 insertions, 725 deletions
diff --git a/src/CGALEvaluator.cc b/src/CGALEvaluator.cc index adaec4a..ec01315 100644 --- a/src/CGALEvaluator.cc +++ b/src/CGALEvaluator.cc @@ -216,7 +216,7 @@ CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node) bbox_size.push_back( bb.ymax()-bb.ymin() ); bbox_size.push_back( bb.zmax()-bb.zmin() ); int newsizemax_index = 0; - for (int i=0;i<3;i++) { + for (int i=0;i<N.dim;i++) { if (node.newsize[i]) { if (bbox_size[i]==NT3(0)) { PRINT("WARNING: Resize in direction normal to flat object is not implemented"); @@ -229,8 +229,11 @@ CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node) newsizemax_index = i; } } - NT3 autoscale = NT3( node.newsize[ newsizemax_index ] ) / bbox_size[ newsizemax_index ]; - for (int i=0;i<3;i++) { + + NT3 autoscale = NT3( 1 ); + if ( node.newsize[ newsizemax_index ] != 0 ) + autoscale = NT3( node.newsize[ newsizemax_index ] ) / bbox_size[ newsizemax_index ]; + for (int i=0;i<N.dim;i++) { if (node.autosize[i] && node.newsize[i]==0) scale[i] = autoscale; } diff --git a/src/Camera.h b/src/Camera.h index dfc71f8..6079672 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -47,7 +47,8 @@ public: projection = Camera::PERSPECTIVE; } - void setup( std::vector<double> params ) { + void setup( std::vector<double> params ) + { if ( params.size() == 7 ) { type = Camera::GIMBAL; object_trans << params[0], params[1], params[2]; @@ -62,6 +63,16 @@ public: } } + void gimbalDefaultTranslate() + { // match the GUI viewport numbers (historical reasons) + object_trans.x() *= -1; + object_trans.y() *= -1; + object_trans.z() *= -1; + object_rot.x() = fmodf(360 - object_rot.x() + 90, 360 ); + object_rot.y() = fmodf(360 - object_rot.y(), 360); + object_rot.z() = fmodf(360 - object_rot.z(), 360); + } + // Vectorcam Eigen::Vector3d eye; Eigen::Vector3d center; // (aka 'target') diff --git a/src/GLView.cc b/src/GLView.cc index b4fb8d6..1cfe82c 100644 --- a/src/GLView.cc +++ b/src/GLView.cc @@ -2,6 +2,7 @@ #include "stdio.h" #include "rendersettings.h" +#include "mathc99.h" #ifdef _WIN32 #include <GL/wglew.h> @@ -459,7 +460,7 @@ void GLView::showAxes() void GLView::showCrosshairs() { - // FIXME: this might not work with Vector camera + // FIXME: this might not work with Vector camera // FIXME: Crosshairs and axes are lighted, this doesn't make sense and causes them // to change color based on view orientation. glLineWidth(3); diff --git a/src/MainWindow.h b/src/MainWindow.h index 79e2080..4f88fbf 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -54,6 +54,7 @@ public: std::vector<shared_ptr<CSGTerm> > background_terms; CSGChain *background_chain; QString last_compiled_doc; + static QString qexamplesdir; static const int maxRecentFiles = 10; QAction *actionRecentFile[maxRecentFiles]; @@ -134,6 +135,7 @@ private slots: void actionFlushCaches(); public: + static void setExamplesDir(const QString &dir) { MainWindow::qexamplesdir = dir; } void viewModeActionsUncheck(); void setCurrentOutput(); void clearCurrentOutput(); @@ -201,7 +203,7 @@ public: static void unlock() { gui_locked--; } private: - static unsigned int gui_locked; + static unsigned int gui_locked; }; #endif diff --git a/src/OpenCSGRenderer.cc b/src/OpenCSGRenderer.cc index b4acf82..e65a259 100644 --- a/src/OpenCSGRenderer.cc +++ b/src/OpenCSGRenderer.cc @@ -77,8 +77,8 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo, std::vector<OpenCSG::Primitive*> primitives; size_t j = 0; for (size_t i = 0;; i++) { - const CSGChainObject &i_obj = chain->objects[i]; bool last = i == chain->objects.size(); + const CSGChainObject &i_obj = last ? chain->objects[i-1] : chain->objects[i]; if (last || i_obj.type == CSGTerm::TYPE_UNION) { if (j+1 != i) { OpenCSG::render(primitives); diff --git a/src/PlatformUtils.cc b/src/PlatformUtils.cc index 5dd007d..5059b78 100644 --- a/src/PlatformUtils.cc +++ b/src/PlatformUtils.cc @@ -38,3 +38,84 @@ std::string PlatformUtils::libraryPath() } return boosty::stringy( path ); } + +#include "version_check.h" +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +#ifdef ENABLE_CGAL +#include "cgal.h" +#include <boost/algorithm/string.hpp> +#if defined(__GNUG__) +#define GCC_INT_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 ) +#if GCC_INT_VERSION > 40600 || defined(__clang__) +#include <cxxabi.h> +#define __openscad_info_demangle__ 1 +#endif // GCC_INT_VERSION +#endif // GNUG +#endif // ENABLE_CGAL + +std::string PlatformUtils::info() +{ + std::stringstream s; + +#if defined(__GNUG__) && !defined(__clang__) + std::string compiler_info( "GCC " + std::string(TOSTRING(__VERSION__)) ); +#elif defined(_MSC_VER) + std::string compiler_info( "MSVC " + std::string(TOSTRING(_MSC_FULL_VER)) ); +#elif defined(__clang__) + std::string compiler_info( "Clang " + std::string(TOSTRING(__clang_version__)) ); +#else + std::string compiler_info( "unknown compiler" ); +#endif + +#if defined( __MINGW64__ ) + std::string mingwstatus("MingW64"); +#elif defined( __MINGW32__ ) + std::string mingwstatus("MingW32"); +#else + std::string mingwstatus("No"); +#endif + +#ifndef OPENCSG_VERSION_STRING +#define OPENCSG_VERSION_STRING "unknown, <1.3.2" +#endif + +#ifdef QT_VERSION + std::string qtVersion = qVersion(); +#else + std::string qtVersion = "Qt disabled"; +#endif + +#ifdef ENABLE_CGAL + std::string cgal_3d_kernel = typeid(CGAL_Kernel3).name(); + std::string cgal_2d_kernel = typeid(CGAL_Kernel2).name(); + std::string cgal_2d_kernelEx = typeid(CGAL_ExactKernel2).name(); +#if defined(__openscad_info_demangle__) + int status; + cgal_3d_kernel = std::string( abi::__cxa_demangle( cgal_3d_kernel.c_str(), 0, 0, &status ) ); + cgal_2d_kernel = std::string( abi::__cxa_demangle( cgal_2d_kernel.c_str(), 0, 0, &status ) ); + cgal_2d_kernelEx = std::string( abi::__cxa_demangle( cgal_2d_kernelEx.c_str(), 0, 0, &status ) ); +#endif // demangle + boost::replace_all( cgal_3d_kernel, "CGAL::", "" ); + boost::replace_all( cgal_2d_kernel, "CGAL::", "" ); + boost::replace_all( cgal_2d_kernelEx, "CGAL::", "" ); +#else // ENABLE_CGAL + std::string cgal_3d_kernel = ""; + std::string cgal_2d_kernel = ""; + std::string cgal_2d_kernelEx = ""; +#endif // ENABLE_CGAL + + s << "OpenSCAD Version: " << TOSTRING(OPENSCAD_VERSION) + << "\nCompiler, build date: " << compiler_info << ", " << __DATE__ + << "\nBoost version: " << BOOST_LIB_VERSION + << "\nEigen version: " << EIGEN_WORLD_VERSION << "." << EIGEN_MAJOR_VERSION << "." << EIGEN_MINOR_VERSION + << "\nCGAL version, kernels: " << TOSTRING(CGAL_VERSION) << ", " << cgal_3d_kernel << ", " << cgal_2d_kernel << ", " << cgal_2d_kernelEx + << "\nOpenCSG version: " << OPENCSG_VERSION_STRING + << "\nQt version: " << qtVersion + << "\nMingW build: " << mingwstatus + << "\nOPENSCADPATH: " << getenv("OPENSCADPATH") + ; + return s.str(); +} + diff --git a/src/PlatformUtils.h b/src/PlatformUtils.h index 089b3ca..18dd5fa 100644 --- a/src/PlatformUtils.h +++ b/src/PlatformUtils.h @@ -8,7 +8,7 @@ namespace PlatformUtils { std::string documentsPath(); std::string libraryPath(); bool createLibraryPath(); - + std::string info(); } #endif diff --git a/src/QGLView.cc b/src/QGLView.cc index b23ba8e..8aaeaf2 100644 --- a/src/QGLView.cc +++ b/src/QGLView.cc @@ -147,13 +147,18 @@ void QGLView::resizeGL(int w, int h) void QGLView::paintGL() { - GLView::gimbalCamPaintGL(); + GLView::gimbalCamPaintGL(); if (statusLabel) { QString msg; + + Camera nc( cam ); + nc.gimbalDefaultTranslate(); msg.sprintf("Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], distance = %.2f", - -cam.object_trans.x(), -cam.object_trans.y(), -cam.object_trans.z(), - fmodf(360 - cam.object_rot.x() + 90, 360), fmodf(360 - cam.object_rot.y(), 360), fmodf(360 - cam.object_rot.z(), 360), cam.viewer_distance); + nc.object_trans.x(), nc.object_trans.y(), nc.object_trans.z(), + nc.object_rot.x(), nc.object_rot.y(), nc.object_rot.z(), + nc.viewer_distance ); + statusLabel->setText(msg); } diff --git a/src/context.cc b/src/context.cc index a7273a4..b5420ff 100644 --- a/src/context.cc +++ b/src/context.cc @@ -38,6 +38,13 @@ namespace fs = boost::filesystem; std::vector<const Context*> Context::ctx_stack; +// $children is not a config_variable. config_variables have dynamic scope, +// meaning they are passed down the call chain implicitly. +// $children is simply misnamed and shouldn't have included the '$'. +static bool is_config_variable(const std::string &name) { + return name[0] == '$' && name != "$children"; +} + /*! Initializes this context. Optionally initializes a context for an external library */ @@ -80,10 +87,8 @@ void Context::setVariables(const AssignmentList &args, void Context::set_variable(const std::string &name, const Value &value) { - if (name[0] == '$') - this->config_variables[name] = value; - else - this->variables[name] = value; + if (is_config_variable(name)) this->config_variables[name] = value; + else this->variables[name] = value; } void Context::set_constant(const std::string &name, const Value &value) @@ -98,7 +103,7 @@ void Context::set_constant(const std::string &name, const Value &value) Value Context::lookup_variable(const std::string &name, bool silent) const { - if (name[0] == '$') { + if (is_config_variable(name)) { for (int i = ctx_stack.size()-1; i >= 0; i--) { const ValueMap &confvars = ctx_stack[i]->config_variables; if (confvars.find(name) != confvars.end()) diff --git a/src/control.cc b/src/control.cc index c5ad09b..50e5eae 100644 --- a/src/control.cc +++ b/src/control.cc @@ -31,6 +31,7 @@ #include "builtin.h" #include "printutils.h" #include <sstream> +#include "mathc99.h" enum control_type_e { CHILD, diff --git a/src/export.h b/src/export.h index a565561..5dae7e0 100644 --- a/src/export.h +++ b/src/export.h @@ -12,6 +12,7 @@ void export_off(CGAL_Nef_polyhedron *root_N, std::ostream &output); void export_dxf(CGAL_Nef_polyhedron *root_N, std::ostream &output); void export_png_with_cgal(CGAL_Nef_polyhedron *root_N, Camera &c, std::ostream &output); void export_png_with_opencsg(Tree &tree, Camera &c, std::ostream &output); +void export_png_with_throwntogether(Tree &tree, Camera &c, std::ostream &output); #endif diff --git a/src/export_png.cc b/src/export_png.cc index c6c191c..6d64d65 100644 --- a/src/export_png.cc +++ b/src/export_png.cc @@ -41,26 +41,25 @@ void export_png_with_cgal(CGAL_Nef_polyhedron *root_N, Camera &cam, std::ostream cam.eye = cam.center - radius*2*cameradir; } - //std::cerr << center << "\n"; - //std::cerr << radius << "\n"; - glview->setCamera( cam ); glview->setRenderer(&cgalRenderer); glview->paintGL(); glview->save(output); } +enum Previewer { OPENCSG, THROWN } previewer; + #ifdef ENABLE_OPENCSG #include "OpenCSGRenderer.h" #include <opencsg.h> #endif +#include "ThrownTogetherRenderer.h" -void export_png_with_opencsg(Tree &tree, Camera &cam, std::ostream &output) +void export_png_preview_common( Tree &tree, Camera &cam, std::ostream &output, Previewer previewer = OPENCSG ) { -#ifdef ENABLE_OPENCSG - CsgInfo csgInfo = CsgInfo(); - if ( !csgInfo.compile_chains( tree ) ) { - fprintf(stderr,"Couldn't initialize OpenCSG chains\n"); + CsgInfo csgInfo = CsgInfo(); + if ( !csgInfo.compile_chains( tree ) ) { + fprintf(stderr,"Couldn't initialize CSG chains\n"); return; } @@ -71,7 +70,10 @@ void export_png_with_opencsg(Tree &tree, Camera &cam, std::ostream &output) return; } - OpenCSGRenderer opencsgRenderer(csgInfo.root_chain, csgInfo.highlights_chain, csgInfo.background_chain, csgInfo.glview->shaderinfo); +#ifdef ENABLE_OPENCSG + OpenCSGRenderer openCSGRenderer(csgInfo.root_chain, csgInfo.highlights_chain, csgInfo.background_chain, csgInfo.glview->shaderinfo); +#endif + ThrownTogetherRenderer thrownTogetherRenderer( csgInfo.root_chain, csgInfo.highlights_chain, csgInfo.background_chain ); if (cam.type == Camera::NONE) { cam.type = Camera::VECTOR; @@ -86,15 +88,31 @@ void export_png_with_opencsg(Tree &tree, Camera &cam, std::ostream &output) } csgInfo.glview->setCamera( cam ); - csgInfo.glview->setRenderer(&opencsgRenderer); - OpenCSG::setContext(0); - OpenCSG::setOption(OpenCSG::OffscreenSetting, OpenCSG::FrameBufferObject); + if ( previewer == OPENCSG ) + csgInfo.glview->setRenderer( &openCSGRenderer ); + else + csgInfo.glview->setRenderer( &thrownTogetherRenderer ); +#ifdef ENABLE_OPENCSG + OpenCSG::setContext( 0 ); + OpenCSG::setOption( OpenCSG::OffscreenSetting, OpenCSG::FrameBufferObject ); +#endif csgInfo.glview->paintGL(); - csgInfo.glview->save(output); + csgInfo.glview->save( output ); +} + +void export_png_with_opencsg(Tree &tree, Camera &cam, std::ostream &output) +{ +#ifdef ENABLE_OPENCSG + export_png_preview_common( tree, cam, output, OPENCSG ); #else fprintf(stderr,"This openscad was built without OpenCSG support\n"); #endif } +void export_png_with_throwntogether(Tree &tree, Camera &cam, std::ostream &output) +{ + export_png_preview_common( tree, cam, output, THROWN ); +} + #endif // ENABLE_CGAL diff --git a/src/imageutils-lodepng.cc b/src/imageutils-lodepng.cc index cd104d6..a71a017 100644 --- a/src/imageutils-lodepng.cc +++ b/src/imageutils-lodepng.cc @@ -9,7 +9,12 @@ bool write_png(std::ostream &output, unsigned char *pixels, int width, int height) { std::vector<unsigned char> dataout; - unsigned err = lodepng::encode(dataout, pixels, width, height, LCT_RGBA, 8); + lodepng::State state; + state.encoder.auto_convert = LAC_NO; + // some png renderers have different interpretations of alpha, so don't use it + state.info_png.color.colortype = LCT_RGB; + state.info_png.color.bitdepth = 8; + unsigned err = lodepng::encode(dataout, pixels, width, height, state); if ( err ) return false; output.write( reinterpret_cast<const char *>(&dataout[0]), dataout.size()); if ( output.bad() ) std::cerr << "Error writing to ostream\n"; diff --git a/src/import.cc b/src/import.cc index b5d67d2..3897331 100644 --- a/src/import.cc +++ b/src/import.cc @@ -212,7 +212,9 @@ PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const #ifdef BOOST_BIG_ENDIAN uint32_byte_swap( facenum ); #endif - if (file_size == 80 + 4 + 50*facenum) binary = true; + if (file_size == static_cast<std::streamoff>(80 + 4 + 50*facenum)) { + binary = true; + } } f.seekg(0); diff --git a/src/mainwin.cc b/src/mainwin.cc index 3d50d6f..65c511f 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -27,7 +27,6 @@ #include "PolySetCache.h" #include "ModuleCache.h" #include "MainWindow.h" -#include "openscad.h" // examplesdir #include "parsersettings.h" #include "Preferences.h" #include "printutils.h" @@ -101,16 +100,11 @@ #endif // ENABLE_CGAL -#ifndef OPENCSG_VERSION_STRING -#define OPENCSG_VERSION_STRING "unknown, <1.3.2" -#endif - #include "boosty.h" -extern QString examplesdir; - // Global application state unsigned int GuiLocker::gui_locked = 0; +QString MainWindow::qexamplesdir; #define QUOTE(x__) # x__ #define QUOTED(x__) QUOTE(x__) @@ -257,10 +251,9 @@ MainWindow::MainWindow(const QString &filename) this->menuOpenRecent->addAction(this->fileActionClearRecent); connect(this->fileActionClearRecent, SIGNAL(triggered()), this, SLOT(clearRecentFiles())); - - if (!examplesdir.isEmpty()) { + if (!qexamplesdir.isEmpty()) { bool found_example = false; - QStringList examples = QDir(examplesdir).entryList(QStringList("*.scad"), + QStringList examples = QDir(qexamplesdir).entryList(QStringList("*.scad"), QDir::Files | QDir::Readable, QDir::Name); foreach (const QString &ex, examples) { this->menuExamples->addAction(ex, this, SLOT(actionOpenExample())); @@ -636,7 +629,9 @@ void MainWindow::compile(bool reload, bool forcedone) // if we haven't yet compiled the current text. else { QString current_doc = editor->toPlainText(); - if (current_doc != last_compiled_doc) shouldcompiletoplevel = true; + if (current_doc != last_compiled_doc && last_compiled_doc.size() == 0) { + shouldcompiletoplevel = true; + } } } else { @@ -987,7 +982,7 @@ void MainWindow::actionOpenExample() { QAction *action = qobject_cast<QAction *>(sender()); if (action) { - openFile(examplesdir + QDir::separator() + action->text()); + openFile(qexamplesdir + QDir::separator() + action->text()); } } @@ -1828,34 +1823,16 @@ MainWindow::helpManual() QDesktopServices::openUrl(QUrl("http://www.openscad.org/documentation.html")); } -#define STRINGIFY(x) #x -#define TOSTRING(x) STRINGIFY(x) void MainWindow::helpLibrary() { - QString libinfo; - libinfo.sprintf("Boost version: %s\n" - "Eigen version: %d.%d.%d\n" - "CGAL version: %s\n" - "OpenCSG version: %s\n" - "Qt version: %s\n\n", - BOOST_LIB_VERSION, - EIGEN_WORLD_VERSION, EIGEN_MAJOR_VERSION, EIGEN_MINOR_VERSION, - TOSTRING(CGAL_VERSION), - OPENCSG_VERSION_STRING, - qVersion()); - -#if defined( __MINGW64__ ) - libinfo += QString("Compiled for MingW64\n\n"); -#elif defined( __MINGW32__ ) - libinfo += QString("Compiled for MingW32\n\n"); -#endif - + QString info( PlatformUtils::info().c_str() ); + info += QString( qglview->getRendererInfo().c_str() ); if (!this->openglbox) { - this->openglbox = new QMessageBox(QMessageBox::Information, - "OpenGL Info", "OpenSCAD Detailed Library Info ", + this->openglbox = new QMessageBox(QMessageBox::Information, + "OpenGL Info", "OpenSCAD Detailed Library and Build Information", QMessageBox::Ok, this); } - this->openglbox->setDetailedText(libinfo + QString(qglview->getRendererInfo().c_str())); + this->openglbox->setDetailedText( info ); this->openglbox->show(); } diff --git a/src/mathc99.cc b/src/mathc99.cc index 335446e..13f4c64 100644 --- a/src/mathc99.cc +++ b/src/mathc99.cc @@ -3,8 +3,12 @@ #ifdef WIN32
#include <algorithm>
+double trunc(double a) {
+ return (a >= 0) ? floor(a) : ceil(a);
+}
+
double round(double a) {
- return a > 0 ? floor(a+0.5) : ceil(a-0.5);
+ return a < 0 ? ceil(a - 0.5f) : floor(a + 0.5f);
}
float fmin(float a, float b) {
diff --git a/src/mathc99.h b/src/mathc99.h index ebc2d66..ae31a22 100644 --- a/src/mathc99.h +++ b/src/mathc99.h @@ -5,6 +5,7 @@ #include <cmath>
//for native win32 builds we need to provide C99 math functions by ourselves
+double trunc(double a);
double round(double a);
float fmin(float a, float b);
float fmax(float a, float b);
diff --git a/src/module.cc b/src/module.cc index 9c3541f..e3a992b 100644 --- a/src/module.cc +++ b/src/module.cc @@ -182,10 +182,12 @@ AbstractNode *Module::instantiate(const Context *ctx, const ModuleInstantiation } ModuleContext c(ctx, evalctx); + // set $children first since we might have variables depending on it + c.set_variable("$children", Value(double(inst->scope.children.size()))); c.initializeModule(*this); module_stack.push_back(inst->name()); c.set_variable("$parent_modules", Value(double(module_stack.size()))); - c.set_variable("$children", Value(double(inst->scope.children.size()))); + c.initializeModule(*this); // FIXME: Set document path to the path of the module #if 0 && DEBUG c.dump(this, inst); diff --git a/src/openscad.cc b/src/openscad.cc index e657cb0..f4f4014 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -25,18 +25,18 @@ */ #include "openscad.h" -#include "MainWindow.h" #include "node.h" #include "module.h" #include "modcontext.h" #include "value.h" #include "export.h" #include "builtin.h" -#include "nodedumper.h" #include "printutils.h" #include "handle_dep.h" #include "parsersettings.h" #include "rendersettings.h" +#include "PlatformUtils.h" +#include "nodedumper.h" #include <string> #include <vector> @@ -50,14 +50,11 @@ #include "csgterm.h" #include "CSGTermEvaluator.h" +#include "CsgInfo.h" -#include <QApplication> -#include <QString> -#include <QDir> #include <sstream> -#ifdef Q_WS_MAC -#include "EventFilter.h" +#ifdef __APPLE__ #include "AppleEvents.h" #ifdef OPENSCAD_DEPLOY #include "SparkleAutoUpdater.h" @@ -77,17 +74,40 @@ namespace po = boost::program_options; namespace fs = boost::filesystem; +namespace Render { enum type { CGAL, OPENCSG, THROWNTOGETHER }; }; +std::string commandline_commands; +std::string currentdir; +using std::string; +using std::vector; +using boost::lexical_cast; +using boost::is_any_of; + +class Echostream : public std::ofstream +{ +public: + Echostream( const char * filename ) : std::ofstream( filename ) { + set_output_handler( &Echostream::output, this ); + } + static void output( const std::string &msg, void *userdata ) { + Echostream *thisp = static_cast<Echostream*>(userdata); + *thisp << msg << "\n"; + } + ~Echostream() { + this->close(); + } +}; static void help(const char *progname) { int tab = int(strlen(progname))+8; fprintf(stderr,"Usage: %s [ -o output_file [ -d deps_file ] ]\\\n" - "%*s[ -m make_command ] [ -D var=val [..] ] [ --render ] \\\n" + "%*s[ -m make_command ] [ -D var=val [..] ] \\\n" "%*s[ --camera=translatex,y,z,rotx,y,z,dist | \\\n" "%*s --camera=eyex,y,z,centerx,y,z ] \\\n" "%*s[ --imgsize=width,height ] [ --projection=(o)rtho|(p)ersp] \\\n" + "%*s[ --render | --preview[=throwntogether] ] \\\n" "%*sfilename\n", - progname, tab, "", tab, "", tab, "", tab, "", tab, ""); + progname, tab, "", tab, "", tab, "", tab, "", tab, "", tab, ""); exit(1); } @@ -99,14 +119,22 @@ static void version() exit(1); } -std::string commandline_commands; -std::string currentdir; -QString examplesdir; +static void info() +{ + std::cout << PlatformUtils::info() << "\n\n"; -using std::string; -using std::vector; -using boost::lexical_cast; -using boost::is_any_of; + CsgInfo csgInfo = CsgInfo(); + try { + csgInfo.glview = new OffscreenView(512,512); + } catch (int error) { + fprintf(stderr,"Can't create OpenGL OffscreenView. Code: %i. Exiting.\n", error); + exit(1); + } + + std::cout << csgInfo.glview->getRendererInfo() << "\n"; + + exit(0); +} Camera get_camera( po::variables_map vm ) { @@ -127,6 +155,10 @@ Camera get_camera( po::variables_map vm ) } } + if (camera.type == Camera::GIMBAL) { + camera.gimbalDefaultTranslate(); + } + if (vm.count("projection")) { string proj = vm["projection"].as<string>(); if (proj=="o" || proj=="ortho" || proj=="orthogonal") @@ -158,17 +190,257 @@ Camera get_camera( po::variables_map vm ) return camera; } -int main(int argc, char **argv) +int cmdline(const char *deps_output_file, const std::string &filename, Camera &camera, const char *output_file, const fs::path &original_path, Render::type renderer, char ** argv ) { - int rc = 0; + parser_init(boosty::stringy(boost::filesystem::path( argv[0] ).parent_path())); + Tree tree; +#ifdef ENABLE_CGAL + CGALEvaluator cgalevaluator(tree); + PolySetCGALEvaluator psevaluator(cgalevaluator); +#endif + const char *stl_output_file = NULL; + const char *off_output_file = NULL; + const char *dxf_output_file = NULL; + const char *csg_output_file = NULL; + const char *png_output_file = NULL; + const char *ast_output_file = NULL; + const char *term_output_file = NULL; + const char *echo_output_file = NULL; + + std::string suffix = boosty::extension_str( output_file ); + boost::algorithm::to_lower( suffix ); + + if (suffix == ".stl") stl_output_file = output_file; + else if (suffix == ".off") off_output_file = output_file; + else if (suffix == ".dxf") dxf_output_file = output_file; + else if (suffix == ".csg") csg_output_file = output_file; + else if (suffix == ".png") png_output_file = output_file; + else if (suffix == ".ast") ast_output_file = output_file; + else if (suffix == ".term") term_output_file = output_file; + else if (suffix == ".echo") echo_output_file = output_file; + else { + fprintf(stderr, "Unknown suffix for output file %s\n", output_file); + return 1; + } + + // Top context - this context only holds builtins + ModuleContext top_ctx; + top_ctx.registerBuiltin(); +#if 0 && DEBUG + top_ctx.dump(NULL, NULL); +#endif + shared_ptr<Echostream> echostream; + if (echo_output_file) + echostream.reset( new Echostream( echo_output_file ) ); + + FileModule *root_module; + ModuleInstantiation root_inst("group"); + AbstractNode *root_node; + AbstractNode *absolute_root_node; + CGAL_Nef_polyhedron root_N; + + handle_dep(filename.c_str()); + + std::ifstream ifs(filename.c_str()); + if (!ifs.is_open()) { + fprintf(stderr, "Can't open input file '%s'!\n", filename.c_str()); + return 1; + } + std::string text((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); + text += "\n" + commandline_commands; + fs::path abspath = boosty::absolute(filename); + std::string parentpath = boosty::stringy(abspath.parent_path()); + root_module = parse(text.c_str(), parentpath.c_str(), false); + if (!root_module) { + fprintf(stderr, "Can't parse file '%s'!\n", filename.c_str()); + return 1; + } + root_module->handleDependencies(); + + fs::path fpath = boosty::absolute(fs::path(filename)); + fs::path fparent = fpath.parent_path(); + fs::current_path(fparent); + top_ctx.setDocumentPath(fparent.string()); + + AbstractNode::resetIndexCounter(); + absolute_root_node = root_module->instantiate(&top_ctx, &root_inst, NULL); + + // Do we have an explicit root node (! modifier)? + if (!(root_node = find_root_tag(absolute_root_node))) + root_node = absolute_root_node; + tree.setRoot(root_node); + + if (csg_output_file) { + fs::current_path(original_path); + std::ofstream fstream(csg_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", csg_output_file); + } + else { + fs::current_path(fparent); // Force exported filenames to be relative to document path + fstream << tree.getString(*root_node) << "\n"; + fstream.close(); + } + } + else if (ast_output_file) { + fs::current_path(original_path); + std::ofstream fstream(ast_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", ast_output_file); + } + else { + fs::current_path(fparent); // Force exported filenames to be relative to document path + fstream << root_module->dump("", "") << "\n"; + fstream.close(); + } + } + else if (term_output_file) { + std::vector<shared_ptr<CSGTerm> > highlight_terms; + std::vector<shared_ptr<CSGTerm> > background_terms; + + CSGTermEvaluator csgRenderer(tree, &psevaluator); + shared_ptr<CSGTerm> root_raw_term = csgRenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms); + + fs::current_path(original_path); + std::ofstream fstream(term_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", term_output_file); + } + else { + if (!root_raw_term) + fstream << "No top-level CSG object\n"; + else { + fstream << root_raw_term->dump() << "\n"; + } + fstream.close(); + } + } + else { #ifdef ENABLE_CGAL - // Causes CGAL errors to abort directly instead of throwing exceptions - // (which we don't catch). This gives us stack traces without rerunning in gdb. - CGAL::set_error_behaviour(CGAL::ABORT); + if ((echo_output_file || png_output_file) && !(renderer==Render::CGAL)) { + // echo or OpenCSG png -> don't necessarily need CGALMesh evaluation + } else { + root_N = cgalevaluator.evaluateCGALMesh(*tree.root()); + } + + fs::current_path(original_path); + + if (deps_output_file) { + std::string deps_out( deps_output_file ); + std::string geom_out; + if ( stl_output_file ) geom_out = std::string(stl_output_file); + else if ( off_output_file ) geom_out = std::string(off_output_file); + else if ( dxf_output_file ) geom_out = std::string(dxf_output_file); + else if ( png_output_file ) geom_out = std::string(png_output_file); + else { + PRINTB("Output file:%s\n",output_file); + PRINT("Sorry, don't know how to write deps for that file type. Exiting\n"); + return 1; + } + int result = write_deps( deps_out, geom_out ); + if ( !result ) { + PRINT("error writing deps"); + return 1; + } + } + + if (stl_output_file) { + if (root_N.dim != 3) { + fprintf(stderr, "Current top level object is not a 3D object.\n"); + return 1; + } + if (!root_N.p3->is_simple()) { + fprintf(stderr, "Object isn't a valid 2-manifold! Modify your design.\n"); + return 1; + } + std::ofstream fstream(stl_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", stl_output_file); + } + else { + export_stl(&root_N, fstream); + fstream.close(); + } + } + + if (off_output_file) { + if (root_N.dim != 3) { + fprintf(stderr, "Current top level object is not a 3D object.\n"); + return 1; + } + if (!root_N.p3->is_simple()) { + fprintf(stderr, "Object isn't a valid 2-manifold! Modify your design.\n"); + return 1; + } + std::ofstream fstream(off_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", off_output_file); + } + else { + export_off(&root_N, fstream); + fstream.close(); + } + } + + if (dxf_output_file) { + if (root_N.dim != 2) { + fprintf(stderr, "Current top level object is not a 2D object.\n"); + return 1; + } + std::ofstream fstream(dxf_output_file); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", dxf_output_file); + } + else { + export_dxf(&root_N, fstream); + fstream.close(); + } + } + + if (png_output_file) { + std::ofstream fstream(png_output_file,std::ios::out|std::ios::binary); + if (!fstream.is_open()) { + PRINTB("Can't open file \"%s\" for export", png_output_file); + } + else { + if (renderer==Render::CGAL) { + export_png_with_cgal(&root_N, camera, fstream); + } else if (renderer==Render::THROWNTOGETHER) { + export_png_with_throwntogether(tree, camera, fstream); + } else { + export_png_with_opencsg(tree, camera, fstream); + } + fstream.close(); + } + } +#else + fprintf(stderr, "OpenSCAD has been compiled without CGAL support!\n"); + return 1; #endif - Builtins::instance()->initialize(); + } + delete root_node; + return 0; +} + +#ifdef OPENSCAD_TESTING +#undef OPENSCAD_QTGUI +#else +#define OPENSCAD_QTGUI 1 +#endif + + +#ifdef OPENSCAD_QTGUI +#include "MainWindow.h" + #ifdef __APPLE__ + #include "EventFilter.h" + #endif +#include <QApplication> +#include <QString> +#include <QDir> +bool QtUseGUI() +{ #ifdef Q_WS_X11 // see <http://qt.nokia.com/doc/4.5/qapplication.html#QApplication-2>: // On X11, the window system is initialized if GUIenabled is true. If GUIenabled @@ -179,18 +451,95 @@ int main(int argc, char **argv) #else bool useGUI = true; #endif - QApplication app(argc, argv, useGUI); + return useGUI; +} + +int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv) +{ + QApplication app(argc, argv, true); //useGUI); #ifdef Q_WS_MAC app.installEventFilter(new EventFilter(&app)); #endif - fs::path original_path = fs::current_path(); - // set up groups for QSettings QCoreApplication::setOrganizationName("OpenSCAD"); QCoreApplication::setOrganizationDomain("openscad.org"); QCoreApplication::setApplicationName("OpenSCAD"); QCoreApplication::setApplicationVersion(TOSTRING(OPENSCAD_VERSION)); + QDir exdir(QApplication::instance()->applicationDirPath()); + QString qexamplesdir; +#ifdef Q_WS_MAC + exdir.cd("../Resources"); // Examples can be bundled + if (!exdir.exists("examples")) exdir.cd("../../.."); +#elif defined(Q_OS_UNIX) + if (exdir.cd("../share/openscad/examples")) { + qexamplesdir = exdir.path(); + } else + if (exdir.cd("../../share/openscad/examples")) { + qexamplesdir = exdir.path(); + } else + if (exdir.cd("../../examples")) { + qexamplesdir = exdir.path(); + } else +#endif + if (exdir.cd("examples")) { + qexamplesdir = exdir.path(); + } + MainWindow::setExamplesDir(qexamplesdir); + + parser_init(QApplication::instance()->applicationDirPath().toLocal8Bit().constData()); + +#ifdef Q_WS_MAC + installAppleEventHandlers(); +#endif + +#if defined(OPENSCAD_DEPLOY) && defined(Q_WS_MAC) + AutoUpdater *updater = new SparkleAutoUpdater; + AutoUpdater::setUpdater(updater); + if (updater->automaticallyChecksForUpdates()) updater->checkForUpdates(); +#endif + +#if 0 /*** disabled by clifford wolf: adds rendering artefacts with OpenCSG ***/ + // turn on anti-aliasing + QGLFormat f; + f.setSampleBuffers(true); + f.setSamples(4); + QGLFormat::setDefaultFormat(f); +#endif + if (!inputFiles.size()) inputFiles.push_back(""); +#ifdef ENABLE_MDI + BOOST_FOREACH(const string &infile, inputFiles) { + new MainWindow(QString::fromLocal8Bit(boosty::stringy(original_path / infile).c_str())); + } + app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); +#else + MainWindow *m = new MainWindow(QString::fromLocal8Bit(boosty::stringy(original_path / inputFiles[0]).c_str())); + app.connect(m, SIGNAL(destroyed()), &app, SLOT(quit())); +#endif + return app.exec(); +} +#else // OPENSCAD_QTGUI +bool QtUseGUI() { return false; } +int gui(const vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv) +{ + fprintf(stderr,"Error: compiled without QT, but trying to run GUI\n"); + return 1; +} +#endif // OPENSCAD_QTGUI + +int main(int argc, char **argv) +{ + int rc = 0; + +#ifdef ENABLE_CGAL + // Causes CGAL errors to abort directly instead of throwing exceptions + // (which we don't catch). This gives us stack traces without rerunning in gdb. + CGAL::set_error_behaviour(CGAL::ABORT); +#endif + Builtins::instance()->initialize(); + + fs::path original_path = fs::current_path(); + const char *filename = NULL; const char *output_file = NULL; const char *deps_output_file = NULL; @@ -199,7 +548,9 @@ int main(int argc, char **argv) desc.add_options() ("help,h", "help message") ("version,v", "print the version") + ("info", "print information about the building process") ("render", "if exporting a png image, do a full CGAL render") + ("preview", po::value<string>(), "if exporting a png image, do an OpenCSG(default) or ThrownTogether preview") ("camera", po::value<string>(), "parameters for camera when exporting png") ("imgsize", po::value<string>(), "=width,height for exporting png") ("projection", po::value<string>(), "(o)rtho or (p)erspective when exporting png") @@ -231,6 +582,14 @@ int main(int argc, char **argv) if (vm.count("help")) help(argv[0]); if (vm.count("version")) version(); + if (vm.count("info")) info(); + + Render::type renderer = Render::OPENCSG; + if (vm.count("render")) + renderer = Render::CGAL; + if (vm.count("preview")) + if (vm["preview"].as<string>() == "throwntogether") + renderer = Render::THROWNTOGETHER; if (vm.count("o")) { // FIXME: Allow for multiple output files? @@ -264,13 +623,12 @@ int main(int argc, char **argv) commandline_commands += ";\n"; } } - - if (vm.count("input-file")) { - filename = vm["input-file"].as< vector<string> >().begin()->c_str(); + vector<string> inputFiles; + if (vm.count("input-file")) { + inputFiles = vm["input-file"].as<vector<string> >(); } - #ifndef ENABLE_MDI - if (vm.count("input-file") > 1) { + if (inputFiles.size() > 1) { help(argv[0]); } #endif @@ -279,295 +637,20 @@ int main(int argc, char **argv) Camera camera = get_camera( vm ); - QDir exdir(QApplication::instance()->applicationDirPath()); -#ifdef Q_WS_MAC - exdir.cd("../Resources"); // Examples can be bundled - if (!exdir.exists("examples")) exdir.cd("../../.."); -#elif defined(Q_OS_UNIX) - if (exdir.cd("../share/openscad/examples")) { - examplesdir = exdir.path(); - } else - if (exdir.cd("../../share/openscad/examples")) { - examplesdir = exdir.path(); - } else - if (exdir.cd("../../examples")) { - examplesdir = exdir.path(); - } else -#endif - if (exdir.cd("examples")) { - examplesdir = exdir.path(); - } - - parser_init(QApplication::instance()->applicationDirPath().toLocal8Bit().constData()); - // Initialize global visitors NodeCache nodecache; NodeDumper dumper(nodecache); - Tree tree; -#ifdef ENABLE_CGAL - CGALEvaluator cgalevaluator(tree); - PolySetCGALEvaluator psevaluator(cgalevaluator); -#endif - - if (output_file) - { - const char *stl_output_file = NULL; - const char *off_output_file = NULL; - const char *dxf_output_file = NULL; - const char *csg_output_file = NULL; - const char *png_output_file = NULL; - const char *ast_output_file = NULL; - const char *term_output_file = NULL; - bool null_output = false; - - QString suffix = QFileInfo(output_file).suffix().toLower(); - if (suffix == "stl") stl_output_file = output_file; - else if (suffix == "off") off_output_file = output_file; - else if (suffix == "dxf") dxf_output_file = output_file; - else if (suffix == "csg") csg_output_file = output_file; - else if (suffix == "png") png_output_file = output_file; - else if (suffix == "ast") ast_output_file = output_file; - else if (suffix == "term") term_output_file = output_file; - else if (strcmp(output_file, "null") == 0) null_output = true; - else { - fprintf(stderr, "Unknown suffix for output file %s\n", output_file); - exit(1); - } - - if (!filename) help(argv[0]); - - // Top context - this context only holds builtins - ModuleContext top_ctx; - top_ctx.registerBuiltin(); -#if 0 && DEBUG - top_ctx.dump(NULL, NULL); -#endif - - FileModule *root_module; - ModuleInstantiation root_inst("group"); - AbstractNode *root_node; - AbstractNode *absolute_root_node; - CGAL_Nef_polyhedron root_N; - - handle_dep(filename); - - std::ifstream ifs(filename); - if (!ifs.is_open()) { - fprintf(stderr, "Can't open input file '%s'!\n", filename); - exit(1); - } - std::string text((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); - text += "\n" + commandline_commands; - fs::path abspath = boosty::absolute(filename); - std::string parentpath = boosty::stringy(abspath.parent_path()); - root_module = parse(text.c_str(), parentpath.c_str(), false); - if (!root_module) exit(1); - root_module->handleDependencies(); - - fs::path fpath = boosty::absolute(fs::path(filename)); - fs::path fparent = fpath.parent_path(); - fs::current_path(fparent); - top_ctx.setDocumentPath(fparent.string()); - - AbstractNode::resetIndexCounter(); - absolute_root_node = root_module->instantiate(&top_ctx, &root_inst, NULL); - - // Do we have an explicit root node (! modifier)? - if (!(root_node = find_root_tag(absolute_root_node))) - root_node = absolute_root_node; - - tree.setRoot(root_node); - - if (csg_output_file) { - fs::current_path(original_path); - std::ofstream fstream(csg_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", csg_output_file); - } - else { - fs::current_path(fparent); // Force exported filenames to be relative to document path - fstream << tree.getString(*root_node) << "\n"; - fstream.close(); - } - } - else if (ast_output_file) { - fs::current_path(original_path); - std::ofstream fstream(ast_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", ast_output_file); - } - else { - fs::current_path(fparent); // Force exported filenames to be relative to document path - fstream << root_module->dump("", "") << "\n"; - fstream.close(); - } - } - else if (term_output_file) { - std::vector<shared_ptr<CSGTerm> > highlight_terms; - std::vector<shared_ptr<CSGTerm> > background_terms; - CSGTermEvaluator csgrenderer(tree, &psevaluator); - shared_ptr<CSGTerm> root_raw_term = csgrenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms); - - fs::current_path(original_path); - std::ofstream fstream(term_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", term_output_file); - } - else { - if (!root_raw_term) - fstream << "No top-level CSG object\n"; - else { - fstream << root_raw_term->dump() << "\n"; - } - fstream.close(); - } - } - else { -#ifdef ENABLE_CGAL - if ((null_output || png_output_file) && !vm.count("render")) { - // null output or OpenCSG png -> don't necessarily need CGALMesh evaluation - } else { - root_N = cgalevaluator.evaluateCGALMesh(*tree.root()); - } - - fs::current_path(original_path); - - if (deps_output_file) { - std::string deps_out( deps_output_file ); - std::string geom_out; - if ( stl_output_file ) geom_out = std::string(stl_output_file); - else if ( off_output_file ) geom_out = std::string(off_output_file); - else if ( dxf_output_file ) geom_out = std::string(dxf_output_file); - else if ( png_output_file ) geom_out = std::string(png_output_file); - else { - PRINTB("Output file:%s\n",output_file); - PRINT("Sorry, don't know how to write deps for that file type. Exiting\n"); - exit(1); - } - int result = write_deps( deps_out, geom_out ); - if ( !result ) { - PRINT("error writing deps"); - exit(1); - } - } - - if (stl_output_file) { - if (root_N.dim != 3) { - fprintf(stderr, "Current top level object is not a 3D object.\n"); - exit(1); - } - if (!root_N.p3->is_simple()) { - fprintf(stderr, "Object isn't a valid 2-manifold! Modify your design.\n"); - exit(1); - } - std::ofstream fstream(stl_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", stl_output_file); - } - else { - export_stl(&root_N, fstream); - fstream.close(); - } - } - - if (off_output_file) { - if (root_N.dim != 3) { - fprintf(stderr, "Current top level object is not a 3D object.\n"); - exit(1); - } - if (!root_N.p3->is_simple()) { - fprintf(stderr, "Object isn't a valid 2-manifold! Modify your design.\n"); - exit(1); - } - std::ofstream fstream(off_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", off_output_file); - } - else { - export_off(&root_N, fstream); - fstream.close(); - } - } - - if (dxf_output_file) { - if (root_N.dim != 2) { - fprintf(stderr, "Current top level object is not a 2D object.\n"); - exit(1); - } - std::ofstream fstream(dxf_output_file); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", dxf_output_file); - } - else { - export_dxf(&root_N, fstream); - fstream.close(); - } - } - - if (png_output_file) { - std::ofstream fstream(png_output_file,std::ios::out|std::ios::binary); - if (!fstream.is_open()) { - PRINTB("Can't open file \"%s\" for export", png_output_file); - } - else { - if (vm.count("render")) { - export_png_with_cgal(&root_N, camera, fstream); - } else { - export_png_with_opencsg(tree, camera, fstream); - } - fstream.close(); - } - } -#else - fprintf(stderr, "OpenSCAD has been compiled without CGAL support!\n"); - exit(1); -#endif - } - delete root_node; + if (output_file) { + if (!inputFiles.size()) help(argv[0]); + rc = cmdline(deps_output_file, inputFiles[0], camera, output_file, original_path, renderer, argv); } - else if (useGUI) - { -#ifdef Q_WS_MAC - installAppleEventHandlers(); -#endif - -#if defined(OPENSCAD_DEPLOY) && defined(Q_WS_MAC) - AutoUpdater *updater = new SparkleAutoUpdater; - AutoUpdater::setUpdater(updater); - if (updater->automaticallyChecksForUpdates()) updater->checkForUpdates(); -#endif - - QString qfilename; - if (filename) qfilename = QString::fromLocal8Bit(boosty::stringy(boosty::absolute(filename)).c_str()); - -#if 0 /*** disabled by clifford wolf: adds rendering artefacts with OpenCSG ***/ - // turn on anti-aliasing - QGLFormat f; - f.setSampleBuffers(true); - f.setSamples(4); - QGLFormat::setDefaultFormat(f); -#endif -#ifdef ENABLE_MDI - new MainWindow(qfilename); - vector<string> inputFiles; - if (vm.count("input-file")) { - inputFiles = vm["input-file"].as<vector<string> >(); - for (vector<string>::const_iterator infile = inputFiles.begin()+1; infile != inputFiles.end(); infile++) { - new MainWindow(QString::fromLocal8Bit(boosty::stringy(original_path / *infile).c_str())); - } - } - app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); -#else - MainWindow *m = new MainWindow(qfilename); - app.connect(m, SIGNAL(destroyed()), &app, SLOT(quit())); -#endif - rc = app.exec(); + else if (QtUseGUI()) { + rc = gui(inputFiles, original_path, argc, argv); } - else - { + else { fprintf(stderr, "Requested GUI mode but can't open display!\n"); - exit(1); + help(argv[0]); } Builtins::instance(true); diff --git a/src/parser.y b/src/parser.y index 5b3d019..5645104 100644 --- a/src/parser.y +++ b/src/parser.y @@ -44,28 +44,30 @@ #include <boost/foreach.hpp> #include <boost/filesystem.hpp> - namespace fs = boost::filesystem; +namespace fs = boost::filesystem; +#define foreach BOOST_FOREACH + #include "boosty.h" - int parser_error_pos = -1; +int parser_error_pos = -1; - int parserlex(void); - void yyerror(char const *s); +int parserlex(void); +void yyerror(char const *s); - int lexerget_lineno(void); - int lexerlex_destroy(void); - int lexerlex(void); +int lexerget_lineno(void); +int lexerlex_destroy(void); +int lexerlex(void); - std::stack<LocalScope *> scope_stack; - FileModule *rootmodule; +std::stack<LocalScope *> scope_stack; +FileModule *rootmodule; - extern void lexerdestroy(); - extern FILE *lexerin; - extern const char *parser_input_buffer; - const char *parser_input_buffer; - std::string parser_source_path; +extern void lexerdestroy(); +extern FILE *lexerin; +extern const char *parser_input_buffer; +const char *parser_input_buffer; +std::string parser_source_path; - %} +%} %union { char *text; @@ -125,112 +127,149 @@ %% -input: -/* empty */ | -TOK_USE { rootmodule->usedlibs.insert($1); } input | -statement input ; +input: /* empty */ + | TOK_USE + { rootmodule->usedlibs.insert($1); } + input + | statement input + ; -inner_input: -/* empty */ | -statement inner_input ; +statement: + ';' + | '{' inner_input '}' + | module_instantiation + { + if ($1) scope_stack.top()->addChild($1); + } + | assignment + | TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' + { + Module *newmodule = new Module(); + newmodule->definition_arguments = *$4; + scope_stack.top()->modules[$2] = newmodule; + scope_stack.push(&newmodule->scope); + free($2); + delete $4; + } + statement + { + scope_stack.pop(); + } + | TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr + { + Function *func = new Function(); + func->definition_arguments = *$4; + func->expr = $8; + scope_stack.top()->functions[$2] = func; + free($2); + delete $4; + } + ';' + ; + +inner_input: + /* empty */ + | statement inner_input + ; assignment: -TOK_ID '=' expr ';' { - bool found = false; - for (AssignmentList::iterator iter = scope_stack.top()->assignments.begin(); - iter != scope_stack.top()->assignments.end(); - iter++) { - if (iter->first == $1) { - iter->second = $3; - found = true; - break; - } - } - if (!found) scope_stack.top()->assignments.push_back(Assignment($1, $3)); -} ; - -statement: -';' | -'{' inner_input '}' | -module_instantiation { - if ($1) scope_stack.top()->addChild($1); -} | -assignment | -TOK_MODULE TOK_ID '(' arguments_decl optional_commas ')' { - Module *newmodule = new Module(); - newmodule->definition_arguments = *$4; - scope_stack.top()->modules[$2] = newmodule; - scope_stack.push(&newmodule->scope); - free($2); - delete $4; -} statement { - scope_stack.pop(); - } | - TOK_FUNCTION TOK_ID '(' arguments_decl optional_commas ')' '=' expr { - Function *func = new Function(); - func->definition_arguments = *$4; - func->expr = $8; - scope_stack.top()->functions[$2] = func; - free($2); - delete $4; - } ';' ; + TOK_ID '=' expr ';' + { + bool found = false; + foreach (Assignment& iter, scope_stack.top()->assignments) { + if (iter.first == $1) { + iter.second = $3; + found = true; + break; + } + } + if (!found) { + scope_stack.top()->assignments.push_back(Assignment($1, $3)); + } + } + ; -if_statement: -TOK_IF '(' expr ')' { - $<ifelse>$ = new IfElseModuleInstantiation(); - $<ifelse>$->arguments.push_back(Assignment("", $3)); - $<ifelse>$->setPath(parser_source_path); - scope_stack.push(&$<ifelse>$->scope); -} child_statement { - scope_stack.pop(); - $$ = $<ifelse>5; - } ; +module_instantiation: + '!' module_instantiation + { + $$ = $2; + if ($$) $$->tag_root = true; + } + | '#' module_instantiation + { + $$ = $2; + if ($$) $$->tag_highlight = true; + } + | '%' module_instantiation + { + $$ = $2; + if ($$) $$->tag_background = true; + } + | '*' module_instantiation + { + delete $2; + $$ = NULL; + } + | single_module_instantiation + { + $<inst>$ = $1; + scope_stack.push(&$1->scope); + } + child_statement + { + scope_stack.pop(); + $$ = $<inst>2; + } + | ifelse_statement + { + $$ = $1; + } + ; ifelse_statement: -if_statement { - $$ = $1; -} | -if_statement TOK_ELSE { - scope_stack.push(&$1->else_scope); -} child_statement { - scope_stack.pop(); - $$ = $1; - } ; + if_statement + { + $$ = $1; + } + | if_statement TOK_ELSE + { + scope_stack.push(&$1->else_scope); + } + child_statement + { + scope_stack.pop(); + $$ = $1; + } + ; -module_instantiation: -'!' module_instantiation { - $$ = $2; - if ($$) $$->tag_root = true; -} | -'#' module_instantiation { - $$ = $2; - if ($$) $$->tag_highlight = true; -} | -'%' module_instantiation { - $$ = $2; - if ($$) $$->tag_background = true; -} | -'*' module_instantiation { - delete $2; - $$ = NULL; -} | -single_module_instantiation { - $<inst>$ = $1; - scope_stack.push(&$1->scope); -} child_statement { - scope_stack.pop(); - $$ = $<inst>2; - } | - ifelse_statement { - $$ = $1; - } ; +if_statement: + TOK_IF '(' expr ')' + { + $<ifelse>$ = new IfElseModuleInstantiation(); + $<ifelse>$->arguments.push_back(Assignment("", $3)); + $<ifelse>$->setPath(parser_source_path); + scope_stack.push(&$<ifelse>$->scope); + } + child_statement + { + scope_stack.pop(); + $$ = $<ifelse>5; + } + ; + +child_statements: + /* empty */ + | child_statements child_statement + ; child_statement: -';' | -'{' child_statements '}' | -module_instantiation { - if ($1) scope_stack.top()->addChild($1); -} ; + ';' + | '{' child_statements '}' + | module_instantiation + { + if ($1) scope_stack.top()->addChild($1); + } + ; /* FIXME: This allows for variable declaration in child blocks, not activated yet @@ -238,198 +277,247 @@ module_instantiation { assignment ; */ -child_statements: -/* empty */ | -child_statements child_statement ; - single_module_instantiation: -TOK_ID '(' arguments_call ')' { - $$ = new ModuleInstantiation($1); - $$->arguments = *$3; - $$->setPath(parser_source_path); - free($1); - delete $3; -} + TOK_ID '(' arguments_call ')' + { + $$ = new ModuleInstantiation($1); + $$->arguments = *$3; + $$->setPath(parser_source_path); + free($1); + delete $3; + } + ; expr: -TOK_TRUE { - $$ = new Expression(Value(true)); -} | -TOK_FALSE { - $$ = new Expression(Value(false)); -} | -TOK_UNDEF { - $$ = new Expression(Value::undefined); -} | -TOK_ID { - $$ = new Expression(); - $$->type = "L"; - $$->var_name = $1; - free($1); -} | -expr '.' TOK_ID { - $$ = new Expression("N", $1); - $$->var_name = $3; - free($3); -} | -TOK_STRING { - $$ = new Expression(Value(std::string($1))); - free($1); -} | -TOK_NUMBER { - $$ = new Expression(Value($1)); -} | -'[' expr ':' expr ']' { - Expression *e_one = new Expression(Value(1.0)); - $$ = new Expression(); - $$->type = "R"; - $$->children.push_back($2); - $$->children.push_back(e_one); - $$->children.push_back($4); -} | -'[' expr ':' expr ':' expr ']' { - $$ = new Expression(); - $$->type = "R"; - $$->children.push_back($2); - $$->children.push_back($4); - $$->children.push_back($6); -} | -'[' optional_commas ']' { - $$ = new Expression(Value(Value::VectorType())); -} | -'[' vector_expr optional_commas ']' { - $$ = $2; -} | -expr '*' expr { - $$ = new Expression("*", $1, $3); -} | -expr '/' expr { - $$ = new Expression("/", $1, $3); -} | -expr '%' expr { - $$ = new Expression("%", $1, $3); -} | -expr '+' expr { - $$ = new Expression("+", $1, $3); -} | -expr '-' expr { - $$ = new Expression("-", $1, $3); -} | -expr '<' expr { - $$ = new Expression("<", $1, $3); -} | -expr LE expr { - $$ = new Expression("<=", $1, $3); -} | -expr EQ expr { - $$ = new Expression("==", $1, $3); -} | -expr NE expr { - $$ = new Expression("!=", $1, $3); -} | -expr GE expr { - $$ = new Expression(">=", $1, $3); -} | -expr '>' expr { - $$ = new Expression(">", $1, $3); -} | -expr AND expr { - $$ = new Expression("&&", $1, $3); -} | -expr OR expr { - $$ = new Expression("||", $1, $3); -} | -'+' expr { - $$ = $2; -} | -'-' expr { - $$ = new Expression("I", $2); -} | -'!' expr { - $$ = new Expression("!", $2); -} | -'(' expr ')' { - $$ = $2; -} | -expr '?' expr ':' expr { - $$ = new Expression(); - $$->type = "?:"; - $$->children.push_back($1); - $$->children.push_back($3); - $$->children.push_back($5); -} | -expr '[' expr ']' { - $$ = new Expression("[]", $1, $3); -} | -TOK_ID '(' arguments_call ')' { - $$ = new Expression(); - $$->type = "F"; - $$->call_funcname = $1; - $$->call_arguments = *$3; - free($1); - delete $3; -} ; + TOK_TRUE + { + $$ = new Expression(Value(true)); + } + | TOK_FALSE + { + $$ = new Expression(Value(false)); + } + | TOK_UNDEF + { + $$ = new Expression(Value::undefined); + } + | TOK_ID + { + $$ = new Expression(); + $$->type = "L"; + $$->var_name = $1; + free($1); + } + | expr '.' TOK_ID + { + $$ = new Expression("N", $1); + $$->var_name = $3; + free($3); + } + | TOK_STRING + { + $$ = new Expression(Value(std::string($1))); + free($1); + } + | TOK_NUMBER + { + $$ = new Expression(Value($1)); + } + | '[' expr ':' expr ']' + { + Expression *e_one = new Expression(Value(1.0)); + $$ = new Expression(); + $$->type = "R"; + $$->children.push_back($2); + $$->children.push_back(e_one); + $$->children.push_back($4); + } + | '[' expr ':' expr ':' expr ']' + { + $$ = new Expression(); + $$->type = "R"; + $$->children.push_back($2); + $$->children.push_back($4); + $$->children.push_back($6); + } + | '[' optional_commas ']' + { + $$ = new Expression(Value(Value::VectorType())); + } + | '[' vector_expr optional_commas ']' + { + $$ = $2; + } + | expr '*' expr + { + $$ = new Expression("*", $1, $3); + } + | expr '/' expr + { + $$ = new Expression("/", $1, $3); + } + | expr '%' expr + { + $$ = new Expression("%", $1, $3); + } + | expr '+' expr + { + $$ = new Expression("+", $1, $3); + } + | expr '-' expr + { + $$ = new Expression("-", $1, $3); + } + | expr '<' expr + { + $$ = new Expression("<", $1, $3); + } + | expr LE expr + { + $$ = new Expression("<=", $1, $3); + } + | expr EQ expr + { + $$ = new Expression("==", $1, $3); + } + | expr NE expr + { + $$ = new Expression("!=", $1, $3); + } + | expr GE expr + { + $$ = new Expression(">=", $1, $3); + } + | expr '>' expr + { + $$ = new Expression(">", $1, $3); + } + | expr AND expr + { + $$ = new Expression("&&", $1, $3); + } + | expr OR expr + { + $$ = new Expression("||", $1, $3); + } + | '+' expr + { + $$ = $2; + } + | '-' expr + { + $$ = new Expression("I", $2); + } + | '!' expr + { + $$ = new Expression("!", $2); + } + | '(' expr ')' + { + $$ = $2; + } + | expr '?' expr ':' expr + { + $$ = new Expression(); + $$->type = "?:"; + $$->children.push_back($1); + $$->children.push_back($3); + $$->children.push_back($5); + } + | expr '[' expr ']' + { + $$ = new Expression("[]", $1, $3); + } + | TOK_ID '(' arguments_call ')' + { + $$ = new Expression(); + $$->type = "F"; + $$->call_funcname = $1; + $$->call_arguments = *$3; + free($1); + delete $3; + } + ; optional_commas: -',' optional_commas | ; + ',' optional_commas + | /* empty */ + ; vector_expr: -expr { - $$ = new Expression("V", $1); -} | -vector_expr ',' optional_commas expr { - $$ = $1; - $$->children.push_back($4); -} ; + expr + { + $$ = new Expression("V", $1); + } + | vector_expr ',' optional_commas expr + { + $$ = $1; + $$->children.push_back($4); + } + ; arguments_decl: -/* empty */ { - $$ = new AssignmentList(); -} | -argument_decl { - $$ = new AssignmentList(); - $$->push_back(*$1); - delete $1; -} | -arguments_decl ',' optional_commas argument_decl { - $$ = $1; - $$->push_back(*$4); - delete $4; -} ; + /* empty */ + { + $$ = new AssignmentList(); + } + | argument_decl + { + $$ = new AssignmentList(); + $$->push_back(*$1); + delete $1; + } + | arguments_decl ',' optional_commas argument_decl + { + $$ = $1; + $$->push_back(*$4); + delete $4; + } + ; argument_decl: -TOK_ID { - $$ = new Assignment($1, NULL); - free($1); -} | -TOK_ID '=' expr { - $$ = new Assignment($1, $3); - free($1); -} ; + TOK_ID + { + $$ = new Assignment($1, NULL); + free($1); + } + | TOK_ID '=' expr + { + $$ = new Assignment($1, $3); + free($1); + } + ; arguments_call: -/* empty */ { - $$ = new AssignmentList(); -} | -argument_call { - $$ = new AssignmentList(); - $$->push_back(*$1); - delete $1; -} | -arguments_call ',' optional_commas argument_call { - $$ = $1; - $$->push_back(*$4); - delete $4; -} ; + /* empty */ + { + $$ = new AssignmentList(); + } + | argument_call + { + $$ = new AssignmentList(); + $$->push_back(*$1); + delete $1; + } + | arguments_call ',' optional_commas argument_call + { + $$ = $1; + $$->push_back(*$4); + delete $4; + } + ; argument_call: -expr { - $$ = new Assignment("", $1); -} | -TOK_ID '=' expr { - $$ = new Assignment($1, $3); - free($1); -} ; + expr + { + $$ = new Assignment("", $1); + } + | TOK_ID '=' expr + { + $$ = new Assignment($1, $3); + free($1); + } + ; %% diff --git a/src/parsersettings.cc b/src/parsersettings.cc index 5ad30e1..63a7713 100644 --- a/src/parsersettings.cc +++ b/src/parsersettings.cc @@ -130,5 +130,6 @@ void parser_init(const std::string &applicationpath) if (is_directory(tmpdir = libdir / "libraries")) { librarydir = boosty::stringy(tmpdir); } + if (!librarydir.empty()) add_librarydir(librarydir); } @@ -32,16 +32,16 @@ std::string svg_styleblock(std::string strokewidth) std::stringstream out; // halfedge: f1/f0 = face mark, b1/b0 = body or hole, m1/m0 = halfedge mark out << "\ - <style type='text/css'>\n\ - .halfedge_f0_b1_m0 { stroke: gold; stroke-width: __STROKEW__px } \n\ - .halfedge_f0_b1_m1 { stroke: gold; stroke-width: __STROKEW__px } \n\ - .halfedge_f0_b0_m0 { stroke: green; stroke-width: __STROKEW__px } \n\ - .halfedge_f0_b0_m1 { stroke: green; stroke-width: __STROKEW__px } \n\ - .halfedge_f1_b1_m0 { stroke: gold; stroke-width: __STROKEW__px } \n\ - .halfedge_f1_b1_m1 { stroke: gold; stroke-width: __STROKEW__px } \n\ - .halfedge_f1_b0_m0 { stroke: green; stroke-width: __STROKEW__px } \n\ - .halfedge_f1_b0_m1 { stroke: green; stroke-width: __STROKEW__px } \n\ - </style>"; + <style type='text/css'>\n\ + .halfedge_f0_b1_m0 { stroke: gold; stroke-width: __STROKEW__px } \n\ + .halfedge_f0_b1_m1 { stroke: gold; stroke-width: __STROKEW__px } \n\ + .halfedge_f0_b0_m0 { stroke: green; stroke-width: __STROKEW__px } \n\ + .halfedge_f0_b0_m1 { stroke: green; stroke-width: __STROKEW__px } \n\ + .halfedge_f1_b1_m0 { stroke: gold; stroke-width: __STROKEW__px } \n\ + .halfedge_f1_b1_m1 { stroke: gold; stroke-width: __STROKEW__px } \n\ + .halfedge_f1_b0_m0 { stroke: green; stroke-width: __STROKEW__px } \n\ + .halfedge_f1_b0_m1 { stroke: green; stroke-width: __STROKEW__px } \n\ + </style>"; std::string tmp = out.str(); boost::replace_all( tmp, "__STROKEW__", strokewidth ); return tmp; @@ -119,14 +119,14 @@ std::string dump_cgal_nef_polyhedron2_face_svg( style << "halfedge_f" << facemark << "_b" << body << "_m"; std::string styleclass = style.str(); - std::stringstream out; + std::stringstream out; CGAL_For_all(c1, c2) { if ( explorer.is_standard( explorer.target(c1) ) ) { -CGAL_Nef_polyhedron2::Explorer::Point source = explorer.point( explorer.source( c1 ) ); + CGAL_Nef_polyhedron2::Explorer::Point source = explorer.point( explorer.source( c1 ) ); CGAL_Point_2e target = explorer.point( explorer.target( c1 ) ); out << " <!-- Halfedge. Mark: " << c1->mark() << " -->\n"; std::string he_mark = boost::lexical_cast<std::string>(c1->mark()); - out << " <line" + out << " <line" << " x1='" << CGAL::to_double(source.x()) << "'" << " y1='" << CGAL::to_double(source.y()) << "'" << " x2='" << CGAL::to_double(target.x()) << "'" @@ -141,10 +141,10 @@ CGAL_Nef_polyhedron2::Explorer::Point source = explorer.point( explorer.source( std::string dump_svg( const CGAL_Nef_polyhedron2 &N ) { - std::stringstream out; - CGAL_Nef_polyhedron2::Explorer explorer = N.explorer(); + std::stringstream out; + CGAL_Nef_polyhedron2::Explorer explorer = N.explorer(); CGAL_Iso_rectangle_2e bbox = bounding_box( N ); - CGAL_Nef_polyhedron2::Explorer::Face_const_iterator i; + CGAL_Nef_polyhedron2::Explorer::Face_const_iterator i; std::string linewidth = "0.05"; @@ -152,23 +152,23 @@ std::string dump_svg( const CGAL_Nef_polyhedron2 &N ) out << svg_header() << "\n" << svg_styleblock( linewidth ) << "\n"; for ( i = explorer.faces_begin(); i!= explorer.faces_end(); ++i ) { - out << " <!-- face begin. mark: " << i->mark() << " -->\n"; - out << " <!-- body begin -->\n"; - CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c1 - = explorer.face_cycle( i ), c2 ( c1 ); - out << dump_cgal_nef_polyhedron2_face_svg( c1, c2, explorer, i->mark(), true ); - out << " <!-- body end -->\n"; + out << " <!-- face begin. mark: " << i->mark() << " -->\n"; + out << " <!-- body begin -->\n"; + CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c1 + = explorer.face_cycle( i ), c2 ( c1 ); + out << dump_cgal_nef_polyhedron2_face_svg( c1, c2, explorer, i->mark(), true ); + out << " <!-- body end -->\n"; - CGAL_Nef_polyhedron2::Explorer::Hole_const_iterator j; - for ( j = explorer.holes_begin( i ); j!= explorer.holes_end( i ); ++j ) { - out << " <!-- hole begin. mark: " << j->mark() << " -->\n"; - CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c3( j ), c4 ( c3 ); - out << dump_cgal_nef_polyhedron2_face_svg( c3, c4, explorer, "green", j->mark() ); - out << " <!-- hole end -->\n"; - } - out << " <!-- face end -->\n"; - } - out << "</svg>"; + CGAL_Nef_polyhedron2::Explorer::Hole_const_iterator j; + for ( j = explorer.holes_begin( i ); j!= explorer.holes_end( i ); ++j ) { + out << " <!-- hole begin. mark: " << j->mark() << " -->\n"; + CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c3( j ), c4 ( c3 ); + out << dump_cgal_nef_polyhedron2_face_svg( c3, c4, explorer, "green", j->mark() ); + out << " <!-- hole end -->\n"; + } + out << " <!-- face end -->\n"; + } + out << "</svg>"; std::string tmp = out.str(); boost::replace_all( tmp, "'", "\"" ); return tmp; @@ -212,14 +212,14 @@ public: CGAL_Point_3 target = c1->source()->target()->point(); CGAL_Point_2e tp1 = project_svg_3to2 ( source, bbox ); CGAL_Point_2e tp2 = project_svg_3to2 ( target, bbox ); - out << " <!-- " << CGAL::to_double(source.x()) << "," - << CGAL::to_double(source.y()) << "," - << CGAL::to_double(source.z()) << " -->\n"; + out << " <!-- " << CGAL::to_double(source.x()) << "," + << CGAL::to_double(source.y()) << "," + << CGAL::to_double(source.z()) << " -->\n"; out << " <line " - << "x1='" << CGAL::to_double(tp1.x()) << "' " - << "y1='" << CGAL::to_double(tp1.y()) << "' " - << "x2='" << CGAL::to_double(tp2.x()) << "' " - << "y2='" << CGAL::to_double(tp2.y()) << "' " + << "x1='" << CGAL::to_double(tp1.x()) << "' " + << "y1='" << CGAL::to_double(tp1.y()) << "' " + << "x2='" << CGAL::to_double(tp2.x()) << "' " + << "y2='" << CGAL::to_double(tp2.y()) << "' " << " stroke='" << color << "'"; if (!(*hfacet).mark()) out << " stroke-dasharray='4 4' />\n"; else out << " />\n"; @@ -234,31 +234,31 @@ public: std::string dump_svg( const CGAL_Nef_polyhedron3 &N ) { - std::stringstream out; + std::stringstream out; std::string linewidth = "0.05"; out << "<!--CGAL_Nef_polyhedron3 dump begin-->\n"; out << svg_header() << "\n" << svg_border() << "\n"; out << svg_styleblock( linewidth ) << "\n" << svg_axes() << "\n"; - CGAL_Nef_polyhedron3::Volume_const_iterator c; - CGAL_forall_volumes(c,N) { - out << " <!--Volume begin-->\n"; - out << " <!--Mark: " << (*c).mark() << "-->\n"; - CGAL_Nef_polyhedron3::Shell_entry_const_iterator it; - CGAL_forall_shells_of(it,c) { - out << " <!--Shell begin-->\n"; - NefPoly3_dumper_svg dumper_svg(N); - N.visit_shell_objects(CGAL_Nef_polyhedron3::SFace_const_handle(it), dumper_svg ); + CGAL_Nef_polyhedron3::Volume_const_iterator c; + CGAL_forall_volumes(c,N) { + out << " <!--Volume begin-->\n"; + out << " <!--Mark: " << (*c).mark() << "-->\n"; + CGAL_Nef_polyhedron3::Shell_entry_const_iterator it; + CGAL_forall_shells_of(it,c) { + out << " <!--Shell begin-->\n"; + NefPoly3_dumper_svg dumper_svg(N); + N.visit_shell_objects(CGAL_Nef_polyhedron3::SFace_const_handle(it), dumper_svg ); out << dumper_svg.out.str(); - out << " <!--Shell end-->\n"; - } - out << " <!--Volume end-->\n"; - } - out << "<!--CGAL_Nef_polyhedron3 dump end-->\n"; + out << " <!--Shell end-->\n"; + } + out << " <!--Volume end-->\n"; + } + out << "<!--CGAL_Nef_polyhedron3 dump end-->\n"; out << "</svg>"; std::string tmp = out.str(); boost::replace_all( tmp, "'", "\"" ); - return tmp; + return tmp; } } // namespace diff --git a/src/version_check.h b/src/version_check.h index db17962..6e07208 100644 --- a/src/version_check.h +++ b/src/version_check.h @@ -87,11 +87,12 @@ a time, to avoid confusion. #else #endif // ENABLE_OPENCSG +#ifndef OPENSCAD_TESTING #include <QtCore/qglobal.h> #if QT_VERSION < 0x040400 #error QT library missing or version too old. See README.md. To force compile, run qmake CONFIG+=skip-version-check #endif // QT - +#endif #ifdef ENABLE_OPENCSG #endif // OpenCSG |