diff --git a/src/CGALRenderer.cc b/src/CGALRenderer.cc index 67529b38..3fd0d7b9 100644 --- a/src/CGALRenderer.cc +++ b/src/CGALRenderer.cc @@ -1,7 +1,6 @@ #include "CGALRenderer.h" #include "visitor.h" #include "state.h" -#include "nodecache.h" #include "module.h" // FIXME: Temporarily for ModuleInstantiation #include "printutils.h" @@ -29,12 +28,12 @@ CGAL_Nef_polyhedron CGALRenderer::renderCGALMesh(const AbstractNode &node) render.execute(); assert(isCached(node)); } - return this->cache[this->dumpcache[node]]; + return this->cache[this->tree.getString(node)]; } bool CGALRenderer::isCached(const AbstractNode &node) const { - return this->cache.contains(this->dumpcache[node]); + return this->cache.contains(this->tree.getString(node)); } /*! @@ -94,7 +93,7 @@ void CGALRenderer::applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp iter != this->visitedchildren[node.index()].end(); iter++) { const AbstractNode *chnode = iter->first; - const QString &chcacheid = iter->second; + const string &chcacheid = iter->second; // FIXME: Don't use deep access to modinst members if (chnode->modinst->tag_background) continue; assert(isCached(*chnode)); @@ -109,7 +108,7 @@ void CGALRenderer::applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp chnode->progress_report(); } } - this->cache.insert(this->dumpcache[node], N); + this->cache.insert(this->tree.getString(node), N); } /* @@ -172,7 +171,7 @@ Response CGALRenderer::visit(const State &state, const TransformNode &node) applyToChildren(node, UNION); // Then apply transform - CGAL_Nef_polyhedron N = this->cache[this->dumpcache[node]]; + CGAL_Nef_polyhedron N = this->cache[this->tree.getString(node)]; assert(N.dim >= 2 && N.dim <= 3); if (N.dim == 2) { // Unfortunately CGAL provides no transform method for CGAL_Nef_polyhedron2 @@ -205,7 +204,7 @@ Response CGALRenderer::visit(const State &state, const TransformNode &node) node.m[2], node.m[6], node.m[10], node.m[14], node.m[15]); N.p3.transform(t); } - this->cache.insert(cacheid, N); + this->cache.insert(this->tree.getString(node), N); } addToParent(state, node); } @@ -237,7 +236,7 @@ Response CGALRenderer::visit(const State &state, const AbstractPolyNode &node) node.progress_report(); ps->unlink(); - this->cache.insert(this->dumpcache[node], N); + this->cache.insert(this->tree.getString(node), N); } catch (...) { // Don't leak the PolySet on ProgressCancelException ps->unlink(); @@ -258,7 +257,7 @@ void CGALRenderer::addToParent(const State &state, const AbstractNode &node) assert(state.isPostfix()); this->visitedchildren.erase(node.index()); if (state.parent()) { - this->visitedchildren[state.parent()->index()].push_back(std::make_pair(&node, this->dumpcache[node])); + this->visitedchildren[state.parent()->index()].push_back(std::make_pair(&node, this->tree.getString(node))); } } diff --git a/src/CGALRenderer.h b/src/CGALRenderer.h index 0492c86e..11abaa33 100644 --- a/src/CGALRenderer.h +++ b/src/CGALRenderer.h @@ -1,11 +1,13 @@ #ifndef CGALRENDERER_H_ #define CGALRENDERER_H_ +#include "myqhash.h" + #include #include #include #include "visitor.h" -#include "nodecache.h" +#include "Tree.h" #include "cgal.h" #ifdef ENABLE_CGAL @@ -23,7 +25,7 @@ class CGALRenderer : public Visitor public: enum CsgOp {UNION, INTERSECTION, DIFFERENCE, MINKOWSKI}; // FIXME: If a cache is not given, we need to fix this ourselves - CGALRenderer(QHash &cache, const NodeCache &dumpcache) : cache(cache), dumpcache(dumpcache) {} + CGALRenderer(QHash &cache, const Tree &tree) : cache(cache), tree(tree) {} virtual ~CGALRenderer() {} virtual Response visit(const State &state, const AbstractNode &node); @@ -38,16 +40,15 @@ public: private: void addToParent(const State &state, const AbstractNode &node); bool isCached(const AbstractNode &node) const; - QString mk_cache_id(const AbstractNode &node) const; void process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, CGALRenderer::CsgOp op); void applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp op); string currindent; - typedef list > ChildList; + typedef list > ChildList; map visitedchildren; - QHash &cache; - const NodeCache &dumpcache; + QHash &cache; + const Tree &tree; }; #endif diff --git a/src/PolySetCGALRenderer.h b/src/PolySetCGALRenderer.h index fb708ed6..ef71a570 100644 --- a/src/PolySetCGALRenderer.h +++ b/src/PolySetCGALRenderer.h @@ -2,7 +2,6 @@ #define POLYSETCGALRENDERER_H_ #include "PolySetRenderer.h" -#include #include "CGALRenderer.h" /*! diff --git a/src/Tree.h b/src/Tree.h index 9cfef841..fec44645 100644 --- a/src/Tree.h +++ b/src/Tree.h @@ -2,7 +2,6 @@ #define TREE_H_ #include "nodecache.h" -//#include "cgal.h" using std::string; @@ -19,7 +18,6 @@ public: // FIXME: Really return a reference? const string &getString(const AbstractNode &node) const; -// CGAL_Nef_polyhedron getCGALMesh(const AbstractNode &node) const; private: const AbstractNode *root_node; diff --git a/src/grid.h b/src/grid.h index 572bc665..6694cf7c 100644 --- a/src/grid.h +++ b/src/grid.h @@ -1,10 +1,10 @@ #ifndef GRID_H_ #define GRID_H_ +#include #include #include #include -#include const double GRID_COARSE = 0.001; const double GRID_FINE = 0.000001; diff --git a/src/myqhash.h b/src/myqhash.h new file mode 100644 index 00000000..13eba093 --- /dev/null +++ b/src/myqhash.h @@ -0,0 +1,9 @@ +#ifndef OPENSCAD_QHASH_H_ +#define OPENSCAD_QHASH_H_ + +#include +#include +extern uint qHash(const std::string &); +#include + +#endif diff --git a/src/qhash.cc b/src/qhash.cc new file mode 100644 index 00000000..cec9adf0 --- /dev/null +++ b/src/qhash.cc @@ -0,0 +1,19 @@ +#include "myqhash.h" + +static uint hash(const uchar *p, int n) +{ + uint h = 0; + uint g; + + while (n--) { + h = (h << 4) + *p++; + if ((g = (h & 0xf0000000)) != 0) + h ^= g >> 23; + h &= ~g; + } + return h; +} + +uint qHash(const std::string &str) { + return hash(reinterpret_cast(str.c_str()), str.length()); +} diff --git a/test-code/CSGTextCache.cc b/test-code/CSGTextCache.cc new file mode 100644 index 00000000..4234c63e --- /dev/null +++ b/test-code/CSGTextCache.cc @@ -0,0 +1,27 @@ +#include "CSGTextCache.h" + +bool CSGTextCache::contains(const AbstractNode &node) const +{ + return this->cache.contains(this->tree.getString(node)); +} + +// We cannot return a reference since the [] operator returns a temporary value +string CSGTextCache::operator[](const AbstractNode &node) const +{ + return this->cache[this->tree.getString(node)]; +} + +void CSGTextCache::insert(const class AbstractNode &node, const string & value) +{ + this->cache.insert(this->tree.getString(node), value); +} + +void CSGTextCache::remove(const class AbstractNode &node) +{ + this->cache.remove(this->tree.getString(node)); +} + +void CSGTextCache::clear() +{ + this->cache.clear(); +} diff --git a/test-code/CSGTextCache.h b/test-code/CSGTextCache.h new file mode 100644 index 00000000..57a69726 --- /dev/null +++ b/test-code/CSGTextCache.h @@ -0,0 +1,27 @@ +#ifndef CSGTEXTCACHE_H_ +#define CSGTEXTCACHE_H_ + +#include "myqhash.h" +#include "Tree.h" +#include + +using std::string; + +class CSGTextCache +{ +public: + CSGTextCache(const Tree &tree) : tree(tree) {} + ~CSGTextCache() {} + + bool contains(const AbstractNode &node) const; + string operator[](const AbstractNode &node) const; + void insert(const class AbstractNode &node, const string & value); + void remove(const class AbstractNode &node); + void clear(); + +private: + QHash cache; + const Tree &tree; +}; + +#endif diff --git a/test-code/CSGTextRenderer.cc b/test-code/CSGTextRenderer.cc index ab498f69..6f1010c1 100644 --- a/test-code/CSGTextRenderer.cc +++ b/test-code/CSGTextRenderer.cc @@ -17,7 +17,7 @@ bool CSGTextRenderer::isCached(const AbstractNode &node) { - return this->cache.contains(this->tree.getString(node)); + return this->cache.contains(node); } /*! @@ -47,49 +47,6 @@ CSGTextRenderer::process(string &target, const string &src, CSGTextRenderer::Csg } } -// /*! -// Modifies target by applying op to target and src: -// target = target [op] src -// */ -// void process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, CsgOp op) -// { -// if (target.dim == 2) { -// switch (op) { -// case UNION: -// target.p2 += src.p2; -// break; -// case INTERSECTION: -// target.p2 *= src.p2; -// break; -// case DIFFERENCE: -// target.p2 -= src.p2; -// break; -// case MINKOWSKI: -// target.p2 = minkowski2(target.p2, src.p2); -// break; -// } -// } -// else if (target.dim == 3) { -// switch (op) { -// case UNION: -// target.p3 += src.p3; -// break; -// case INTERSECTION: -// target.p3 *= src.p3; -// break; -// case DIFFERENCE: -// target.p3 -= src.p3; -// break; -// case MINKOWSKI: -// target.p3 = minkowski3(target.p3, src.p3); -// break; -// } -// } -// else { -// assert(false && "Dimention of Nef polyhedron must be 2 or 3"); -// } -// } - void CSGTextRenderer::applyToChildren(const AbstractNode &node, CSGTextRenderer::CsgOp op) { std::stringstream stream; @@ -99,26 +56,25 @@ void CSGTextRenderer::applyToChildren(const AbstractNode &node, CSGTextRenderer: if (this->visitedchildren[node.index()].size() > 0) { // FIXME: assert that cache contains nodes in code below bool first = true; -// CGAL_Nef_polyhedron N; for (ChildList::const_iterator iter = this->visitedchildren[node.index()].begin(); iter != this->visitedchildren[node.index()].end(); iter++) { - const AbstractNode *chnode = iter->first; - const string &chcacheid = iter->second; + const AbstractNode *chnode = *iter; + assert(this->cache.contains(*chnode)); // FIXME: Don't use deep access to modinst members if (chnode->modinst->tag_background) continue; if (first) { - N += "(" + this->cache[chcacheid]; + N += "(" + this->cache[*chnode]; // if (N.dim != 0) first = false; // FIXME: when can this happen? first = false; } else { - process(N, this->cache[chcacheid], op); + process(N, this->cache[*chnode], op); } chnode->progress_report(); } N += ")"; } - this->cache.insert(this->tree.getString(node), N); + this->cache.insert(node, N); } /* @@ -204,23 +160,8 @@ Response CSGTextRenderer::visit(const State &state, const AbstractPolyNode &node // FIXME: Manage caching // FIXME: Will generate one single Nef polyhedron (no csg ops necessary) -// PolySet *ps = render_polyset(RENDER_CGAL); -// try { -// 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(); - -// ps->unlink(); -// return N; -// } -// catch (...) { // Don't leak the PolySet on ProgressCancelException -// ps->unlink(); -// throw; -// } - string N = typeid(node).name(); - this->cache.insert(this->tree.getString(node), N); + this->cache.insert(node, N); // std::cout << "Insert: " << N << "\n"; // std::cout << "Node: " << cacheid.toStdString() << "\n\n"; @@ -240,26 +181,6 @@ void CSGTextRenderer::addToParent(const State &state, const AbstractNode &node) assert(state.isPostfix()); this->visitedchildren.erase(node.index()); if (state.parent()) { - this->visitedchildren[state.parent()->index()].push_back(std::make_pair(&node, this->tree.getString(node))); + this->visitedchildren[state.parent()->index()].push_back(&node); } } - - - -static uint hash(const uchar *p, int n) -{ - uint h = 0; - uint g; - - while (n--) { - h = (h << 4) + *p++; - if ((g = (h & 0xf0000000)) != 0) - h ^= g >> 23; - h &= ~g; - } - return h; -} - -uint qHash(const string &str) { - return hash(reinterpret_cast(str.c_str()), str.length()); -} diff --git a/test-code/CSGTextRenderer.h b/test-code/CSGTextRenderer.h index 236f900b..4085e60b 100644 --- a/test-code/CSGTextRenderer.h +++ b/test-code/CSGTextRenderer.h @@ -1,26 +1,20 @@ #ifndef CSGTEXTRENDERER_H_ #define CSGTEXTRENDERER_H_ -#include -#include -extern uint qHash(const std::string &); +#include "visitor.h" +#include "CSGTextCache.h" #include #include -#include -#include "visitor.h" -#include "Tree.h" using std::string; using std::map; using std::list; -using std::pair; class CSGTextRenderer : public Visitor { public: - CSGTextRenderer(QHash &cache, const Tree &tree) : - cache(cache), tree(tree) {} + CSGTextRenderer(CSGTextCache &cache) : cache(cache) {} virtual ~CSGTextRenderer() {} virtual Response visit(const State &state, const AbstractNode &node); @@ -37,11 +31,10 @@ private: void applyToChildren(const AbstractNode &node, CSGTextRenderer::CsgOp op); string currindent; - typedef list > ChildList; + typedef list ChildList; map visitedchildren; - QHash &cache; - const Tree &tree; + CSGTextCache &cache; }; #endif diff --git a/test-code/cgaltest.cc b/test-code/cgaltest.cc index 147e390d..ed646cea 100644 --- a/test-code/cgaltest.cc +++ b/test-code/cgaltest.cc @@ -23,6 +23,7 @@ * */ +#include "myqhash.h" #include "openscad.h" #include "node.h" #include "module.h" @@ -30,10 +31,9 @@ #include "value.h" #include "export.h" #include "builtin.h" -#include "nodedumper.h" +#include "Tree.h" #include "CGALRenderer.h" #include "PolySetCGALRenderer.h" -#include "Tree.h" #include #include @@ -49,6 +49,8 @@ QString currentdir; QString examplesdir; QString librarydir; +using std::string; + void handle_dep(QString filename) { if (filename.startsWith("/")) @@ -63,20 +65,14 @@ void handle_dep(QString filename) } // FIXME: enforce some maximum cache size (old version had 100K vertices as limit) -QHash cache; +QHash cache; void cgalTree(Tree &tree) { - const AbstractNode *root = tree.root(); - assert(root); - NodeCache &cache = tree.cache(); - NodeDumper dumper(cache, false); - Traverser trav(dumper, *root, Traverser::PRE_AND_POSTFIX); - trav.execute(); - assert(!cache[*root].empty()); + assert(tree.root()); - CSGTextRenderer renderer(csgcache, cache); - Traverser render(renderer, *root, Traverser::PRE_AND_POSTFIX); + CGALRenderer renderer(cache, tree); + Traverser render(renderer, *tree.root(), Traverser::PRE_AND_POSTFIX); render.execute(); } @@ -170,16 +166,13 @@ int main(int argc, char **argv) cgalTree(tree); - std::cout << cache[tree.cache()[*root_node]] << "\n"; + std::cout << tree.getString(*root_node) << "\n"; - CGALRenderer cgalrenderer(dumper.getCache()); - PolySetCGALRenderer psrenderer(cgalrenderer); - PolySetRenderer::setRenderer(&psrenderer); +// CGALRenderer cgalrenderer(dumper.getCache()); +// PolySetCGALRenderer psrenderer(cgalrenderer); +// PolySetRenderer::setRenderer(&psrenderer); -// This is done in renderCGALMesh() for convenience, but can be overridden here -// Traverser render(cgalrenderer, *root_node, Traverser::PRE_AND_POSTFIX); -// render.execute(); - CGAL_Nef_polyhedron N = cgalrenderer.renderCGALMesh(*root_node); + CGAL_Nef_polyhedron N = cache[tree.getString(*root_node)]; QDir::setCurrent(original_path.absolutePath()); export_stl(&N, fileInfo.baseName() + ".stl", NULL); diff --git a/test-code/cgaltest.pro b/test-code/cgaltest.pro index a91cb5ba..5f0ea994 100644 --- a/test-code/cgaltest.pro +++ b/test-code/cgaltest.pro @@ -62,6 +62,7 @@ HEADERS += ../src/builtin.h \ ../src/state.h \ ../src/PolySetRenderer.h \ ../src/PolySetCGALRenderer.h \ + ../src/myqhash.h \ ../src/Tree.h SOURCES += cgaltest.cc \ @@ -100,4 +101,5 @@ SOURCES += cgaltest.cc \ ../src/traverser.cc \ ../src/PolySetRenderer.cc \ ../src/PolySetCGALRenderer.cc \ + ../src/qhash.cc \ ../src/Tree.cc diff --git a/test-code/csgtexttest.cc b/test-code/csgtexttest.cc index f464900e..95b530d3 100644 --- a/test-code/csgtexttest.cc +++ b/test-code/csgtexttest.cc @@ -24,6 +24,7 @@ */ #include "CSGTextRenderer.h" +#include "CSGTextCache.h" #include "openscad.h" #include "node.h" #include "module.h" @@ -61,14 +62,10 @@ void handle_dep(QString filename) } } - -QHash csgcache; -void csgTree(Tree &tree) +void csgTree(CSGTextCache &cache, const AbstractNode &root) { - assert(tree.root()); - - CSGTextRenderer renderer(csgcache, tree); - Traverser render(renderer, *tree.root(), Traverser::PRE_AND_POSTFIX); + CSGTextRenderer renderer(cache); + Traverser render(renderer, root, Traverser::PRE_AND_POSTFIX); render.execute(); } @@ -159,11 +156,12 @@ int main(int argc, char **argv) Tree tree; tree.setRoot(root_node); + CSGTextCache csgcache(tree); - csgTree(tree); + csgTree(csgcache, *root_node); std::cout << tree.getString(*root_node) << "\n"; - std::cout << csgcache[tree.getString(*root_node)] << "\n"; + std::cout << csgcache[*root_node] << "\n"; destroy_builtin_functions(); destroy_builtin_modules(); diff --git a/test-code/csgtexttest.pro b/test-code/csgtexttest.pro index a1c3148b..8fd47697 100644 --- a/test-code/csgtexttest.pro +++ b/test-code/csgtexttest.pro @@ -66,7 +66,9 @@ HEADERS += ../src/builtin.h \ ../src/state.h \ ../src/PolySetRenderer.h \ ../src/Tree.h \ - CSGTextRenderer.h + ../src/myqhash.h \ + CSGTextRenderer.h \ + CSGTextCache.h SOURCES += csgtexttest.cc \ ../src/export.cc \ @@ -100,4 +102,6 @@ SOURCES += csgtexttest.cc \ ../src/traverser.cc \ ../src/PolySetRenderer.cc \ ../src/Tree.cc \ - CSGTextRenderer.cc + ../src/qhash.cc \ + CSGTextRenderer.cc \ + CSGTextCache.cc