summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarius Kintel <kintel@sim.no>2010-03-02 18:22:31 (GMT)
committerMarius Kintel <marius@kintel.net>2010-10-31 00:42:34 (GMT)
commit393c5a19fedfa4f97ca939fbcf52c2ccab1cde6a (patch)
treefbcb75d32e8763aac3f0ad28528936a0ec11930b /src
parent746159d1838e895e80725cdc892f7bef85feb1af (diff)
Committed current version of visitor refactoring
Diffstat (limited to 'src')
-rw-r--r--src/cgaladv.cc43
-rw-r--r--src/csgnode.h33
-rw-r--r--src/csgops.cc65
-rw-r--r--src/dxflinextrude.cc56
-rw-r--r--src/dxflinextrudenode.h30
-rw-r--r--src/dxfrotextrude.cc45
-rw-r--r--src/dxfrotextrudenode.h28
-rw-r--r--src/import.cc60
-rw-r--r--src/importnode.h32
-rw-r--r--src/mainwin.cc2
-rw-r--r--src/node.cc63
-rw-r--r--src/node.h42
-rw-r--r--src/nodecache.h33
-rw-r--r--src/nodedumper.cc98
-rw-r--r--src/nodedumper.h37
-rw-r--r--src/openscad.cc15
-rw-r--r--src/polyset.cc10
-rw-r--r--src/polyset.h2
-rw-r--r--src/primitives.cc50
-rw-r--r--src/printutils.cc3
-rw-r--r--src/projection.cc30
-rw-r--r--src/projectionnode.h24
-rw-r--r--src/render.cc31
-rw-r--r--src/state.h28
-rw-r--r--src/surface.cc19
-rw-r--r--src/transform.cc48
-rw-r--r--src/traverser.cc40
-rw-r--r--src/traverser.h26
-rw-r--r--src/value.h1
-rw-r--r--src/visitor.h52
30 files changed, 882 insertions, 164 deletions
diff --git a/src/cgaladv.cc b/src/cgaladv.cc
index 829bc84..e391ea8 100644
--- a/src/cgaladv.cc
+++ b/src/cgaladv.cc
@@ -29,6 +29,8 @@
#include "builtin.h"
#include "printutils.h"
#include "cgal.h"
+#include "visitor.h"
+#include <sstream>
#ifdef ENABLE_CGAL
extern CGAL_Nef_polyhedron3 minkowski3(CGAL_Nef_polyhedron3 a, CGAL_Nef_polyhedron3 b);
@@ -52,15 +54,21 @@ public:
class CgaladvNode : public AbstractNode
{
public:
+ CgaladvNode(const ModuleInstantiation *mi, cgaladv_type_e type) : AbstractNode(mi), type(type) {
+ convexity = 1;
+ }
+ virtual ~CgaladvNode() { }
+ virtual Response accept(const class State &state, Visitor &visitor) const {
+ return visitor.visit(state, *this);
+ }
+ virtual std::string toString() const;
+
Value path;
QString subdiv_type;
int convexity, level;
cgaladv_type_e type;
- CgaladvNode(const ModuleInstantiation *mi, cgaladv_type_e type) : AbstractNode(mi), type(type) {
- convexity = 1;
- }
#ifdef ENABLE_CGAL
- virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual CGAL_Nef_polyhedron renderCSGMesh() const;
#endif
virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const;
virtual QString dump(QString indent) const;
@@ -128,7 +136,7 @@ void register_builtin_cgaladv()
#ifdef ENABLE_CGAL
-CGAL_Nef_polyhedron CgaladvNode::render_cgal_nef_polyhedron() const
+CGAL_Nef_polyhedron CgaladvNode::renderCSGMesh() const
{
QString cache_id = mk_cache_id();
if (cgal_nef_cache.contains(cache_id)) {
@@ -147,11 +155,11 @@ CGAL_Nef_polyhedron CgaladvNode::render_cgal_nef_polyhedron() const
if (v->modinst->tag_background)
continue;
if (first) {
- N = v->render_cgal_nef_polyhedron();
+ N = v->renderCsgMesh();
if (N.dim != 0)
first = false;
} else {
- CGAL_Nef_polyhedron tmp = v->render_cgal_nef_polyhedron();
+ CGAL_Nef_polyhedron tmp = v->renderCsgMesh();
if (N.dim == 3 && tmp.dim == 3) {
N.p3 = minkowski3(N.p3, tmp.p3);
}
@@ -224,3 +232,24 @@ QString CgaladvNode::dump(QString indent) const
return dump_cache;
}
+std::string CgaladvNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": ";
+
+ switch (type) {
+ case MINKOWSKI:
+ stream << "minkowski(convexity = " << this->convexity << ")";
+ break;
+ case GLIDE:
+ stream << "glide(path = " << this->path.dump() << ", convexity = " << this->convexity << ")";
+ break;
+ case SUBDIV:
+ stream << "subdiv(level = " << this->level << ", convexity = " << this->convexity << ")";
+ break;
+ default:
+ assert(false);
+ }
+
+ return stream.str();
+}
diff --git a/src/csgnode.h b/src/csgnode.h
new file mode 100644
index 0000000..405dd96
--- /dev/null
+++ b/src/csgnode.h
@@ -0,0 +1,33 @@
+#ifndef CSGNODE_H_
+#define CSGNODE_H_
+
+#include "node.h"
+#include "visitor.h"
+#ifdef ENABLE_CGAL
+# include "cgal.h"
+#endif
+
+enum csg_type_e {
+ CSG_TYPE_UNION,
+ CSG_TYPE_DIFFERENCE,
+ CSG_TYPE_INTERSECTION
+};
+
+class CsgNode : public AbstractNode
+{
+public:
+ csg_type_e type;
+ CsgNode(const ModuleInstantiation *mi, csg_type_e type) : AbstractNode(mi), type(type) { }
+ virtual Response accept(const class State &state, Visitor &visitor) const {
+ return visitor.visit(state, *this);
+ }
+ virtual std::string toString() const;
+
+#ifdef ENABLE_CGAL
+ virtual CGAL_Nef_polyhedron renderCSGMesh() const;
+#endif
+ CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const;
+ virtual QString dump(QString indent) const;
+};
+
+#endif
diff --git a/src/csgops.cc b/src/csgops.cc
index ae97085..5baa149 100644
--- a/src/csgops.cc
+++ b/src/csgops.cc
@@ -23,22 +23,13 @@
*
*/
+#include "csgnode.h"
+
#include "module.h"
-#include "node.h"
#include "csgterm.h"
#include "builtin.h"
#include "printutils.h"
-#ifdef ENABLE_CGAL
-# include "cgal.h"
-# include <CGAL/assertions_behaviour.h>
-# include <CGAL/exceptions.h>
-#endif
-
-enum csg_type_e {
- CSG_TYPE_UNION,
- CSG_TYPE_DIFFERENCE,
- CSG_TYPE_INTERSECTION
-};
+#include <sstream>
class CsgModule : public AbstractModule
{
@@ -48,18 +39,6 @@ public:
virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
};
-class CsgNode : public AbstractNode
-{
-public:
- csg_type_e type;
- CsgNode(const ModuleInstantiation *mi, csg_type_e type) : AbstractNode(mi), type(type) { }
-#ifdef ENABLE_CGAL
- virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
-#endif
- CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const;
- virtual QString dump(QString indent) const;
-};
-
AbstractNode *CsgModule::evaluate(const Context*, const ModuleInstantiation *inst) const
{
CsgNode *node = new CsgNode(inst, type);
@@ -73,7 +52,7 @@ AbstractNode *CsgModule::evaluate(const Context*, const ModuleInstantiation *ins
#ifdef ENABLE_CGAL
-CGAL_Nef_polyhedron CsgNode::render_cgal_nef_polyhedron() const
+CGAL_Nef_polyhedron CsgNode::renderCSGMesh() const
{
QString cache_id = mk_cache_id();
if (cgal_nef_cache.contains(cache_id)) {
@@ -92,24 +71,24 @@ CGAL_Nef_polyhedron CsgNode::render_cgal_nef_polyhedron() const
if (v->modinst->tag_background)
continue;
if (first) {
- N = v->render_cgal_nef_polyhedron();
+ N = v->renderCSGMesh();
if (N.dim != 0)
first = false;
} else if (N.dim == 2) {
if (type == CSG_TYPE_UNION) {
- N.p2 += v->render_cgal_nef_polyhedron().p2;
+ N.p2 += v->renderCSGMesh().p2;
} else if (type == CSG_TYPE_DIFFERENCE) {
- N.p2 -= v->render_cgal_nef_polyhedron().p2;
+ N.p2 -= v->renderCSGMesh().p2;
} else if (type == CSG_TYPE_INTERSECTION) {
- N.p2 *= v->render_cgal_nef_polyhedron().p2;
+ N.p2 *= v->renderCSGMesh().p2;
}
} else if (N.dim == 3) {
if (type == CSG_TYPE_UNION) {
- N.p3 += v->render_cgal_nef_polyhedron().p3;
+ N.p3 += v->renderCSGMesh().p3;
} else if (type == CSG_TYPE_DIFFERENCE) {
- N.p3 -= v->render_cgal_nef_polyhedron().p3;
+ N.p3 -= v->renderCSGMesh().p3;
} else if (type == CSG_TYPE_INTERSECTION) {
- N.p3 *= v->render_cgal_nef_polyhedron().p3;
+ N.p3 *= v->renderCSGMesh().p3;
}
}
v->progress_report();
@@ -172,6 +151,28 @@ QString CsgNode::dump(QString indent) const
return dump_cache;
}
+std::string CsgNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": ";
+
+ switch (this->type) {
+ case CSG_TYPE_UNION:
+ stream << "union()";
+ break;
+ case CSG_TYPE_DIFFERENCE:
+ stream << "difference()";
+ break;
+ case CSG_TYPE_INTERSECTION:
+ stream << "intersection()";
+ break;
+ default:
+ assert(false);
+ }
+
+ return stream.str();
+}
+
void register_builtin_csgops()
{
builtin_modules["union"] = new CsgModule(CSG_TYPE_UNION);
diff --git a/src/dxflinextrude.cc b/src/dxflinextrude.cc
index 83c3d9c..1f6bc8c 100644
--- a/src/dxflinextrude.cc
+++ b/src/dxflinextrude.cc
@@ -23,8 +23,9 @@
*
*/
+#include "dxflinextrudenode.h"
+
#include "module.h"
-#include "node.h"
#include "context.h"
#include "printutils.h"
#include "builtin.h"
@@ -32,11 +33,13 @@
#include "dxftess.h"
#include "polyset.h"
#include "progress.h"
+#include "visitor.h"
#include "openscad.h" // get_fragments_from_r()
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <sstream>
#include <QApplication>
#include <QTime>
@@ -49,24 +52,6 @@ public:
virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
};
-class DxfLinearExtrudeNode : public AbstractPolyNode
-{
-public:
- int convexity, slices;
- double fn, fs, fa, height, twist;
- double origin_x, origin_y, scale;
- bool center, has_twist;
- QString filename, layername;
- DxfLinearExtrudeNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {
- convexity = slices = 0;
- fn = fs = fa = height = twist = 0;
- origin_x = origin_y = scale = 0;
- center = has_twist = false;
- }
- virtual PolySet *render_polyset(render_mode_e mode) const;
- virtual QString dump(QString indent) const;
-};
-
AbstractNode *DxfLinearExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
{
DxfLinearExtrudeNode *node = new DxfLinearExtrudeNode(inst);
@@ -91,10 +76,8 @@ AbstractNode *DxfLinearExtrudeModule::evaluate(const Context *ctx, const ModuleI
Value twist = c.lookup_variable("twist", true);
Value slices = c.lookup_variable("slices", true);
- if(!file.text.isNull())
+ if (!file.text.isNull())
node->filename = c.get_absolute_path(file.text);
- else
- node->filename = file.text;
node->layername = layer.text;
node->height = height.num;
@@ -236,7 +219,7 @@ PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e) const
foreach(AbstractNode * v, children) {
if (v->modinst->tag_background)
continue;
- N.p2 += v->render_cgal_nef_polyhedron().p2;
+ N.p2 += v->renderCSGMesh().p2;
}
dxf = new DxfData(N);
@@ -344,3 +327,30 @@ QString DxfLinearExtrudeNode::dump(QString indent) const
return dump_cache;
}
+std::string DxfLinearExtrudeNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": ";
+
+ QString text;
+ struct stat st;
+ memset(&st, 0, sizeof(struct stat));
+ stat(this->filename.toAscii().data(), &st);
+
+ stream << "linear_extrude("
+ "file = \"" << this->filename << "\", "
+ "cache = \"" << std::hex << (int)st.st_mtime << "." << (int)st.st_size << "\", "
+ "layer = \"" << this->layername << "\", "
+ "height = " << std::dec << this->height << ", "
+ "origin = [ " << this->origin_x << " " << this->origin_y << " ], "
+ "scale = " << this->scale << ", "
+ "center = " << (this->center?"true":"false") << ", "
+ "convexity = " << this->convexity;
+
+ if (this->has_twist) {
+ stream << ", twist = " << this->twist << ", slices = " << this->slices;
+ }
+ stream << ", $fn = " << this->fn << ", $fa = " << this->fa << ", $fs = " << this->fs << ")";
+
+ return stream.str();
+}
diff --git a/src/dxflinextrudenode.h b/src/dxflinextrudenode.h
new file mode 100644
index 0000000..2df52c8
--- /dev/null
+++ b/src/dxflinextrudenode.h
@@ -0,0 +1,30 @@
+#ifndef DXFLINEXTRUDENODE_H_
+#define DXFLINEXTRUDENODE_H_
+
+#include "node.h"
+#include "visitor.h"
+
+class DxfLinearExtrudeNode : public AbstractPolyNode
+{
+public:
+ DxfLinearExtrudeNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {
+ convexity = slices = 0;
+ fn = fs = fa = height = twist = 0;
+ origin_x = origin_y = scale = 0;
+ center = has_twist = false;
+ }
+ virtual Response accept(const class State &state, Visitor &visitor) const {
+ return visitor.visit(state, *this);
+ }
+ virtual std::string toString() const;
+
+ int convexity, slices;
+ double fn, fs, fa, height, twist;
+ double origin_x, origin_y, scale;
+ bool center, has_twist;
+ QString filename, layername;
+ virtual PolySet *render_polyset(render_mode_e mode) const;
+ virtual QString dump(QString indent) const;
+};
+
+#endif
diff --git a/src/dxfrotextrude.cc b/src/dxfrotextrude.cc
index ea603f0..98f91f3 100644
--- a/src/dxfrotextrude.cc
+++ b/src/dxfrotextrude.cc
@@ -23,19 +23,21 @@
*
*/
+#include "dxfrotextrudenode.h"
#include "module.h"
-#include "node.h"
#include "context.h"
#include "printutils.h"
#include "builtin.h"
#include "polyset.h"
#include "dxfdata.h"
#include "progress.h"
+#include "visitor.h"
#include "openscad.h" // get_fragments_from_r()
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <sstream>
#include <QTime>
#include <QApplication>
@@ -48,22 +50,6 @@ public:
virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
};
-class DxfRotateExtrudeNode : public AbstractPolyNode
-{
-public:
- int convexity;
- double fn, fs, fa;
- double origin_x, origin_y, scale;
- QString filename, layername;
- DxfRotateExtrudeNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {
- convexity = 0;
- fn = fs = fa = 0;
- origin_x = origin_y = scale = 0;
- }
- virtual PolySet *render_polyset(render_mode_e mode) const;
- virtual QString dump(QString indent) const;
-};
-
AbstractNode *DxfRotateExtrudeModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
{
DxfRotateExtrudeNode *node = new DxfRotateExtrudeNode(inst);
@@ -84,10 +70,8 @@ AbstractNode *DxfRotateExtrudeModule::evaluate(const Context *ctx, const ModuleI
Value origin = c.lookup_variable("origin", true);
Value scale = c.lookup_variable("scale", true);
- if(!file.text.isNull())
+ if (!file.text.isNull())
node->filename = c.get_absolute_path(file.text);
- else
- node->filename = file.text;
node->layername = layer.text;
node->convexity = (int)convexity.num;
@@ -136,7 +120,7 @@ PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e) const
foreach(AbstractNode * v, children) {
if (v->modinst->tag_background)
continue;
- N.p2 += v->render_cgal_nef_polyhedron().p2;
+ N.p2 += v->renderCSGMesh().p2;
}
dxf = new DxfData(N);
@@ -234,3 +218,22 @@ QString DxfRotateExtrudeNode::dump(QString indent) const
return dump_cache;
}
+std::string DxfRotateExtrudeNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": ";
+
+ struct stat st;
+ memset(&st, 0, sizeof(struct stat));
+ stat(filename.toAscii().data(), &st);
+ stream << "rotate_extrude("
+ "file = \"" << this->filename << "\", "
+ "cache = \"" << std::hex << (int)st.st_mtime << "." << (int)st.st_size << "\", "
+ "layer = \"" << this->layername << "\", "
+ "origin = [ " << std::dec << this->origin_x << " " << this->origin_y << " ], "
+ "scale = " << this->scale << ", "
+ "convexity = " << this->convexity << ", "
+ "$fn = " << this->fn << ", $fa = " << this->fa << ", $fs = " << this->fs << ")";
+
+ return stream.str();
+}
diff --git a/src/dxfrotextrudenode.h b/src/dxfrotextrudenode.h
new file mode 100644
index 0000000..fbe2b85
--- /dev/null
+++ b/src/dxfrotextrudenode.h
@@ -0,0 +1,28 @@
+#ifndef DXFROTEXTRUDENODE_H_
+#define DXFROTEXTRUDENODE_H_
+
+#include "node.h"
+#include "visitor.h"
+
+class DxfRotateExtrudeNode : public AbstractPolyNode
+{
+public:
+ DxfRotateExtrudeNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {
+ convexity = 0;
+ fn = fs = fa = 0;
+ origin_x = origin_y = scale = 0;
+ }
+ virtual Response accept(const class State &state, Visitor &visitor) const {
+ return visitor.visit(state, *this);
+ }
+ virtual std::string toString() const;
+
+ int convexity;
+ double fn, fs, fa;
+ double origin_x, origin_y, scale;
+ QString filename, layername;
+ virtual PolySet *render_polyset(render_mode_e mode) const;
+ virtual QString dump(QString indent) const;
+};
+
+#endif
diff --git a/src/import.cc b/src/import.cc
index bab13ae..5d0a497 100644
--- a/src/import.cc
+++ b/src/import.cc
@@ -23,8 +23,9 @@
*
*/
+#include "importnode.h"
+
#include "module.h"
-#include "node.h"
#include "polyset.h"
#include "context.h"
#include "builtin.h"
@@ -36,12 +37,7 @@
#include <QFile>
#include <sys/types.h>
#include <sys/stat.h>
-
-enum import_type_e {
- TYPE_STL,
- TYPE_OFF,
- TYPE_DXF
-};
+#include <sstream>
class ImportModule : public AbstractModule
{
@@ -51,20 +47,6 @@ public:
virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
};
-class ImportNode : public AbstractPolyNode
-{
-public:
- import_type_e type;
- QString filename;
- QString layername;
- int convexity;
- double fn, fs, fa;
- double origin_x, origin_y, scale;
- ImportNode(const ModuleInstantiation *mi, import_type_e type) : AbstractPolyNode(mi), type(type) { }
- virtual PolySet *render_polyset(render_mode_e mode) const;
- virtual QString dump(QString indent) const;
-};
-
AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
{
ImportNode *node = new ImportNode(inst, type);
@@ -231,3 +213,39 @@ QString ImportNode::dump(QString indent) const
return dump_cache;
}
+std::string ImportNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": ";
+
+ QString text;
+ struct stat st;
+ memset(&st, 0, sizeof(struct stat));
+ stat(this->filename.toAscii().data(), &st);
+
+ switch (this->type) {
+ case TYPE_STL:
+ stream << "import_stl(file = \"" << this->filename << "\", "
+ "cache = \"" << std::hex << (int)st.st_mtime << "." << (int)st.st_size << "\", "
+ "convexity = " << std::dec << this->convexity << ")";
+ break;
+ case TYPE_OFF:
+ stream << "import_off(file = \"" << this->filename << "\", "
+ "cache = \"" << std::hex << (int)st.st_mtime << "." << (int)st.st_size << "\", "
+ "convexity = " << std::dec << this->convexity << ")";
+ break;
+ case TYPE_DXF:
+ stream << "import_dxf(file = \"" << this->filename << "\", "
+ "cache = \"" << std::hex << (int)st.st_mtime << "." << (int)st.st_size << "\", "
+ "layer = \"" << this->layername << "\", "
+ "origin = [ " << std::dec << this->origin_x << " " << this->origin_y << " ], "
+ "scale = " << this->scale << ", "
+ "convexity = " << this->convexity << ", "
+ "$fn = " << this->fn << ", $fa = " << this->fa << ", $fs = " << this->fs << ")";
+ break;
+ default:
+ assert(false);
+ }
+
+ return stream.str();
+}
diff --git a/src/importnode.h b/src/importnode.h
new file mode 100644
index 0000000..b226569
--- /dev/null
+++ b/src/importnode.h
@@ -0,0 +1,32 @@
+#ifndef IMPORTNODE_H_
+#define IMPORTNODE_H_
+
+#include "node.h"
+#include "visitor.h"
+
+enum import_type_e {
+ TYPE_STL,
+ TYPE_OFF,
+ TYPE_DXF
+};
+
+class ImportNode : public AbstractPolyNode
+{
+public:
+ ImportNode(const ModuleInstantiation *mi, import_type_e type) : AbstractPolyNode(mi), type(type) { }
+ virtual Response accept(const class State &state, Visitor &visitor) const {
+ return visitor.visit(state, *this);
+ }
+ virtual std::string toString() const;
+
+ import_type_e type;
+ QString filename;
+ QString layername;
+ int convexity;
+ double fn, fs, fa;
+ double origin_x, origin_y, scale;
+ virtual PolySet *render_polyset(render_mode_e mode) const;
+ virtual QString dump(QString indent) const;
+};
+
+#endif
diff --git a/src/mainwin.cc b/src/mainwin.cc
index ef738fc..1bf2695 100644
--- a/src/mainwin.cc
+++ b/src/mainwin.cc
@@ -1126,7 +1126,7 @@ void MainWindow::actionRenderCGAL()
progress_report_prep(root_node, report_func, pd);
try {
- this->root_N = new CGAL_Nef_polyhedron(root_node->render_cgal_nef_polyhedron());
+ this->root_N = new CGAL_Nef_polyhedron(root_node->renderCSGMesh());
}
catch (ProgressCancelException e) {
PRINT("Rendering cancelled.");
diff --git a/src/node.cc b/src/node.cc
index 87a7051..437fdfa 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -29,7 +29,9 @@
#include "csgterm.h"
#include "progress.h"
#include "polyset.h"
+#include "visitor.h"
#include <QRegExp>
+#include <sstream>
int AbstractNode::idx_counter;
@@ -45,6 +47,21 @@ AbstractNode::~AbstractNode()
delete v;
}
+Response AbstractNode::accept(const class State &state, Visitor &visitor) const
+{
+ return visitor.visit(state, *this);
+}
+
+Response AbstractIntersectionNode::accept(const class State &state, Visitor &visitor) const
+{
+ return visitor.visit(state, *this);
+}
+
+Response AbstractPolyNode::accept(const class State &state, Visitor &visitor) const
+{
+ return visitor.visit(state, *this);
+}
+
QString AbstractNode::mk_cache_id() const
{
QString cache_id = dump("");
@@ -79,19 +96,19 @@ static CGAL_Nef_polyhedron render_cgal_nef_polyhedron_backend(const AbstractNode
if (v->modinst->tag_background)
continue;
if (first) {
- N = v->render_cgal_nef_polyhedron();
+ N = v->renderCSGMesh();
if (N.dim != 0)
first = false;
} else if (N.dim == 2) {
if (intersect)
- N.p2 *= v->render_cgal_nef_polyhedron().p2;
+ N.p2 *= v->renderCSGMesh().p2;
else
- N.p2 += v->render_cgal_nef_polyhedron().p2;
+ N.p2 += v->renderCSGMesh().p2;
} else {
if (intersect)
- N.p3 *= v->render_cgal_nef_polyhedron().p3;
+ N.p3 *= v->renderCSGMesh().p3;
else
- N.p3 += v->render_cgal_nef_polyhedron().p3;
+ N.p3 += v->renderCSGMesh().p3;
}
v->progress_report();
}
@@ -103,12 +120,12 @@ static CGAL_Nef_polyhedron render_cgal_nef_polyhedron_backend(const AbstractNode
return N;
}
-CGAL_Nef_polyhedron AbstractNode::render_cgal_nef_polyhedron() const
+CGAL_Nef_polyhedron AbstractNode::renderCSGMesh() const
{
return render_cgal_nef_polyhedron_backend(this, false);
}
-CGAL_Nef_polyhedron AbstractIntersectionNode::render_cgal_nef_polyhedron() const
+CGAL_Nef_polyhedron AbstractIntersectionNode::renderCSGMesh() const
{
return render_cgal_nef_polyhedron_backend(this, true);
}
@@ -159,10 +176,17 @@ QString AbstractNode::dump(QString indent) const
return dump_cache;
}
+std::string AbstractNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": group()";
+ return stream.str();
+}
+
QString AbstractIntersectionNode::dump(QString indent) const
{
if (dump_cache.isEmpty()) {
- QString text = indent + QString("n%1: intersection() {\n").arg(idx);
+ QString text = indent + QString::fromStdString(this->toString()) + " {\n";
foreach (AbstractNode *v, children)
text += v->dump(indent + QString("\t"));
((AbstractNode*)this)->dump_cache = text + indent + "}\n";
@@ -170,6 +194,13 @@ QString AbstractIntersectionNode::dump(QString indent) const
return dump_cache;
}
+std::string AbstractIntersectionNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": intersection()";
+ return stream.str();
+}
+
void AbstractNode::progress_prepare()
{
foreach (AbstractNode *v, children)
@@ -184,7 +215,7 @@ void AbstractNode::progress_report() const
#ifdef ENABLE_CGAL
-CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const
+CGAL_Nef_polyhedron AbstractPolyNode::renderCSGMesh() const
{
QString cache_id = mk_cache_id();
if (cgal_nef_cache.contains(cache_id)) {
@@ -197,7 +228,7 @@ CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const
PolySet *ps = render_polyset(RENDER_CGAL);
try {
- CGAL_Nef_polyhedron N = ps->render_cgal_nef_polyhedron();
+ CGAL_Nef_polyhedron N = ps->renderCSGMesh();
cgal_nef_cache.insert(cache_id, new cgal_nef_cache_entry(N), N.weight());
print_messages_pop();
progress_report();
@@ -231,3 +262,15 @@ CSGTerm *AbstractPolyNode::render_csg_term_from_ps(double m[20], QVector<CSGTerm
return t;
}
+std::ostream &operator<<(std::ostream &stream, const QString &str)
+{
+ stream << str.toStdString();
+ return stream;
+}
+
+std::ostream &operator<<(std::ostream &stream, const AbstractNode &node)
+{
+ stream << node.toString();
+ return stream;
+}
+
diff --git a/src/node.h b/src/node.h
index 2e1d718..08a5cb1 100644
--- a/src/node.h
+++ b/src/node.h
@@ -8,6 +8,8 @@
#include "cgal.h"
#endif
+#include "traverser.h"
+
extern int progress_report_count;
extern void (*progress_report_f)(const class AbstractNode*, void*, int);
extern void *progress_report_vp;
@@ -19,20 +21,31 @@ class AbstractNode
{
static int idx_counter; // Node instantiation index
public:
+ AbstractNode(const class ModuleInstantiation *mi);
+ virtual ~AbstractNode();
+ virtual Response accept(const class State &state, class Visitor &visitor) const;
+ virtual std::string toString() const;
+
+ // FIXME: Make return value a reference
+ const std::list<AbstractNode*> getChildren() const {
+ return this->children.toList().toStdList();
+ }
+ int index() const { return this->idx; }
+
static void resetIndexCounter() { idx_counter = 1; }
QVector<AbstractNode*> children;
- const class ModuleInstantiation *modinst;
-
+ const ModuleInstantiation *modinst;
+
int progress_mark;
void progress_prepare();
void progress_report() const;
- int idx;
+ int idx; // Node index (unique per tree)
QString dump_cache;
- AbstractNode(const ModuleInstantiation *mi);
- virtual ~AbstractNode();
+
+
virtual QString mk_cache_id() const;
#ifdef ENABLE_CGAL
struct cgal_nef_cache_entry {
@@ -41,7 +54,7 @@ public:
cgal_nef_cache_entry(const CGAL_Nef_polyhedron &N);
};
static QCache<QString, cgal_nef_cache_entry> cgal_nef_cache;
- virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual CGAL_Nef_polyhedron renderCSGMesh() const;
class CSGTerm *render_csg_term_from_nef(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, const char *statement, int convexity) const;
#endif
virtual class CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const;
@@ -52,8 +65,12 @@ class AbstractIntersectionNode : public AbstractNode
{
public:
AbstractIntersectionNode(const ModuleInstantiation *mi) : AbstractNode(mi) { };
+ virtual ~AbstractIntersectionNode() { };
+ virtual Response accept(const class State &state, class Visitor &visitor) const;
+ virtual std::string toString() const;
+
#ifdef ENABLE_CGAL
- virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual CGAL_Nef_polyhedron renderCSGMesh() const;
#endif
virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const;
virtual QString dump(QString indent) const;
@@ -62,17 +79,24 @@ public:
class AbstractPolyNode : public AbstractNode
{
public:
+ AbstractPolyNode(const ModuleInstantiation *mi) : AbstractNode(mi) { };
+ virtual ~AbstractPolyNode() { };
+ virtual Response accept(const class State &state, class Visitor &visitor) const;
+
enum render_mode_e {
RENDER_CGAL,
RENDER_OPENCSG
};
- AbstractPolyNode(const ModuleInstantiation *mi) : AbstractNode(mi) { };
virtual class PolySet *render_polyset(render_mode_e mode) const = 0;
#ifdef ENABLE_CGAL
- virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual CGAL_Nef_polyhedron renderCSGMesh() const;
#endif
virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const;
static CSGTerm *render_csg_term_from_ps(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, PolySet *ps, const ModuleInstantiation *modinst, int idx);
};
+std::ostream &operator<<(std::ostream &stream, const AbstractNode &node);
+// FIXME: Doesn't belong here..
+std::ostream &operator<<(std::ostream &stream, const QString &str);
+
#endif
diff --git a/src/nodecache.h b/src/nodecache.h
new file mode 100644
index 0000000..c5a5524
--- /dev/null
+++ b/src/nodecache.h
@@ -0,0 +1,33 @@
+#ifndef NODECACHE_H_
+#define NODECACHE_H_
+
+#include <vector>
+#include "node.h"
+
+template <class T>
+class NodeCache
+{
+public:
+ NodeCache() { }
+ virtual ~NodeCache() { }
+
+ const T & operator[](const AbstractNode &node) const {
+ if (this->cache.size() > node.index()) return this->cache[node.index()];
+ else return nullvalue;
+ }
+
+ void insert(const class AbstractNode &node, const T & value) {
+ this->cache.resize(node.index() + 1);
+ this->cache[node.index()] = value;
+ }
+
+ void remove(const class AbstractNode &node) {
+ if (this->cache.size() > node.index()) this->cache[node.index()] = nullvalue;
+ }
+
+private:
+ std::vector<T> cache;
+ T nullvalue;
+};
+
+#endif
diff --git a/src/nodedumper.cc b/src/nodedumper.cc
new file mode 100644
index 0000000..1956a89
--- /dev/null
+++ b/src/nodedumper.cc
@@ -0,0 +1,98 @@
+#include "nodedumper.h"
+#include <string>
+#include <map>
+#include <list>
+#include "visitor.h"
+#include "state.h"
+#include "nodecache.h"
+
+#include <sstream>
+#include <iostream>
+
+// For compatibility with old dump() output
+#define NODEDUMPER_COMPAT_MODE
+#ifdef NODEDUMPER_COMPAT_MODE
+#include "dxflinextrudenode.h"
+#include "dxfrotextrudenode.h"
+#include "projectionnode.h"
+#endif
+
+
+bool NodeDumper::isCached(const AbstractNode &node)
+{
+ return !this->cache[node].empty();
+}
+
+void NodeDumper::handleIndent(const State &state)
+{
+ if (state.isPrefix()) {
+ this->currindent += "\t";
+ }
+ else if (state.isPostfix()) {
+ this->currindent.erase((this->currindent.length() >= 1) ?
+ this->currindent.length() - 1 : 0);
+ }
+}
+
+string NodeDumper::dumpChildren(const AbstractNode &node)
+{
+ std::stringstream dump;
+ if (!this->visitedchildren[node.index()].empty()) {
+ dump << " {\n";
+
+ for (ChildList::const_iterator iter = this->visitedchildren[node.index()].begin();
+ iter != this->visitedchildren[node.index()].end();
+ iter++) {
+ dump << this->cache[**iter] << "\n";
+ }
+
+ dump << this->currindent << "}";
+ }
+ else {
+#ifndef NODEDUMPER_COMPAT_MODE
+ dump << ";";
+#else
+ if (dynamic_cast<const AbstractPolyNode*>(&node) &&
+ !dynamic_cast<const ProjectionNode*>(&node) &&
+ !dynamic_cast<const DxfRotateExtrudeNode*>(&node) &&
+ !dynamic_cast<const DxfLinearExtrudeNode*>(&node)) dump << ";";
+ else dump << " {\n" << this->currindent << "}";
+#endif
+ }
+ return dump.str();
+}
+
+
+Response NodeDumper::visit(const State &state, const AbstractNode &node)
+{
+ if (isCached(node)) return PruneTraversal;
+ else handleIndent(state);
+ if (state.isPostfix()) {
+ std::stringstream dump;
+ dump << this->currindent << node;
+ dump << dumpChildren(node);
+ this->cache.insert(node, dump.str());
+ }
+
+ handleVisitedChildren(state, node);
+ return ContinueTraversal;
+}
+
+const string &NodeDumper::getDump() const
+{
+ assert(this->root);
+ return this->cache[*this->root];
+}
+
+void NodeDumper::handleVisitedChildren(const State &state, const AbstractNode &node)
+{
+ if (state.isPostfix()) {
+ this->visitedchildren.erase(node.index());
+ if (!state.parent()) {
+ this->root = &node;
+ }
+ else {
+ this->visitedchildren[state.parent()->index()].push_back(&node);
+ }
+ }
+}
diff --git a/src/nodedumper.h b/src/nodedumper.h
new file mode 100644
index 0000000..568d578
--- /dev/null
+++ b/src/nodedumper.h
@@ -0,0 +1,37 @@
+#ifndef NODEDUMPER_H_
+#define NODEDUMPER_H_
+
+#include <string>
+#include <map>
+#include <list>
+#include "visitor.h"
+#include "nodecache.h"
+
+using std::string;
+using std::map;
+using std::list;
+
+class NodeDumper : public Visitor
+{
+public:
+ NodeDumper() : root(NULL) {}
+ virtual ~NodeDumper() {}
+
+ virtual Response visit(const State &state, const AbstractNode &node);
+
+ const string &getDump() const;
+private:
+ void handleVisitedChildren(const State &state, const AbstractNode &node);
+ bool isCached(const AbstractNode &node);
+ void handleIndent(const State &state);
+ string dumpChildren(const AbstractNode &node);
+
+ string currindent;
+ const AbstractNode *root;
+ typedef list<const AbstractNode *> ChildList;
+ map<int, ChildList> visitedchildren;
+ NodeCache<string> cache;
+};
+
+
+#endif
diff --git a/src/openscad.cc b/src/openscad.cc
index bf24c9f..fdd2502 100644
--- a/src/openscad.cc
+++ b/src/openscad.cc
@@ -31,6 +31,7 @@
#include "value.h"
#include "export.h"
#include "builtin.h"
+#include "nodedumper.h"
#ifdef ENABLE_CGAL
#include "cgal.h"
@@ -284,8 +285,20 @@ int main(int argc, char **argv)
AbstractNode::resetIndexCounter();
root_node = root_module->evaluate(&root_ctx, &root_inst);
+ NodeDumper dumper;
+ Traverser trav(dumper, *root_node, Traverser::PRE_AND_POSTFIX);
+ trav.execute();
+// std::cout << dumper.getDump();
+// std::cout << std::endl;
+// trav.execute();
+// std::cout << dumper.getDump();
+// std::cout << std::endl;
+ printf(dumper.getDump().c_str());
+ exit(1);
+
+
CGAL_Nef_polyhedron *root_N;
- root_N = new CGAL_Nef_polyhedron(root_node->render_cgal_nef_polyhedron());
+ root_N = new CGAL_Nef_polyhedron(root_node->renderCSGMesh());
QDir::setCurrent(original_path.absolutePath());
diff --git a/src/polyset.cc b/src/polyset.cc
index d438769..4548f8a 100644
--- a/src/polyset.cc
+++ b/src/polyset.cc
@@ -144,7 +144,9 @@ void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, double *m
bool mirrored = m3f.determinant() < 0;
if (colormode == COLORMODE_MATERIAL) {
- const QColor &col = Preferences::inst()->color(Preferences::OPENCSG_FACE_FRONT_COLOR);
+// FIXME: Reenable/rewrite - don't be dependant on GUI
+// const QColor &col = Preferences::inst()->color(Preferences::OPENCSG_FACE_FRONT_COLOR);
+ const QColor &col = QColor(0xf9, 0xd7, 0x2c);
glColor3f(col.redF(), col.greenF(), col.blueF());
#ifdef ENABLE_OPENCSG
if (shaderinfo) {
@@ -154,7 +156,9 @@ void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, double *m
#endif /* ENABLE_OPENCSG */
}
if (colormode == COLORMODE_CUTOUT) {
- const QColor &col = Preferences::inst()->color(Preferences::OPENCSG_FACE_BACK_COLOR);
+// FIXME: Reenable/rewrite - don't be dependant on GUI
+// const QColor &col = Preferences::inst()->color(Preferences::OPENCSG_FACE_BACK_COLOR);
+ const QColor &col = QColor(0x9d, 0xcb, 0x51);
glColor3f(col.redF(), col.greenF(), col.blueF());
#ifdef ENABLE_OPENCSG
if (shaderinfo) {
@@ -407,7 +411,7 @@ public:
}
};
-CGAL_Nef_polyhedron PolySet::render_cgal_nef_polyhedron() const
+CGAL_Nef_polyhedron PolySet::renderCSGMesh() const
{
if (this->is2d)
{
diff --git a/src/polyset.h b/src/polyset.h
index 0914e91..074f82e 100644
--- a/src/polyset.h
+++ b/src/polyset.h
@@ -78,7 +78,7 @@ public:
void render_edges(colormode_e colormode, csgmode_e csgmode) const;
#ifdef ENABLE_CGAL
- CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ CGAL_Nef_polyhedron renderCSGMesh() const;
#endif
int refcount;
diff --git a/src/primitives.cc b/src/primitives.cc
index ac1f0a3..8838547 100644
--- a/src/primitives.cc
+++ b/src/primitives.cc
@@ -32,6 +32,8 @@
#include "builtin.h"
#include "printutils.h"
#include <assert.h>
+#include "visitor.h"
+#include <sstream>
enum primitive_type_e {
CUBE,
@@ -54,13 +56,18 @@ public:
class PrimitiveNode : public AbstractPolyNode
{
public:
+ PrimitiveNode(const ModuleInstantiation *mi, primitive_type_e type) : AbstractPolyNode(mi), type(type) { }
+ virtual Response accept(const class State &state, Visitor &visitor) const {
+ return visitor.visit(state, *this);
+ }
+ virtual std::string toString() const;
+
bool center;
double x, y, z, h, r1, r2;
double fn, fs, fa;
primitive_type_e type;
int convexity;
Value points, paths, triangles;
- PrimitiveNode(const ModuleInstantiation *mi, primitive_type_e type) : AbstractPolyNode(mi), type(type) { }
virtual PolySet *render_polyset(render_mode_e mode) const;
virtual QString dump(QString indent) const;
};
@@ -542,3 +549,44 @@ QString PrimitiveNode::dump(QString indent) const
return dump_cache;
}
+std::string PrimitiveNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": ";
+
+ switch (this->type) {
+ case CUBE:
+ stream << "cube(size = [" << this->x << ", " << this->y << ", " << this->z << "], "
+ << "center = " << (center ? "true" : "false") << ")";
+ break;
+ case SPHERE:
+ stream << "sphere($fn = " << this->fn << ", $fa = " << this->fa
+ << ", $fs = " << this->fs << ", r = " << this->r1 << ")";
+ break;
+ case CYLINDER:
+ stream << "cylinder($fn = " << this->fn << ", $fa = " << this->fa
+ << ", $fs = " << this->fs << ", h = " << this->h << ", r1 = " << this->r1
+ << ", r2 = " << this->r2 << ", center = " << (center ? "true" : "false") << ")";
+ break;
+ case POLYHEDRON:
+ stream << "polyhedron(points = " << this->points.dump()
+ << ", triangles = " << this->triangles.dump()
+ << ", convexity = " << this->convexity << ")";
+ break;
+ case SQUARE:
+ stream << "square(size = [" << this->x << ", " << this->y << "], "
+ << "center = " << (center ? "true" : "false") << ")";
+ break;
+ case CIRCLE:
+ stream << "circle($fn = " << this->fn << ", $fa = " << this->fa
+ << ", $fs = " << this->fs << ", r = " << this->r1 << ")";
+ break;
+ case POLYGON:
+ stream << "polygon(points = " << this->points.dump() << ", paths = " << this->paths.dump() << ", convexity = " << this->convexity << ")";
+ break;
+ default:
+ assert(false);
+ }
+
+ return stream.str();
+}
diff --git a/src/printutils.cc b/src/printutils.cc
index 8830a8c..0f4c67d 100644
--- a/src/printutils.cc
+++ b/src/printutils.cc
@@ -18,8 +18,7 @@ void print_messages_push()
void print_messages_pop()
{
- QString msg = print_messages_stack.last();
- print_messages_stack.removeLast();
+ QString msg = print_messages_stack.takeLast();
if (print_messages_stack.size() > 0 && !msg.isNull()) {
if (!print_messages_stack.last().isEmpty())
print_messages_stack.last() += "\n";
diff --git a/src/projection.cc b/src/projection.cc
index 7a3f77a..985ed20 100644
--- a/src/projection.cc
+++ b/src/projection.cc
@@ -23,8 +23,8 @@
*
*/
+#include "projectionnode.h"
#include "module.h"
-#include "node.h"
#include "context.h"
#include "printutils.h"
#include "builtin.h"
@@ -33,6 +33,7 @@
#include "polyset.h"
#include "export.h"
#include "progress.h"
+#include "visitor.h"
#ifdef ENABLE_CGAL
# include <CGAL/assertions_behaviour.h>
@@ -43,6 +44,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <assert.h>
+#include <sstream>
#include <QApplication>
#include <QTime>
@@ -55,18 +57,6 @@ public:
virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
};
-class ProjectionNode : public AbstractPolyNode
-{
-public:
- int convexity;
- bool cut_mode;
- ProjectionNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {
- cut_mode = false;
- }
- virtual PolySet *render_polyset(render_mode_e mode) const;
- virtual QString dump(QString indent) const;
-};
-
AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
{
ProjectionNode *node = new ProjectionNode(inst);
@@ -122,7 +112,7 @@ PolySet *ProjectionNode::render_polyset(render_mode_e) const
foreach(AbstractNode *v, this->children) {
if (v->modinst->tag_background)
continue;
- N.p3 += v->render_cgal_nef_polyhedron().p3;
+ N.p3 += v->renderCSGMesh().p3;
}
}
catch (CGAL::Assertion_exception e) {
@@ -173,7 +163,7 @@ PolySet *ProjectionNode::render_polyset(render_mode_e) const
cube->append_vertex(x1, y1, z1);
cube->append_vertex(x1, y1, z2);
cube->append_vertex(x1, y2, z2);
- CGAL_Nef_polyhedron Ncube = cube->render_cgal_nef_polyhedron();
+ CGAL_Nef_polyhedron Ncube = cube->renderCSGMesh();
cube->unlink();
// N.p3 *= CGAL_Nef_polyhedron3(CGAL_Plane(0, 0, 1, 0), CGAL_Nef_polyhedron3::INCLUDED);
@@ -298,3 +288,13 @@ QString ProjectionNode::dump(QString indent) const
return dump_cache;
}
+std::string ProjectionNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": ";
+
+ stream << "projection(cut = " << (this->cut_mode ? "true" : "false")
+ << ", convexity = " << this->convexity << ")";
+
+ return stream.str();
+}
diff --git a/src/projectionnode.h b/src/projectionnode.h
new file mode 100644
index 0000000..d5ba6da
--- /dev/null
+++ b/src/projectionnode.h
@@ -0,0 +1,24 @@
+#ifndef PROJECTIONNODE_H_
+#define PROJECTIONNODE_H_
+
+#include "node.h"
+#include "visitor.h"
+
+class ProjectionNode : public AbstractPolyNode
+{
+public:
+ ProjectionNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {
+ cut_mode = false;
+ }
+ virtual Response accept(const class State &state, Visitor &visitor) const {
+ return visitor.visit(state, *this);
+ }
+ virtual std::string toString() const;
+
+ int convexity;
+ bool cut_mode;
+ virtual PolySet *render_polyset(render_mode_e mode) const;
+ virtual QString dump(QString indent) const;
+};
+
+#endif
diff --git a/src/render.cc b/src/render.cc
index d851fc8..5bd57fc 100644
--- a/src/render.cc
+++ b/src/render.cc
@@ -33,13 +33,14 @@
#include "builtin.h"
#include "printutils.h"
#include "progress.h"
+#include "visitor.h"
#ifdef ENABLE_CGAL
# include "cgal.h"
#endif
-#include <QProgressDialog>
#include <QApplication>
#include <QTime>
+#include <sstream>
class RenderModule : public AbstractModule
{
@@ -51,10 +52,15 @@ public:
class RenderNode : public AbstractNode
{
public:
- int convexity;
RenderNode(const ModuleInstantiation *mi) : AbstractNode(mi), convexity(1) { }
+ virtual Response accept(const class State &state, Visitor &visitor) const {
+ return visitor.visit(state, *this);
+ }
+ virtual std::string toString() const;
+
+ int convexity;
#ifdef ENABLE_CGAL
- virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual CGAL_Nef_polyhedron renderCSGMesh() const;
#endif
CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const;
virtual QString dump(QString indent) const;
@@ -90,7 +96,7 @@ void register_builtin_render()
#ifdef ENABLE_CGAL
-CGAL_Nef_polyhedron RenderNode::render_cgal_nef_polyhedron() const
+CGAL_Nef_polyhedron RenderNode::renderCSGMesh() const
{
QString cache_id = mk_cache_id();
if (cgal_nef_cache.contains(cache_id)) {
@@ -108,13 +114,13 @@ CGAL_Nef_polyhedron RenderNode::render_cgal_nef_polyhedron() const
if (v->modinst->tag_background)
continue;
if (first) {
- N = v->render_cgal_nef_polyhedron();
+ N = v->renderCSGMesh();
if (N.dim != 0)
first = false;
} else if (N.dim == 2) {
- N.p2 += v->render_cgal_nef_polyhedron().p2;
+ N.p2 += v->renderCSGMesh().p2;
} else if (N.dim == 3) {
- N.p3 += v->render_cgal_nef_polyhedron().p3;
+ N.p3 += v->renderCSGMesh().p3;
}
v->progress_report();
}
@@ -153,7 +159,7 @@ CSGTerm *AbstractNode::render_csg_term_from_nef(double m[20], QVector<CSGTerm*>
QTime t;
t.start();
- N = this->render_cgal_nef_polyhedron();
+ N = this->renderCSGMesh();
int s = t.elapsed() / 1000;
PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
@@ -261,3 +267,12 @@ QString RenderNode::dump(QString indent) const
return dump_cache;
}
+std::string RenderNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": ";
+
+ stream << "render(convexity = " << convexity << ")";
+
+ return stream.str();
+}
diff --git a/src/state.h b/src/state.h
new file mode 100644
index 0000000..7ac8e9f
--- /dev/null
+++ b/src/state.h
@@ -0,0 +1,28 @@
+#ifndef STATE_H_
+#define STATE_H_
+
+class State
+{
+public:
+ State(const class AbstractNode *parent)
+ : parentnode(parent), isprefix(false), ispostfix(false), numchildren(0) { }
+ virtual ~State() {}
+
+ void setPrefix(bool on) { this->isprefix = on; }
+ void setPostfix(bool on) { this->ispostfix = on; }
+ void setNumChildren(unsigned int numc) { this->numchildren = numc; }
+ void setParent(const AbstractNode *parent) { this->parentnode = parent; }
+
+ bool isPrefix() const { return this->isprefix; }
+ bool isPostfix() const { return this->ispostfix; }
+ unsigned int numChildren() const { return this->numchildren; }
+ const AbstractNode *parent() const { return this->parentnode; }
+
+private:
+ const AbstractNode * parentnode;
+ bool isprefix;
+ bool ispostfix;
+ unsigned int numchildren;
+};
+
+#endif
diff --git a/src/surface.cc b/src/surface.cc
index ddcd3a6..57b3f59 100644
--- a/src/surface.cc
+++ b/src/surface.cc
@@ -31,8 +31,10 @@
#include "dxftess.h"
#include "printutils.h"
#include "openscad.h" // handle_dep()
+#include "visitor.h"
#include <QFile>
+#include <sstream>
class SurfaceModule : public AbstractModule
{
@@ -44,10 +46,15 @@ public:
class SurfaceNode : public AbstractPolyNode
{
public:
+ SurfaceNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) { }
+ virtual Response accept(const class State &state, Visitor &visitor) const {
+ return visitor.visit(state, *this);
+ }
+ virtual std::string toString() const;
+
QString filename;
bool center;
int convexity;
- SurfaceNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) { }
virtual PolySet *render_polyset(render_mode_e mode) const;
virtual QString dump(QString indent) const;
};
@@ -208,3 +215,13 @@ QString SurfaceNode::dump(QString indent) const
return dump_cache;
}
+std::string SurfaceNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": ";
+
+ stream << "surface(file = \"" << this->filename
+ << "\", center = " << (this->center ? "true" : "false") << ")";
+
+ return stream.str();
+}
diff --git a/src/transform.cc b/src/transform.cc
index 746283e..8f61c26 100644
--- a/src/transform.cc
+++ b/src/transform.cc
@@ -32,6 +32,8 @@
#include "dxftess.h"
#include "builtin.h"
#include "printutils.h"
+#include "visitor.h"
+#include <sstream>
enum transform_type_e {
SCALE,
@@ -53,10 +55,15 @@ public:
class TransformNode : public AbstractNode
{
public:
- double m[20];
TransformNode(const ModuleInstantiation *mi) : AbstractNode(mi) { }
+ virtual Response accept(const class State &state, Visitor &visitor) const {
+ return visitor.visit(state, *this);
+ }
+ virtual std::string toString() const;
+
+ double m[20];
#ifdef ENABLE_CGAL
- virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
+ virtual CGAL_Nef_polyhedron renderCSGMesh() const;
#endif
virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const;
virtual QString dump(QString indent) const;
@@ -240,7 +247,7 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti
#ifdef ENABLE_CGAL
-CGAL_Nef_polyhedron TransformNode::render_cgal_nef_polyhedron() const
+CGAL_Nef_polyhedron TransformNode::renderCSGMesh() const
{
QString cache_id = mk_cache_id();
if (cgal_nef_cache.contains(cache_id)) {
@@ -258,13 +265,13 @@ CGAL_Nef_polyhedron TransformNode::render_cgal_nef_polyhedron() const
if (v->modinst->tag_background)
continue;
if (first) {
- N = v->render_cgal_nef_polyhedron();
+ N = v->renderCSGMesh();
if (N.dim != 0)
first = false;
} else if (N.dim == 2) {
- N.p2 += v->render_cgal_nef_polyhedron().p2;
+ N.p2 += v->renderCSGMesh().p2;
} else if (N.dim == 3) {
- N.p3 += v->render_cgal_nef_polyhedron().p3;
+ N.p3 += v->renderCSGMesh().p3;
}
v->progress_report();
}
@@ -291,7 +298,7 @@ CGAL_Nef_polyhedron TransformNode::render_cgal_nef_polyhedron() const
ps.is2d = true;
dxf_tesselate(&ps, &dd, 0, true, false, 0);
- N = ps.render_cgal_nef_polyhedron();
+ N = ps.renderCSGMesh();
ps.refcount = 0;
}
if (N.dim == 3) {
@@ -368,6 +375,32 @@ QString TransformNode::dump(QString indent) const
return dump_cache;
}
+std::string TransformNode::toString() const
+{
+ std::stringstream stream;
+ stream << "n" << this->index() << ": ";
+
+ if (m[16] >= 0 || m[17] >= 0 || m[18] >= 0 || m[19] >= 0) {
+ stream << "color([" << m[16] << ", " << m[17] << ", " << m[18] << ", " << m[19] << "])";
+ }
+ else {
+ stream << "multmatrix([";
+ for (int j=0;j<4;j++) {
+ stream << "[";
+ for (int i=0;i<4;i++) {
+ // FIXME: The 0 test is to avoid a leading minus before a single 0 (cosmetics)
+ stream << ((m[i*4+j]==0)?0:m[i*4+j]);
+ if (i != 3) stream << ", ";
+ }
+ stream << "]";
+ if (j != 3) stream << ", ";
+ }
+ stream << "])";
+ }
+
+ return stream.str();
+}
+
void register_builtin_transform()
{
builtin_modules["scale"] = new TransformModule(SCALE);
@@ -377,4 +410,3 @@ void register_builtin_transform()
builtin_modules["multmatrix"] = new TransformModule(MULTMATRIX);
builtin_modules["color"] = new TransformModule(COLOR);
}
-
diff --git a/src/traverser.cc b/src/traverser.cc
new file mode 100644
index 0000000..af29132
--- /dev/null
+++ b/src/traverser.cc
@@ -0,0 +1,40 @@
+#include "traverser.h"
+#include "visitor.h"
+#include "node.h"
+#include "state.h"
+
+void Traverser::execute()
+{
+ State state(NULL);
+ traverse(state, this->root);
+}
+
+void Traverser::traverse(const State &state, const AbstractNode &node)
+{
+ // FIXME: Handle abort
+
+ State newstate = state;
+ newstate.setNumChildren(node.getChildren().size());
+
+ if (traversaltype == PREFIX || traversaltype == PRE_AND_POSTFIX) {
+ newstate.setPrefix(true);
+ newstate.setParent(state.parent());
+ node.accept(newstate, this->visitor);
+ }
+
+ newstate.setParent(&node);
+ const std::list<AbstractNode*> &children = node.getChildren();
+ for (std::list<AbstractNode*>::const_iterator iter = children.begin();
+ iter != children.end();
+ iter++) {
+
+ traverse(newstate, **iter);
+ }
+
+ if (traversaltype == POSTFIX || traversaltype == PRE_AND_POSTFIX) {
+ newstate.setParent(state.parent());
+ newstate.setPrefix(false);
+ newstate.setPostfix(true);
+ node.accept(newstate, this->visitor);
+ }
+}
diff --git a/src/traverser.h b/src/traverser.h
new file mode 100644
index 0000000..80913e3
--- /dev/null
+++ b/src/traverser.h
@@ -0,0 +1,26 @@
+#ifndef TRAVERSER_H_
+#define TRAVERSER_H_
+
+enum Response {ContinueTraversal, AbortTraversal, PruneTraversal};
+
+class Traverser
+{
+public:
+ enum TraversalType {PREFIX, POSTFIX, PRE_AND_POSTFIX};
+
+ Traverser(class Visitor &visitor, const class AbstractNode &root, TraversalType travtype)
+ : visitor(visitor), root(root), traversaltype(travtype) {
+ }
+ virtual ~Traverser() { }
+
+ void execute();
+private:
+ // FIXME: reverse parameters
+ void traverse(const class State &state, const AbstractNode &node);
+
+ Visitor &visitor;
+ const AbstractNode &root;
+ TraversalType traversaltype;
+};
+
+#endif
diff --git a/src/value.h b/src/value.h
index 3491cbb..982d5d8 100644
--- a/src/value.h
+++ b/src/value.h
@@ -59,6 +59,7 @@ public:
bool getv2(double &x, double &y) const;
bool getv3(double &x, double &y, double &z) const;
+ // FIXME: stream support
QString dump() const;
private:
diff --git a/src/visitor.h b/src/visitor.h
new file mode 100644
index 0000000..7867446
--- /dev/null
+++ b/src/visitor.h
@@ -0,0 +1,52 @@
+#ifndef VISITOR_H_
+#define VISITOR_H_
+
+#include "traverser.h"
+
+class Visitor
+{
+public:
+ Visitor() {}
+ virtual ~Visitor() {}
+
+ virtual Response visit(const class State &state, const class AbstractNode &node) = 0;
+ virtual Response visit(const class State &state, const class AbstractIntersectionNode &node) {
+ return visit(state, (const class AbstractNode &)node);
+ }
+ virtual Response visit(const class State &state, const class AbstractPolyNode &node) {
+ return visit(state, (const class AbstractNode &)node);
+ }
+ virtual Response visit(const class State &state, const class CgaladvNode &node) {
+ return visit(state, (const class AbstractNode &)node);
+ }
+ virtual Response visit(const class State &state, const class CsgNode &node) {
+ return visit(state, (const class AbstractNode &)node);
+ }
+ virtual Response visit(const class State &state, const class DxfLinearExtrudeNode &node) {
+ return visit(state, (const class AbstractPolyNode &)node);
+ }
+ virtual Response visit(const class State &state, const class DxfRotateExtrudeNode &node) {
+ return visit(state, (const class AbstractPolyNode &)node);
+ }
+ virtual Response visit(const class State &state, const class ImportNode &node) {
+ return visit(state, (const class AbstractPolyNode &)node);
+ }
+ virtual Response visit(const class State &state, const class PrimitiveNode &node) {
+ return visit(state, (const class AbstractPolyNode &)node);
+ }
+ virtual Response visit(const class State &state, const class ProjectionNode &node) {
+ return visit(state, (const class AbstractPolyNode &)node);
+ }
+ virtual Response visit(const class State &state, const class RenderNode &node) {
+ return visit(state, (const class AbstractNode &)node);
+ }
+ virtual Response visit(const class State &state, const class SurfaceNode &node) {
+ return visit(state, (const class AbstractPolyNode &)node);
+ }
+ virtual Response visit(const class State &state, const class TransformNode &node) {
+ return visit(state, (const class AbstractNode &)node);
+ }
+ // Add visit() methods for new visitable subtypes of AbstractNode here
+};
+
+#endif
contact: Jan Huwald // Impressum