Added CSGTextCache for experimenting with cache-tree organization

stl_dim
Marius Kintel 2010-04-12 06:57:02 +02:00
parent e8e213b3c9
commit 1caf80e561
15 changed files with 139 additions and 149 deletions

View File

@ -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)));
}
}

View File

@ -1,11 +1,13 @@
#ifndef CGALRENDERER_H_
#define CGALRENDERER_H_
#include "myqhash.h"
#include <string>
#include <map>
#include <list>
#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<QString, CGAL_Nef_polyhedron> &cache, const NodeCache<string> &dumpcache) : cache(cache), dumpcache(dumpcache) {}
CGALRenderer(QHash<string, CGAL_Nef_polyhedron> &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<pair<const AbstractNode *, QString> > ChildList;
typedef list<pair<const AbstractNode *, string> > ChildList;
map<int, ChildList> visitedchildren;
QHash<QString, CGAL_Nef_polyhedron> &cache;
const NodeCache<string> &dumpcache;
QHash<string, CGAL_Nef_polyhedron> &cache;
const Tree &tree;
};
#endif

View File

@ -2,7 +2,6 @@
#define POLYSETCGALRENDERER_H_
#include "PolySetRenderer.h"
#include <QHash>
#include "CGALRenderer.h"
/*!

View File

@ -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;

View File

@ -1,10 +1,10 @@
#ifndef GRID_H_
#define GRID_H_
#include <QHash>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <QHash>
const double GRID_COARSE = 0.001;
const double GRID_FINE = 0.000001;

9
src/myqhash.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef OPENSCAD_QHASH_H_
#define OPENSCAD_QHASH_H_
#include <qglobal.h>
#include <string>
extern uint qHash(const std::string &);
#include <QHash>
#endif

19
src/qhash.cc Normal file
View File

@ -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<const uchar *>(str.c_str()), str.length());
}

27
test-code/CSGTextCache.cc Normal file
View File

@ -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();
}

27
test-code/CSGTextCache.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef CSGTEXTCACHE_H_
#define CSGTEXTCACHE_H_
#include "myqhash.h"
#include "Tree.h"
#include <string>
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<string, string> cache;
const Tree &tree;
};
#endif

View File

@ -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<const uchar *>(str.c_str()), str.length());
}

View File

@ -1,26 +1,20 @@
#ifndef CSGTEXTRENDERER_H_
#define CSGTEXTRENDERER_H_
#include <qglobal.h>
#include <string>
extern uint qHash(const std::string &);
#include "visitor.h"
#include "CSGTextCache.h"
#include <map>
#include <list>
#include <QHash>
#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<string, string> &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<pair<const AbstractNode *, string> > ChildList;
typedef list<const AbstractNode *> ChildList;
map<int, ChildList> visitedchildren;
QHash<string, string> &cache;
const Tree &tree;
CSGTextCache &cache;
};
#endif

View File

@ -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 <QApplication>
#include <QFile>
@ -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<string, CGAL_Nef_polyhedron> cache;
QHash<std::string, CGAL_Nef_polyhedron> cache;
void cgalTree(Tree &tree)
{
const AbstractNode *root = tree.root();
assert(root);
NodeCache<string> &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);

View File

@ -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

View File

@ -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<string, string> 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();

View File

@ -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