From 53337ff65426ff1ebd87160b502ec383d201ac7b Mon Sep 17 00:00:00 2001 From: kintel Date: Sun, 31 Oct 2010 01:19:06 +0000 Subject: [PATCH 01/14] Committed current version of visitor refactoring git-svn-id: http://svn.clifford.at/openscad/trunk@571 b57f626f-c46c-0410-a088-ec61d464b74c --- openscad.pro | 16 ++++++- src/cgaladv.cc | 43 +++++++++++++++--- src/csgnode.h | 33 ++++++++++++++ src/csgops.cc | 65 +++++++++++++-------------- src/dxflinextrude.cc | 56 +++++++++++++---------- src/dxflinextrudenode.h | 30 +++++++++++++ src/dxfrotextrude.cc | 45 ++++++++++--------- src/dxfrotextrudenode.h | 28 ++++++++++++ src/import.cc | 60 ++++++++++++++++--------- src/importnode.h | 32 ++++++++++++++ src/mainwin.cc | 2 +- src/node.cc | 63 +++++++++++++++++++++----- src/node.h | 42 ++++++++++++++---- src/nodecache.h | 33 ++++++++++++++ src/nodedumper.cc | 98 +++++++++++++++++++++++++++++++++++++++++ src/nodedumper.h | 37 ++++++++++++++++ src/openscad.cc | 15 ++++++- src/polyset.cc | 10 +++-- src/polyset.h | 2 +- src/primitives.cc | 50 ++++++++++++++++++++- src/printutils.cc | 3 +- src/projection.cc | 30 ++++++------- src/projectionnode.h | 24 ++++++++++ src/render.cc | 31 +++++++++---- src/state.h | 28 ++++++++++++ src/surface.cc | 19 +++++++- src/transform.cc | 48 ++++++++++++++++---- src/traverser.cc | 40 +++++++++++++++++ src/traverser.h | 26 +++++++++++ src/value.h | 1 + src/visitor.h | 52 ++++++++++++++++++++++ test-code/dumptest.cc | 16 ++++--- test-code/dumptest.pro | 18 +++++++- 33 files changed, 921 insertions(+), 175 deletions(-) create mode 100644 src/csgnode.h create mode 100644 src/dxflinextrudenode.h create mode 100644 src/dxfrotextrudenode.h create mode 100644 src/importnode.h create mode 100644 src/nodecache.h create mode 100644 src/nodedumper.cc create mode 100644 src/nodedumper.h create mode 100644 src/projectionnode.h create mode 100644 src/state.h create mode 100644 src/traverser.cc create mode 100644 src/traverser.h create mode 100644 src/visitor.h diff --git a/openscad.pro b/openscad.pro index 42a5d226..fec7a798 100644 --- a/openscad.pro +++ b/openscad.pro @@ -98,12 +98,22 @@ HEADERS += src/CGAL_renderer.h \ src/highlighter.h \ src/module.h \ src/node.h \ + src/csgnode.h \ + src/dxflinextrudenode.h \ + src/dxfrotextrudenode.h \ + src/projectionnode.h \ + src/importnode.h \ src/openscad.h \ src/polyset.h \ src/printutils.h \ src/value.h \ src/progress.h \ - src/editor.h + src/editor.h \ + src/visitor.h \ + src/state.h \ + src/traverser.h \ + src/nodecache.h \ + src/nodedumper.h SOURCES += src/openscad.cc \ src/mainwin.cc \ @@ -140,7 +150,9 @@ SOURCES += src/openscad.cc \ src/nef2dxf.cc \ src/Preferences.cc \ src/progress.cc \ - src/editor.cc + src/editor.cc \\ + src/traverser.cc \ + src/nodedumper.cc macx { HEADERS += src/AppleEvents.h \ diff --git a/src/cgaladv.cc b/src/cgaladv.cc index 829bc84d..e391ea80 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 #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 *highlights, QVector *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 00000000..405dd964 --- /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 *highlights, QVector *background) const; + virtual QString dump(QString indent) const; +}; + +#endif diff --git a/src/csgops.cc b/src/csgops.cc index ae970854..5baa149b 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 -# include -#endif - -enum csg_type_e { - CSG_TYPE_UNION, - CSG_TYPE_DIFFERENCE, - CSG_TYPE_INTERSECTION -}; +#include 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 *highlights, QVector *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 83c3d9ca..1f6bc8c3 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 #include #include +#include #include #include @@ -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 00000000..2df52c8d --- /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 ea603f09..98f91f3a 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 #include #include +#include #include #include @@ -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 00000000..fbe2b85f --- /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 bab13aef..5d0a4971 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 #include #include - -enum import_type_e { - TYPE_STL, - TYPE_OFF, - TYPE_DXF -}; +#include 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 00000000..b2265695 --- /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 ef738fce..1bf26959 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 87a70514..437fdfa4 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 +#include 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 getChildren() const { + return this->children.toList().toStdList(); + } + int index() const { return this->idx; } + static void resetIndexCounter() { idx_counter = 1; } QVector 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 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 *highlights, QVector *background, const char *statement, int convexity) const; #endif virtual class CSGTerm *render_csg_term(double m[20], QVector *highlights, QVector *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 *highlights, QVector *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 *highlights, QVector *background) const; static CSGTerm *render_csg_term_from_ps(double m[20], QVector *highlights, QVector *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 00000000..c5a5524c --- /dev/null +++ b/src/nodecache.h @@ -0,0 +1,33 @@ +#ifndef NODECACHE_H_ +#define NODECACHE_H_ + +#include +#include "node.h" + +template +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 cache; + T nullvalue; +}; + +#endif diff --git a/src/nodedumper.cc b/src/nodedumper.cc new file mode 100644 index 00000000..1956a899 --- /dev/null +++ b/src/nodedumper.cc @@ -0,0 +1,98 @@ +#include "nodedumper.h" +#include +#include +#include +#include "visitor.h" +#include "state.h" +#include "nodecache.h" + +#include +#include + +// 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(&node) && + !dynamic_cast(&node) && + !dynamic_cast(&node) && + !dynamic_cast(&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 00000000..568d5786 --- /dev/null +++ b/src/nodedumper.h @@ -0,0 +1,37 @@ +#ifndef NODEDUMPER_H_ +#define NODEDUMPER_H_ + +#include +#include +#include +#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 ChildList; + map visitedchildren; + NodeCache cache; +}; + + +#endif diff --git a/src/openscad.cc b/src/openscad.cc index bf24c9f9..fdd2502f 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 d4387699..4548f8a4 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 0914e916..074f82ea 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 ac1f0a38..88385470 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -32,6 +32,8 @@ #include "builtin.h" #include "printutils.h" #include +#include "visitor.h" +#include 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 8830a8c7..0f4c67d9 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 7a3f77a5..985ed20e 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 @@ -43,6 +44,7 @@ #include #include #include +#include #include #include @@ -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 00000000..d5ba6dae --- /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 d851fc88..5bd57fce 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 #include #include +#include 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 *highlights, QVector *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 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 00000000..7ac8e9fa --- /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 ddcd3a67..57b3f597 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 +#include 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 746283ed..8f61c264 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 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 *highlights, QVector *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 00000000..af29132e --- /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 &children = node.getChildren(); + for (std::list::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 00000000..80913e3b --- /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 3491cbbc..982d5d8b 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 00000000..7867446d --- /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 diff --git a/test-code/dumptest.cc b/test-code/dumptest.cc index 45d19ff9..cb2b13c5 100644 --- a/test-code/dumptest.cc +++ b/test-code/dumptest.cc @@ -30,7 +30,7 @@ #include "value.h" #include "export.h" #include "builtin.h" -//#include "nodedumper.h" +#include "nodedumper.h" #include #include @@ -148,17 +148,19 @@ int main(int argc, char **argv) QString dumpstr_cached = root_node->dump(""); if (dumpstr != dumpstr_cached) rc = 1; - printf(dumpstr.toUtf8()); - -#if 0 NodeDumper dumper; Traverser trav(dumper, *root_node, Traverser::PRE_AND_POSTFIX); trav.execute(); - std::string dumpstdstr = dumper.getDump(); + std::string dumpstdstr = dumper.getDump() + "\n"; trav.execute(); - std::string dumpstdstr_cached = dumper.getDump(); + std::string dumpstdstr_cached = dumper.getDump() + "\n"; if (dumpstdstr != dumpstdstr_cached) rc = 1; -#endif + + if (QString::fromStdString(dumpstdstr) != dumpstr) { + printf(dumpstr.toUtf8()); + printf(dumpstdstr.c_str()); + rc = 1; + } destroy_builtin_functions(); destroy_builtin_modules(); diff --git a/test-code/dumptest.pro b/test-code/dumptest.pro index a6729f73..d196cda3 100644 --- a/test-code/dumptest.pro +++ b/test-code/dumptest.pro @@ -50,11 +50,23 @@ HEADERS += ../src/builtin.h \ ../src/grid.h \ ../src/module.h \ ../src/node.h \ + ../src/dxflinextrudenode.h \ + ../src/dxfrotextrudenode.h \ + ../src/projectionnode.h \ + ../src/importnode.h \ + ../src/csgnode.h \ ../src/openscad.h \ ../src/polyset.h \ ../src/printutils.h \ ../src/value.h \ - ../src/progress.h + ../src/progress.h \ + ../src/traverser.h \ + ../src/csgnode.h \ + ../src/visitor.h \ + ../src/nodedumper.h \ + ../src/nodecache.h \ + ../src/importnode.h \ + ../src/state.h SOURCES += dumptest.cc \ ../src/export.cc \ @@ -83,4 +95,6 @@ SOURCES += dumptest.cc \ ../src/dxflinextrude.cc \ ../src/dxfrotextrude.cc \ ../src/printutils.cc \ - ../src/progress.cc + ../src/progress.cc \ + ../src/nodedumper.cc \ + ../src/traverser.cc From b3f4c98c80acaa414f7bdacc86314d97267acba5 Mon Sep 17 00:00:00 2001 From: kintel Date: Sun, 31 Oct 2010 01:19:28 +0000 Subject: [PATCH 02/14] FIXME's added to AbstractNode git-svn-id: http://svn.clifford.at/openscad/trunk@572 b57f626f-c46c-0410-a088-ec61d464b74c --- src/node.h | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/node.h b/src/node.h index 08a5cb1e..f3a5b0bd 100644 --- a/src/node.h +++ b/src/node.h @@ -19,6 +19,10 @@ void progress_report_fin(); class AbstractNode { + // FIXME: the idx_counter/idx is mostly (only?) for debugging. + // We can hash on pointer value or smth. else. + // -> remove and + // use smth. else to display node identifier in CSG tree output? static int idx_counter; // Node instantiation index public: AbstractNode(const class ModuleInstantiation *mi); @@ -34,19 +38,28 @@ public: static void resetIndexCounter() { idx_counter = 1; } + // FIXME: Rewrite to STL container? + // FIXME: Make protected QVector children; const ModuleInstantiation *modinst; - + + // progress_mark is a running number used for progress indication + // FIXME: Make all progress handling external, put it in the traverser class? int progress_mark; void progress_prepare(); void progress_report() const; int idx; // Node index (unique per tree) + + // FIXME: Remove these three with dump() method QString dump_cache; - - - virtual QString mk_cache_id() const; + virtual QString dump(QString indent) const; + + // FIXME: Rewrite to visitor + virtual class CSGTerm *render_csg_term(double m[20], QVector *highlights, QVector *background) const; + + // FIXME: Rewrite to visitor #ifdef ENABLE_CGAL struct cgal_nef_cache_entry { CGAL_Nef_polyhedron N; @@ -57,8 +70,6 @@ public: virtual CGAL_Nef_polyhedron renderCSGMesh() const; class CSGTerm *render_csg_term_from_nef(double m[20], QVector *highlights, QVector *background, const char *statement, int convexity) const; #endif - virtual class CSGTerm *render_csg_term(double m[20], QVector *highlights, QVector *background) const; - virtual QString dump(QString indent) const; }; class AbstractIntersectionNode : public AbstractNode From e0c5673e1bf965fbb1bbbef2562a54be1a3144a3 Mon Sep 17 00:00:00 2001 From: kintel Date: Sun, 31 Oct 2010 01:58:50 +0000 Subject: [PATCH 03/14] Reverted accidental commits git-svn-id: http://svn.clifford.at/openscad/trunk@573 b57f626f-c46c-0410-a088-ec61d464b74c --- openscad.pro | 16 +------ src/cgaladv.cc | 43 +++--------------- src/csgnode.h | 33 -------------- src/csgops.cc | 65 ++++++++++++++------------- src/dxflinextrude.cc | 56 ++++++++++------------- src/dxflinextrudenode.h | 30 ------------- src/dxfrotextrude.cc | 45 +++++++++---------- src/dxfrotextrudenode.h | 28 ------------ src/import.cc | 60 +++++++++---------------- src/importnode.h | 32 -------------- src/mainwin.cc | 2 +- src/node.cc | 63 +++++--------------------- src/node.h | 57 +++++------------------- src/nodecache.h | 33 -------------- src/nodedumper.cc | 98 ----------------------------------------- src/nodedumper.h | 37 ---------------- src/openscad.cc | 15 +------ src/polyset.cc | 10 ++--- src/polyset.h | 2 +- src/primitives.cc | 50 +-------------------- src/printutils.cc | 3 +- src/projection.cc | 30 ++++++------- src/projectionnode.h | 24 ---------- src/render.cc | 31 ++++--------- src/state.h | 28 ------------ src/surface.cc | 19 +------- src/transform.cc | 48 ++++---------------- src/traverser.cc | 40 ----------------- src/traverser.h | 26 ----------- src/value.h | 1 - src/visitor.h | 52 ---------------------- test-code/dumptest.cc | 16 +++---- test-code/dumptest.pro | 18 +------- 33 files changed, 177 insertions(+), 934 deletions(-) delete mode 100644 src/csgnode.h delete mode 100644 src/dxflinextrudenode.h delete mode 100644 src/dxfrotextrudenode.h delete mode 100644 src/importnode.h delete mode 100644 src/nodecache.h delete mode 100644 src/nodedumper.cc delete mode 100644 src/nodedumper.h delete mode 100644 src/projectionnode.h delete mode 100644 src/state.h delete mode 100644 src/traverser.cc delete mode 100644 src/traverser.h delete mode 100644 src/visitor.h diff --git a/openscad.pro b/openscad.pro index fec7a798..42a5d226 100644 --- a/openscad.pro +++ b/openscad.pro @@ -98,22 +98,12 @@ HEADERS += src/CGAL_renderer.h \ src/highlighter.h \ src/module.h \ src/node.h \ - src/csgnode.h \ - src/dxflinextrudenode.h \ - src/dxfrotextrudenode.h \ - src/projectionnode.h \ - src/importnode.h \ src/openscad.h \ src/polyset.h \ src/printutils.h \ src/value.h \ src/progress.h \ - src/editor.h \ - src/visitor.h \ - src/state.h \ - src/traverser.h \ - src/nodecache.h \ - src/nodedumper.h + src/editor.h SOURCES += src/openscad.cc \ src/mainwin.cc \ @@ -150,9 +140,7 @@ SOURCES += src/openscad.cc \ src/nef2dxf.cc \ src/Preferences.cc \ src/progress.cc \ - src/editor.cc \\ - src/traverser.cc \ - src/nodedumper.cc + src/editor.cc macx { HEADERS += src/AppleEvents.h \ diff --git a/src/cgaladv.cc b/src/cgaladv.cc index e391ea80..829bc84d 100644 --- a/src/cgaladv.cc +++ b/src/cgaladv.cc @@ -29,8 +29,6 @@ #include "builtin.h" #include "printutils.h" #include "cgal.h" -#include "visitor.h" -#include #ifdef ENABLE_CGAL extern CGAL_Nef_polyhedron3 minkowski3(CGAL_Nef_polyhedron3 a, CGAL_Nef_polyhedron3 b); @@ -54,21 +52,15 @@ 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 renderCSGMesh() const; + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif virtual CSGTerm *render_csg_term(double m[20], QVector *highlights, QVector *background) const; virtual QString dump(QString indent) const; @@ -136,7 +128,7 @@ void register_builtin_cgaladv() #ifdef ENABLE_CGAL -CGAL_Nef_polyhedron CgaladvNode::renderCSGMesh() const +CGAL_Nef_polyhedron CgaladvNode::render_cgal_nef_polyhedron() const { QString cache_id = mk_cache_id(); if (cgal_nef_cache.contains(cache_id)) { @@ -155,11 +147,11 @@ CGAL_Nef_polyhedron CgaladvNode::renderCSGMesh() const if (v->modinst->tag_background) continue; if (first) { - N = v->renderCsgMesh(); + N = v->render_cgal_nef_polyhedron(); if (N.dim != 0) first = false; } else { - CGAL_Nef_polyhedron tmp = v->renderCsgMesh(); + CGAL_Nef_polyhedron tmp = v->render_cgal_nef_polyhedron(); if (N.dim == 3 && tmp.dim == 3) { N.p3 = minkowski3(N.p3, tmp.p3); } @@ -232,24 +224,3 @@ 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 deleted file mode 100644 index 405dd964..00000000 --- a/src/csgnode.h +++ /dev/null @@ -1,33 +0,0 @@ -#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 *highlights, QVector *background) const; - virtual QString dump(QString indent) const; -}; - -#endif diff --git a/src/csgops.cc b/src/csgops.cc index 5baa149b..ae970854 100644 --- a/src/csgops.cc +++ b/src/csgops.cc @@ -23,13 +23,22 @@ * */ -#include "csgnode.h" - #include "module.h" +#include "node.h" #include "csgterm.h" #include "builtin.h" #include "printutils.h" -#include +#ifdef ENABLE_CGAL +# include "cgal.h" +# include +# include +#endif + +enum csg_type_e { + CSG_TYPE_UNION, + CSG_TYPE_DIFFERENCE, + CSG_TYPE_INTERSECTION +}; class CsgModule : public AbstractModule { @@ -39,6 +48,18 @@ 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 *highlights, QVector *background) const; + virtual QString dump(QString indent) const; +}; + AbstractNode *CsgModule::evaluate(const Context*, const ModuleInstantiation *inst) const { CsgNode *node = new CsgNode(inst, type); @@ -52,7 +73,7 @@ AbstractNode *CsgModule::evaluate(const Context*, const ModuleInstantiation *ins #ifdef ENABLE_CGAL -CGAL_Nef_polyhedron CsgNode::renderCSGMesh() const +CGAL_Nef_polyhedron CsgNode::render_cgal_nef_polyhedron() const { QString cache_id = mk_cache_id(); if (cgal_nef_cache.contains(cache_id)) { @@ -71,24 +92,24 @@ CGAL_Nef_polyhedron CsgNode::renderCSGMesh() const if (v->modinst->tag_background) continue; if (first) { - N = v->renderCSGMesh(); + N = v->render_cgal_nef_polyhedron(); if (N.dim != 0) first = false; } else if (N.dim == 2) { if (type == CSG_TYPE_UNION) { - N.p2 += v->renderCSGMesh().p2; + N.p2 += v->render_cgal_nef_polyhedron().p2; } else if (type == CSG_TYPE_DIFFERENCE) { - N.p2 -= v->renderCSGMesh().p2; + N.p2 -= v->render_cgal_nef_polyhedron().p2; } else if (type == CSG_TYPE_INTERSECTION) { - N.p2 *= v->renderCSGMesh().p2; + N.p2 *= v->render_cgal_nef_polyhedron().p2; } } else if (N.dim == 3) { if (type == CSG_TYPE_UNION) { - N.p3 += v->renderCSGMesh().p3; + N.p3 += v->render_cgal_nef_polyhedron().p3; } else if (type == CSG_TYPE_DIFFERENCE) { - N.p3 -= v->renderCSGMesh().p3; + N.p3 -= v->render_cgal_nef_polyhedron().p3; } else if (type == CSG_TYPE_INTERSECTION) { - N.p3 *= v->renderCSGMesh().p3; + N.p3 *= v->render_cgal_nef_polyhedron().p3; } } v->progress_report(); @@ -151,28 +172,6 @@ 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 1f6bc8c3..83c3d9ca 100644 --- a/src/dxflinextrude.cc +++ b/src/dxflinextrude.cc @@ -23,9 +23,8 @@ * */ -#include "dxflinextrudenode.h" - #include "module.h" +#include "node.h" #include "context.h" #include "printutils.h" #include "builtin.h" @@ -33,13 +32,11 @@ #include "dxftess.h" #include "polyset.h" #include "progress.h" -#include "visitor.h" #include "openscad.h" // get_fragments_from_r() #include #include #include -#include #include #include @@ -52,6 +49,24 @@ 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); @@ -76,8 +91,10 @@ 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; @@ -219,7 +236,7 @@ PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e) const foreach(AbstractNode * v, children) { if (v->modinst->tag_background) continue; - N.p2 += v->renderCSGMesh().p2; + N.p2 += v->render_cgal_nef_polyhedron().p2; } dxf = new DxfData(N); @@ -327,30 +344,3 @@ 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 deleted file mode 100644 index 2df52c8d..00000000 --- a/src/dxflinextrudenode.h +++ /dev/null @@ -1,30 +0,0 @@ -#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 98f91f3a..ea603f09 100644 --- a/src/dxfrotextrude.cc +++ b/src/dxfrotextrude.cc @@ -23,21 +23,19 @@ * */ -#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 #include #include -#include #include #include @@ -50,6 +48,22 @@ 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); @@ -70,8 +84,10 @@ 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; @@ -120,7 +136,7 @@ PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e) const foreach(AbstractNode * v, children) { if (v->modinst->tag_background) continue; - N.p2 += v->renderCSGMesh().p2; + N.p2 += v->render_cgal_nef_polyhedron().p2; } dxf = new DxfData(N); @@ -218,22 +234,3 @@ 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 deleted file mode 100644 index fbe2b85f..00000000 --- a/src/dxfrotextrudenode.h +++ /dev/null @@ -1,28 +0,0 @@ -#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 5d0a4971..bab13aef 100644 --- a/src/import.cc +++ b/src/import.cc @@ -23,9 +23,8 @@ * */ -#include "importnode.h" - #include "module.h" +#include "node.h" #include "polyset.h" #include "context.h" #include "builtin.h" @@ -37,7 +36,12 @@ #include #include #include -#include + +enum import_type_e { + TYPE_STL, + TYPE_OFF, + TYPE_DXF +}; class ImportModule : public AbstractModule { @@ -47,6 +51,20 @@ 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); @@ -213,39 +231,3 @@ 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 deleted file mode 100644 index b2265695..00000000 --- a/src/importnode.h +++ /dev/null @@ -1,32 +0,0 @@ -#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 1bf26959..ef738fce 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->renderCSGMesh()); + this->root_N = new CGAL_Nef_polyhedron(root_node->render_cgal_nef_polyhedron()); } catch (ProgressCancelException e) { PRINT("Rendering cancelled."); diff --git a/src/node.cc b/src/node.cc index 437fdfa4..87a70514 100644 --- a/src/node.cc +++ b/src/node.cc @@ -29,9 +29,7 @@ #include "csgterm.h" #include "progress.h" #include "polyset.h" -#include "visitor.h" #include -#include int AbstractNode::idx_counter; @@ -47,21 +45,6 @@ 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(""); @@ -96,19 +79,19 @@ static CGAL_Nef_polyhedron render_cgal_nef_polyhedron_backend(const AbstractNode if (v->modinst->tag_background) continue; if (first) { - N = v->renderCSGMesh(); + N = v->render_cgal_nef_polyhedron(); if (N.dim != 0) first = false; } else if (N.dim == 2) { if (intersect) - N.p2 *= v->renderCSGMesh().p2; + N.p2 *= v->render_cgal_nef_polyhedron().p2; else - N.p2 += v->renderCSGMesh().p2; + N.p2 += v->render_cgal_nef_polyhedron().p2; } else { if (intersect) - N.p3 *= v->renderCSGMesh().p3; + N.p3 *= v->render_cgal_nef_polyhedron().p3; else - N.p3 += v->renderCSGMesh().p3; + N.p3 += v->render_cgal_nef_polyhedron().p3; } v->progress_report(); } @@ -120,12 +103,12 @@ static CGAL_Nef_polyhedron render_cgal_nef_polyhedron_backend(const AbstractNode return N; } -CGAL_Nef_polyhedron AbstractNode::renderCSGMesh() const +CGAL_Nef_polyhedron AbstractNode::render_cgal_nef_polyhedron() const { return render_cgal_nef_polyhedron_backend(this, false); } -CGAL_Nef_polyhedron AbstractIntersectionNode::renderCSGMesh() const +CGAL_Nef_polyhedron AbstractIntersectionNode::render_cgal_nef_polyhedron() const { return render_cgal_nef_polyhedron_backend(this, true); } @@ -176,17 +159,10 @@ 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::fromStdString(this->toString()) + " {\n"; + QString text = indent + QString("n%1: intersection() {\n").arg(idx); foreach (AbstractNode *v, children) text += v->dump(indent + QString("\t")); ((AbstractNode*)this)->dump_cache = text + indent + "}\n"; @@ -194,13 +170,6 @@ 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) @@ -215,7 +184,7 @@ void AbstractNode::progress_report() const #ifdef ENABLE_CGAL -CGAL_Nef_polyhedron AbstractPolyNode::renderCSGMesh() const +CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const { QString cache_id = mk_cache_id(); if (cgal_nef_cache.contains(cache_id)) { @@ -228,7 +197,7 @@ CGAL_Nef_polyhedron AbstractPolyNode::renderCSGMesh() const PolySet *ps = render_polyset(RENDER_CGAL); try { - CGAL_Nef_polyhedron N = ps->renderCSGMesh(); + CGAL_Nef_polyhedron N = ps->render_cgal_nef_polyhedron(); cgal_nef_cache.insert(cache_id, new cgal_nef_cache_entry(N), N.weight()); print_messages_pop(); progress_report(); @@ -262,15 +231,3 @@ CSGTerm *AbstractPolyNode::render_csg_term_from_ps(double m[20], QVector remove and - // use smth. else to display node identifier in CSG tree output? 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 getChildren() const { - return this->children.toList().toStdList(); - } - int index() const { return this->idx; } - static void resetIndexCounter() { idx_counter = 1; } - // FIXME: Rewrite to STL container? - // FIXME: Make protected QVector children; - const ModuleInstantiation *modinst; + const class ModuleInstantiation *modinst; - // progress_mark is a running number used for progress indication - // FIXME: Make all progress handling external, put it in the traverser class? int progress_mark; void progress_prepare(); void progress_report() const; - int idx; // Node index (unique per tree) - - // FIXME: Remove these three with dump() method + int idx; QString dump_cache; + + AbstractNode(const ModuleInstantiation *mi); + virtual ~AbstractNode(); virtual QString mk_cache_id() const; - virtual QString dump(QString indent) const; - - // FIXME: Rewrite to visitor - virtual class CSGTerm *render_csg_term(double m[20], QVector *highlights, QVector *background) const; - - // FIXME: Rewrite to visitor #ifdef ENABLE_CGAL struct cgal_nef_cache_entry { CGAL_Nef_polyhedron N; @@ -67,21 +41,19 @@ public: cgal_nef_cache_entry(const CGAL_Nef_polyhedron &N); }; static QCache cgal_nef_cache; - virtual CGAL_Nef_polyhedron renderCSGMesh() const; + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; class CSGTerm *render_csg_term_from_nef(double m[20], QVector *highlights, QVector *background, const char *statement, int convexity) const; #endif + virtual class CSGTerm *render_csg_term(double m[20], QVector *highlights, QVector *background) const; + virtual QString dump(QString indent) const; }; 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 renderCSGMesh() const; + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif virtual CSGTerm *render_csg_term(double m[20], QVector *highlights, QVector *background) const; virtual QString dump(QString indent) const; @@ -90,24 +62,17 @@ 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 renderCSGMesh() const; + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif virtual CSGTerm *render_csg_term(double m[20], QVector *highlights, QVector *background) const; static CSGTerm *render_csg_term_from_ps(double m[20], QVector *highlights, QVector *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 deleted file mode 100644 index c5a5524c..00000000 --- a/src/nodecache.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef NODECACHE_H_ -#define NODECACHE_H_ - -#include -#include "node.h" - -template -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 cache; - T nullvalue; -}; - -#endif diff --git a/src/nodedumper.cc b/src/nodedumper.cc deleted file mode 100644 index 1956a899..00000000 --- a/src/nodedumper.cc +++ /dev/null @@ -1,98 +0,0 @@ -#include "nodedumper.h" -#include -#include -#include -#include "visitor.h" -#include "state.h" -#include "nodecache.h" - -#include -#include - -// 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(&node) && - !dynamic_cast(&node) && - !dynamic_cast(&node) && - !dynamic_cast(&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 deleted file mode 100644 index 568d5786..00000000 --- a/src/nodedumper.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef NODEDUMPER_H_ -#define NODEDUMPER_H_ - -#include -#include -#include -#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 ChildList; - map visitedchildren; - NodeCache cache; -}; - - -#endif diff --git a/src/openscad.cc b/src/openscad.cc index fdd2502f..bf24c9f9 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -31,7 +31,6 @@ #include "value.h" #include "export.h" #include "builtin.h" -#include "nodedumper.h" #ifdef ENABLE_CGAL #include "cgal.h" @@ -285,20 +284,8 @@ 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->renderCSGMesh()); + root_N = new CGAL_Nef_polyhedron(root_node->render_cgal_nef_polyhedron()); QDir::setCurrent(original_path.absolutePath()); diff --git a/src/polyset.cc b/src/polyset.cc index 4548f8a4..d4387699 100644 --- a/src/polyset.cc +++ b/src/polyset.cc @@ -144,9 +144,7 @@ void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, double *m bool mirrored = m3f.determinant() < 0; if (colormode == COLORMODE_MATERIAL) { -// 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); + const QColor &col = Preferences::inst()->color(Preferences::OPENCSG_FACE_FRONT_COLOR); glColor3f(col.redF(), col.greenF(), col.blueF()); #ifdef ENABLE_OPENCSG if (shaderinfo) { @@ -156,9 +154,7 @@ void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, double *m #endif /* ENABLE_OPENCSG */ } if (colormode == COLORMODE_CUTOUT) { -// 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); + const QColor &col = Preferences::inst()->color(Preferences::OPENCSG_FACE_BACK_COLOR); glColor3f(col.redF(), col.greenF(), col.blueF()); #ifdef ENABLE_OPENCSG if (shaderinfo) { @@ -411,7 +407,7 @@ public: } }; -CGAL_Nef_polyhedron PolySet::renderCSGMesh() const +CGAL_Nef_polyhedron PolySet::render_cgal_nef_polyhedron() const { if (this->is2d) { diff --git a/src/polyset.h b/src/polyset.h index 074f82ea..0914e916 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 renderCSGMesh() const; + CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif int refcount; diff --git a/src/primitives.cc b/src/primitives.cc index 88385470..ac1f0a38 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -32,8 +32,6 @@ #include "builtin.h" #include "printutils.h" #include -#include "visitor.h" -#include enum primitive_type_e { CUBE, @@ -56,18 +54,13 @@ 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; }; @@ -549,44 +542,3 @@ 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 0f4c67d9..8830a8c7 100644 --- a/src/printutils.cc +++ b/src/printutils.cc @@ -18,7 +18,8 @@ void print_messages_push() void print_messages_pop() { - QString msg = print_messages_stack.takeLast(); + QString msg = print_messages_stack.last(); + print_messages_stack.removeLast(); 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 985ed20e..7a3f77a5 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,7 +33,6 @@ #include "polyset.h" #include "export.h" #include "progress.h" -#include "visitor.h" #ifdef ENABLE_CGAL # include @@ -44,7 +43,6 @@ #include #include #include -#include #include #include @@ -57,6 +55,18 @@ 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); @@ -112,7 +122,7 @@ PolySet *ProjectionNode::render_polyset(render_mode_e) const foreach(AbstractNode *v, this->children) { if (v->modinst->tag_background) continue; - N.p3 += v->renderCSGMesh().p3; + N.p3 += v->render_cgal_nef_polyhedron().p3; } } catch (CGAL::Assertion_exception e) { @@ -163,7 +173,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->renderCSGMesh(); + CGAL_Nef_polyhedron Ncube = cube->render_cgal_nef_polyhedron(); cube->unlink(); // N.p3 *= CGAL_Nef_polyhedron3(CGAL_Plane(0, 0, 1, 0), CGAL_Nef_polyhedron3::INCLUDED); @@ -288,13 +298,3 @@ 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 deleted file mode 100644 index d5ba6dae..00000000 --- a/src/projectionnode.h +++ /dev/null @@ -1,24 +0,0 @@ -#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 5bd57fce..d851fc88 100644 --- a/src/render.cc +++ b/src/render.cc @@ -33,14 +33,13 @@ #include "builtin.h" #include "printutils.h" #include "progress.h" -#include "visitor.h" #ifdef ENABLE_CGAL # include "cgal.h" #endif +#include #include #include -#include class RenderModule : public AbstractModule { @@ -52,15 +51,10 @@ public: class RenderNode : public AbstractNode { public: - 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; + RenderNode(const ModuleInstantiation *mi) : AbstractNode(mi), convexity(1) { } #ifdef ENABLE_CGAL - virtual CGAL_Nef_polyhedron renderCSGMesh() const; + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif CSGTerm *render_csg_term(double m[20], QVector *highlights, QVector *background) const; virtual QString dump(QString indent) const; @@ -96,7 +90,7 @@ void register_builtin_render() #ifdef ENABLE_CGAL -CGAL_Nef_polyhedron RenderNode::renderCSGMesh() const +CGAL_Nef_polyhedron RenderNode::render_cgal_nef_polyhedron() const { QString cache_id = mk_cache_id(); if (cgal_nef_cache.contains(cache_id)) { @@ -114,13 +108,13 @@ CGAL_Nef_polyhedron RenderNode::renderCSGMesh() const if (v->modinst->tag_background) continue; if (first) { - N = v->renderCSGMesh(); + N = v->render_cgal_nef_polyhedron(); if (N.dim != 0) first = false; } else if (N.dim == 2) { - N.p2 += v->renderCSGMesh().p2; + N.p2 += v->render_cgal_nef_polyhedron().p2; } else if (N.dim == 3) { - N.p3 += v->renderCSGMesh().p3; + N.p3 += v->render_cgal_nef_polyhedron().p3; } v->progress_report(); } @@ -159,7 +153,7 @@ CSGTerm *AbstractNode::render_csg_term_from_nef(double m[20], QVector QTime t; t.start(); - N = this->renderCSGMesh(); + N = this->render_cgal_nef_polyhedron(); int s = t.elapsed() / 1000; PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60); @@ -267,12 +261,3 @@ 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 deleted file mode 100644 index 7ac8e9fa..00000000 --- a/src/state.h +++ /dev/null @@ -1,28 +0,0 @@ -#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 57b3f597..ddcd3a67 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -31,10 +31,8 @@ #include "dxftess.h" #include "printutils.h" #include "openscad.h" // handle_dep() -#include "visitor.h" #include -#include class SurfaceModule : public AbstractModule { @@ -46,15 +44,10 @@ 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; }; @@ -215,13 +208,3 @@ 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 8f61c264..746283ed 100644 --- a/src/transform.cc +++ b/src/transform.cc @@ -32,8 +32,6 @@ #include "dxftess.h" #include "builtin.h" #include "printutils.h" -#include "visitor.h" -#include enum transform_type_e { SCALE, @@ -55,15 +53,10 @@ public: class TransformNode : public AbstractNode { public: - 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]; + TransformNode(const ModuleInstantiation *mi) : AbstractNode(mi) { } #ifdef ENABLE_CGAL - virtual CGAL_Nef_polyhedron renderCSGMesh() const; + virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const; #endif virtual CSGTerm *render_csg_term(double m[20], QVector *highlights, QVector *background) const; virtual QString dump(QString indent) const; @@ -247,7 +240,7 @@ AbstractNode *TransformModule::evaluate(const Context *ctx, const ModuleInstanti #ifdef ENABLE_CGAL -CGAL_Nef_polyhedron TransformNode::renderCSGMesh() const +CGAL_Nef_polyhedron TransformNode::render_cgal_nef_polyhedron() const { QString cache_id = mk_cache_id(); if (cgal_nef_cache.contains(cache_id)) { @@ -265,13 +258,13 @@ CGAL_Nef_polyhedron TransformNode::renderCSGMesh() const if (v->modinst->tag_background) continue; if (first) { - N = v->renderCSGMesh(); + N = v->render_cgal_nef_polyhedron(); if (N.dim != 0) first = false; } else if (N.dim == 2) { - N.p2 += v->renderCSGMesh().p2; + N.p2 += v->render_cgal_nef_polyhedron().p2; } else if (N.dim == 3) { - N.p3 += v->renderCSGMesh().p3; + N.p3 += v->render_cgal_nef_polyhedron().p3; } v->progress_report(); } @@ -298,7 +291,7 @@ CGAL_Nef_polyhedron TransformNode::renderCSGMesh() const ps.is2d = true; dxf_tesselate(&ps, &dd, 0, true, false, 0); - N = ps.renderCSGMesh(); + N = ps.render_cgal_nef_polyhedron(); ps.refcount = 0; } if (N.dim == 3) { @@ -375,32 +368,6 @@ 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); @@ -410,3 +377,4 @@ 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 deleted file mode 100644 index af29132e..00000000 --- a/src/traverser.cc +++ /dev/null @@ -1,40 +0,0 @@ -#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 &children = node.getChildren(); - for (std::list::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 deleted file mode 100644 index 80913e3b..00000000 --- a/src/traverser.h +++ /dev/null @@ -1,26 +0,0 @@ -#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 982d5d8b..3491cbbc 100644 --- a/src/value.h +++ b/src/value.h @@ -59,7 +59,6 @@ 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 deleted file mode 100644 index 7867446d..00000000 --- a/src/visitor.h +++ /dev/null @@ -1,52 +0,0 @@ -#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 diff --git a/test-code/dumptest.cc b/test-code/dumptest.cc index cb2b13c5..45d19ff9 100644 --- a/test-code/dumptest.cc +++ b/test-code/dumptest.cc @@ -30,7 +30,7 @@ #include "value.h" #include "export.h" #include "builtin.h" -#include "nodedumper.h" +//#include "nodedumper.h" #include #include @@ -148,19 +148,17 @@ int main(int argc, char **argv) QString dumpstr_cached = root_node->dump(""); if (dumpstr != dumpstr_cached) rc = 1; + printf(dumpstr.toUtf8()); + +#if 0 NodeDumper dumper; Traverser trav(dumper, *root_node, Traverser::PRE_AND_POSTFIX); trav.execute(); - std::string dumpstdstr = dumper.getDump() + "\n"; + std::string dumpstdstr = dumper.getDump(); trav.execute(); - std::string dumpstdstr_cached = dumper.getDump() + "\n"; + std::string dumpstdstr_cached = dumper.getDump(); if (dumpstdstr != dumpstdstr_cached) rc = 1; - - if (QString::fromStdString(dumpstdstr) != dumpstr) { - printf(dumpstr.toUtf8()); - printf(dumpstdstr.c_str()); - rc = 1; - } +#endif destroy_builtin_functions(); destroy_builtin_modules(); diff --git a/test-code/dumptest.pro b/test-code/dumptest.pro index d196cda3..a6729f73 100644 --- a/test-code/dumptest.pro +++ b/test-code/dumptest.pro @@ -50,23 +50,11 @@ HEADERS += ../src/builtin.h \ ../src/grid.h \ ../src/module.h \ ../src/node.h \ - ../src/dxflinextrudenode.h \ - ../src/dxfrotextrudenode.h \ - ../src/projectionnode.h \ - ../src/importnode.h \ - ../src/csgnode.h \ ../src/openscad.h \ ../src/polyset.h \ ../src/printutils.h \ ../src/value.h \ - ../src/progress.h \ - ../src/traverser.h \ - ../src/csgnode.h \ - ../src/visitor.h \ - ../src/nodedumper.h \ - ../src/nodecache.h \ - ../src/importnode.h \ - ../src/state.h + ../src/progress.h SOURCES += dumptest.cc \ ../src/export.cc \ @@ -95,6 +83,4 @@ SOURCES += dumptest.cc \ ../src/dxflinextrude.cc \ ../src/dxfrotextrude.cc \ ../src/printutils.cc \ - ../src/progress.cc \ - ../src/nodedumper.cc \ - ../src/traverser.cc + ../src/progress.cc From d479fca855688c92f4a9f72f4ec18d655c3b351d Mon Sep 17 00:00:00 2001 From: kintel Date: Sun, 31 Oct 2010 02:51:11 +0000 Subject: [PATCH 04/14] Added a rands() function that returns a vector of random numbers. the function takes either 3 arguments or 4 rands(min,max,num) or rands(min,max,num,seed) git-svn-id: http://svn.clifford.at/openscad/trunk@574 b57f626f-c46c-0410-a088-ec61d464b74c --- src/func.cc | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/func.cc b/src/func.cc index eb0afcdc..6f7ff1c1 100644 --- a/src/func.cc +++ b/src/func.cc @@ -124,6 +124,44 @@ Value builtin_sign(const Context *, const QVector&, const QVectormax) ? frand()*(min-max)+max : frand()*(max-min)+min; +} + +Value builtin_rands(const Context *, const QVector&, const QVector &args) +{ + if (args.size() == 3 && args[0].type == Value::NUMBER && args[1].type == Value::NUMBER && args[2].type == Value::NUMBER) + { + srand((unsigned int)time(0)); + } + else if (args.size() == 4 && args[0].type == Value::NUMBER && args[1].type == Value::NUMBER && args[2].type == Value::NUMBER && args[3].type == Value::NUMBER) + { + srand((unsigned int)args[3].num); + } + else + { + return Value(); + } + + Value v; + v.type = Value::VECTOR; + + for(int i=0; i&, const QVector &args) { if (args.size() >= 1 && args[0].type == Value::NUMBER) { @@ -300,6 +338,7 @@ void initialize_builtin_functions() { builtin_functions["abs"] = new BuiltinFunction(&builtin_abs); builtin_functions["sign"] = new BuiltinFunction(&builtin_sign); + builtin_functions["rands"] = new BuiltinFunction(&builtin_rands); builtin_functions["min"] = new BuiltinFunction(&builtin_min); builtin_functions["max"] = new BuiltinFunction(&builtin_max); builtin_functions["sin"] = new BuiltinFunction(&builtin_sin); From b36acfd268c79cdfff1e06532f2ac0e9db9d8c2f Mon Sep 17 00:00:00 2001 From: kintel Date: Sun, 31 Oct 2010 02:51:27 +0000 Subject: [PATCH 05/14] coding style git-svn-id: http://svn.clifford.at/openscad/trunk@575 b57f626f-c46c-0410-a088-ec61d464b74c --- src/func.cc | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/func.cc b/src/func.cc index 6f7ff1c1..e8ff54a3 100644 --- a/src/func.cc +++ b/src/func.cc @@ -136,11 +136,18 @@ double frand(double min, double max) Value builtin_rands(const Context *, const QVector&, const QVector &args) { - if (args.size() == 3 && args[0].type == Value::NUMBER && args[1].type == Value::NUMBER && args[2].type == Value::NUMBER) + if (args.size() == 3 && + args[0].type == Value::NUMBER && + args[1].type == Value::NUMBER && + args[2].type == Value::NUMBER) { srand((unsigned int)time(0)); } - else if (args.size() == 4 && args[0].type == Value::NUMBER && args[1].type == Value::NUMBER && args[2].type == Value::NUMBER && args[3].type == Value::NUMBER) + else if (args.size() == 4 && + args[0].type == Value::NUMBER && + args[1].type == Value::NUMBER && + args[2].type == Value::NUMBER && + args[3].type == Value::NUMBER) { srand((unsigned int)args[3].num); } @@ -148,16 +155,16 @@ Value builtin_rands(const Context *, const QVector&, const QVector Date: Tue, 2 Nov 2010 11:13:36 +0000 Subject: [PATCH 06/14] use is implemented, added note about include limitation git-svn-id: http://svn.clifford.at/openscad/trunk@576 b57f626f-c46c-0410-a088-ec61d464b74c --- doc/TODO.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/TODO.txt b/doc/TODO.txt index ceab45bf..c01b13ab 100644 --- a/doc/TODO.txt +++ b/doc/TODO.txt @@ -132,10 +132,11 @@ o Function-Module-Interface - Pass a module instanciation to a function (e.g. for a volume() function) - Pass a function to a module instanciation (e.g. for dynamic extrusion paths) o Language Frontend + - include statement doesn't support nesting. This can be fixed by + keeping a nested stack of current input files in the lexer. See + the "Flex & Bison" O'Reilly book, "Start States and Nested Input + Files", page 28, for an example. - Allow local variables and functions everywhere (not only on module level) - - Add "use" statement to load modules. Like include but read a module only once, - ignore all top level objects (they are used as module testcase) and search in - a module search path. - allow 0/1 f/t FALSE/TRUE as boolean values - allow any expression to be evaluated as boolean (e.g. 1 = true, 0 = false) - Rethink for vs. intersection_for vs. group. Should for loops From 928ccb1d06473a7557433e77f531bc11a2d5812f Mon Sep 17 00:00:00 2001 From: kintel Date: Tue, 2 Nov 2010 11:13:41 +0000 Subject: [PATCH 07/14] Recently added features git-svn-id: http://svn.clifford.at/openscad/trunk@577 b57f626f-c46c-0410-a088-ec61d464b74c --- RELEASE_NOTES | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 51b20ee0..69fe747a 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,8 +1,10 @@ -OpenSCAD 2010.06 +OpenSCAD 2010.XX ================ -... add stuff here ... +o Added rands() function +o Added sign() function +o Bugfixes: More robust DXF export OpenSCAD 2010.05 ================ From ae97a22883812f13939e14bb4ce7411c5ecadfe8 Mon Sep 17 00:00:00 2001 From: kintel Date: Tue, 2 Nov 2010 11:13:44 +0000 Subject: [PATCH 08/14] Tag deprecation as such git-svn-id: http://svn.clifford.at/openscad/trunk@578 b57f626f-c46c-0410-a088-ec61d464b74c --- src/lexer.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lexer.l b/src/lexer.l index 48729c85..e0e70eb0 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -106,7 +106,7 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { finfo = QFileInfo(QDir(librarydir), filename); } - PRINTF("WARNING: Support for implicit include will be removed in future releases. Use `include ' instead."); + PRINTF("DEPRECATED: Support for implicit include will be removed in future releases. Use `include ' instead."); handle_dep(finfo.absoluteFilePath()); yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r"); if (!yyin) { From 7f0551e5380929cd57a7bef5a4694ba5dea94aab Mon Sep 17 00:00:00 2001 From: kintel Date: Tue, 2 Nov 2010 14:17:03 +0000 Subject: [PATCH 09/14] TOK_NUMBER lexer improvement by Steven Dick git-svn-id: http://svn.clifford.at/openscad/trunk@579 b57f626f-c46c-0410-a088-ec61d464b74c --- src/lexer.l | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lexer.l b/src/lexer.l index e0e70eb0..49243fdd 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -65,6 +65,8 @@ extern const char *parser_source_path; %x comment +DIGIT [0-9] + %% include[ \t\r\n>]*"<"[^ \t\r\n>]+">" { @@ -135,7 +137,7 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { "false" return TOK_FALSE; "undef" return TOK_UNDEF; -[0-9][0-9.]* { parserlval.number = QString(yytext).toDouble(); return TOK_NUMBER; } +{DIGIT}+|{DIGIT}*\.{DIGIT}+|{DIGIT}+\.{DIGIT}* { parserlval.number = QString(yytext).toDouble(); return TOK_NUMBER; } "$"?[a-zA-Z0-9_]+ { parserlval.text = strdup(yytext); return TOK_ID; } \"[^"]*\" { From 183b3f9cb9841820f52f2aa3af258e19d3269806 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 3 Nov 2010 19:30:49 +0100 Subject: [PATCH 10/14] added notes about byacc and boost, removed fixed macos x build issues --- doc/TODO.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/TODO.txt b/doc/TODO.txt index c01b13ab..feed2b9a 100644 --- a/doc/TODO.txt +++ b/doc/TODO.txt @@ -185,6 +185,11 @@ o Consider decoupling DXF-specific functionality from the 2D subsystem o Visitation refactoring - Make AbstractNode members private/protected? +BUILD SYSTEM +------------ +o Fedora is reported to ship with byacc, which doesn't support bison extensions (e.g. %debuig). Look into this, either be yacc-compatible or force the build system to use bison. +o We currently link in -lboost_thread. Should we always use -lboost_thread-mt under Linux or can we pick this up using qmake? + TESTING ------- o Caching and MDI looks suspicious when the code relies on external resources @@ -208,9 +213,6 @@ MISC ---- o Streamline the cmd-line interface a bit - Implicit output file format -o Mac OS X: - - 32-bit compatibility - o Build everything including i386 arch o Write checklists for typical extension work (add new module, add new function) -> make sure new test files are added From e2ae2a714d623473b7e85c32b22a08156f461d77 Mon Sep 17 00:00:00 2001 From: Giles Bathgate Date: Wed, 17 Nov 2010 21:27:10 +0000 Subject: [PATCH 11/14] This adds support for escape sequences in strings e.g \t \n \r \" \\ --- src/lexer.l | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/lexer.l b/src/lexer.l index 49243fdd..b9491693 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -140,11 +140,15 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { {DIGIT}+|{DIGIT}*\.{DIGIT}+|{DIGIT}+\.{DIGIT}* { parserlval.number = QString(yytext).toDouble(); return TOK_NUMBER; } "$"?[a-zA-Z0-9_]+ { parserlval.text = strdup(yytext); return TOK_ID; } -\"[^"]*\" { - parserlval.text = strdup(yytext+1); - parserlval.text[strlen(parserlval.text)-1] = 0; - return TOK_STRING; -} +\"(\\[tnr\"\\]|[^\\"])*\" { QString str(yytext+1); + str.chop(1); + str=str.replace("\\\\","\\"); + str=str.replace("\\\"","\""); + str=str.replace("\\t","\t"); + str=str.replace("\\n","\n"); + str=str.replace("\\r","\r"); + parserlval.text = strdup(str.toAscii().data()); + return TOK_STRING; } [\n\r\t ] \/\/[^\n]*\n? From ff249dfefb59a7d999210be269d1169c3db5646d Mon Sep 17 00:00:00 2001 From: Giles Bathgate Date: Tue, 30 Nov 2010 20:44:05 +0000 Subject: [PATCH 12/14] Improvement to lexing of strings don't use QString.replace, use the power of flex instead. --- src/lexer.l | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/lexer.l b/src/lexer.l index b9491693..86006d06 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -30,7 +30,7 @@ #include "parser_yacc.h" #include #include - +QString* stringcontents; int lexerget_lineno(void); #ifdef __GNUC__ static void yyunput(int, char*) __attribute__((unused)); @@ -63,7 +63,7 @@ extern const char *parser_source_path; %option yylineno %option noyywrap -%x comment +%x comment string DIGIT [0-9] @@ -140,15 +140,19 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { {DIGIT}+|{DIGIT}*\.{DIGIT}+|{DIGIT}+\.{DIGIT}* { parserlval.number = QString(yytext).toDouble(); return TOK_NUMBER; } "$"?[a-zA-Z0-9_]+ { parserlval.text = strdup(yytext); return TOK_ID; } -\"(\\[tnr\"\\]|[^\\"])*\" { QString str(yytext+1); - str.chop(1); - str=str.replace("\\\\","\\"); - str=str.replace("\\\"","\""); - str=str.replace("\\t","\t"); - str=str.replace("\\n","\n"); - str=str.replace("\\r","\r"); - parserlval.text = strdup(str.toAscii().data()); - return TOK_STRING; } +\" { BEGIN(string); stringcontents = new QString(); } +{ +\\n { stringcontents->append('\n'); } +\\t { stringcontents->append('\t'); } +\\r { stringcontents->append('\r'); } +\\\\ { stringcontents->append('\\'); } +\\\" { stringcontents->append('"'); } +[^\\\n\"]+ { stringcontents->append(lexertext); } +\" { BEGIN(INITIAL); + parserlval.text = strdup(stringcontents->toLocal8Bit()); + delete stringcontents; + return TOK_STRING; } +} [\n\r\t ] \/\/[^\n]*\n? From 5ef31011f39106318981d758967b64b5ee2fb275 Mon Sep 17 00:00:00 2001 From: Giles Bathgate Date: Fri, 3 Dec 2010 17:43:00 +0000 Subject: [PATCH 13/14] Added support for nested includes. --- src/lexer.l | 72 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 16 deletions(-) diff --git a/src/lexer.l b/src/lexer.l index 86006d06..91606c6e 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -28,6 +28,7 @@ #include "openscad.h" #include "printutils.h" #include "parser_yacc.h" +#include #include #include QString* stringcontents; @@ -58,35 +59,33 @@ extern const char *parser_source_path; } \ } +void includefile(); +QDir sourcepath(); +QStack path_stack; + +QString filename; +QString filepath; + %} %option yylineno %option noyywrap %x comment string +%x include path DIGIT [0-9] %% -include[ \t\r\n>]*"<"[^ \t\r\n>]+">" { - QString filename(yytext); - filename.remove(QRegExp("^include[ \t\r\n>]*<")); - filename.remove(QRegExp(">$")); - QFileInfo finfo(QDir(parser_source_path), filename); - if (!finfo.exists()) { - finfo = QFileInfo(QDir(librarydir), filename); - } - handle_dep(finfo.absoluteFilePath()); - yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r"); - if (!yyin) { - PRINTA("WARNING: Can't open input file `%1'.", filename); - } else { - yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE )); - BEGIN(INITIAL); - } +include[ \t\r\n>]*"<" { BEGIN(include); } +{ +[^\t\r\n>]+"/" { filepath = yytext; } +[^\t\r\n>/]+ { filename = yytext; } +">" { BEGIN(INITIAL); includefile(); } } + use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { QString filename(yytext); filename.remove(QRegExp("^use[ \t\r\n>]*<")); @@ -121,6 +120,8 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { } <> { + if(!path_stack.isEmpty()) + path_stack.pop(); if (yyin && yyin != stdin) fclose(yyin); yypop_buffer_state(); @@ -169,3 +170,42 @@ use[ \t\r\n>]*"<"[^ \t\r\n>]+">" { . { return yytext[0]; } +%% + +QDir sourcepath() +{ + if(!path_stack.isEmpty()) + return path_stack.top(); + + return QDir(parser_source_path); +} + +void includefile() +{ + if(filename.isEmpty()) + return; + + if(filepath.isEmpty()) { + path_stack.push(sourcepath()); + } else { + QFileInfo dirinfo(sourcepath(),filepath); + path_stack.push(dirinfo.dir()); + filepath.clear(); + } + + QFileInfo finfo(sourcepath(), filename); + if (!finfo.exists()) { + finfo = QFileInfo(QDir(librarydir), filename); + } + + handle_dep(finfo.absoluteFilePath()); + yyin = fopen(finfo.absoluteFilePath().toLocal8Bit(), "r"); + if (!yyin) { + PRINTA("WARNING: Can't open input file `%1'.", filename); + return; + } + filename.clear(); + + yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE )); +} + From d98e398ec185f87501c1374cc3863457ed450663 Mon Sep 17 00:00:00 2001 From: Giles Bathgate Date: Thu, 9 Dec 2010 12:18:24 +0000 Subject: [PATCH 14/14] Removed some unneeded cruft. --- src/lexer.l | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lexer.l b/src/lexer.l index 91606c6e..9e8aaf85 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -72,7 +72,7 @@ QString filepath; %option noyywrap %x comment string -%x include path +%x include DIGIT [0-9] @@ -80,9 +80,9 @@ DIGIT [0-9] include[ \t\r\n>]*"<" { BEGIN(include); } { -[^\t\r\n>]+"/" { filepath = yytext; } -[^\t\r\n>/]+ { filename = yytext; } -">" { BEGIN(INITIAL); includefile(); } +[^\t\r\n>]+"/" { filepath = yytext; } +[^\t\r\n>/]+ { filename = yytext; } +">" { BEGIN(INITIAL); includefile(); } }