summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CGALEvaluator.cc9
-rw-r--r--src/Camera.h13
-rw-r--r--src/GLView.cc3
-rw-r--r--src/MainWindow.h4
-rw-r--r--src/OpenCSGRenderer.cc2
-rw-r--r--src/PlatformUtils.cc81
-rw-r--r--src/PlatformUtils.h2
-rw-r--r--src/QGLView.cc11
-rw-r--r--src/context.cc15
-rw-r--r--src/control.cc1
-rw-r--r--src/export.h1
-rw-r--r--src/export_png.cc44
-rw-r--r--src/imageutils-lodepng.cc7
-rw-r--r--src/import.cc4
-rw-r--r--src/mainwin.cc47
-rw-r--r--src/mathc99.cc6
-rw-r--r--src/mathc99.h1
-rw-r--r--src/module.cc4
-rw-r--r--src/openscad.cc707
-rw-r--r--src/parser.y666
-rw-r--r--src/parsersettings.cc1
-rw-r--r--src/svg.cc110
-rw-r--r--src/version_check.h3
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);
}
diff --git a/src/svg.cc b/src/svg.cc
index a21e844..b3a7afa 100644
--- a/src/svg.cc
+++ b/src/svg.cc
@@ -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
contact: Jan Huwald // Impressum