mirror of https://github.com/vitalif/openscad
Another refactoring session:
o mk_cache_id() obsoleted by removing the node index from the dump o node index output removed from each node and make optional in NodeDumper o The visitors are no longer global, but associated with a tree o Added Tree class to manage node trees and the (now implicit) dump cache o Moved PolySet cache into PolySetRendererstl_dim
parent
53a9953b7d
commit
e8e213b3c9
|
@ -22,8 +22,6 @@
|
|||
#include <assert.h>
|
||||
#include <QRegExp>
|
||||
|
||||
CGALRenderer *CGALRenderer::global_renderer = NULL;
|
||||
|
||||
CGAL_Nef_polyhedron CGALRenderer::renderCGALMesh(const AbstractNode &node)
|
||||
{
|
||||
if (!isCached(node)) {
|
||||
|
@ -31,12 +29,12 @@ CGAL_Nef_polyhedron CGALRenderer::renderCGALMesh(const AbstractNode &node)
|
|||
render.execute();
|
||||
assert(isCached(node));
|
||||
}
|
||||
return this->cache[mk_cache_id(node)];
|
||||
return this->cache[this->dumpcache[node]];
|
||||
}
|
||||
|
||||
bool CGALRenderer::isCached(const AbstractNode &node) const
|
||||
{
|
||||
return this->cache.contains(mk_cache_id(node));
|
||||
return this->cache.contains(this->dumpcache[node]);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -111,8 +109,7 @@ void CGALRenderer::applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp
|
|||
chnode->progress_report();
|
||||
}
|
||||
}
|
||||
QString cacheid = mk_cache_id(node);
|
||||
this->cache.insert(cacheid, N);
|
||||
this->cache.insert(this->dumpcache[node], N);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -175,8 +172,7 @@ Response CGALRenderer::visit(const State &state, const TransformNode &node)
|
|||
applyToChildren(node, UNION);
|
||||
|
||||
// Then apply transform
|
||||
QString cacheid = mk_cache_id(node);
|
||||
CGAL_Nef_polyhedron N = this->cache[cacheid];
|
||||
CGAL_Nef_polyhedron N = this->cache[this->dumpcache[node]];
|
||||
assert(N.dim >= 2 && N.dim <= 3);
|
||||
if (N.dim == 2) {
|
||||
// Unfortunately CGAL provides no transform method for CGAL_Nef_polyhedron2
|
||||
|
@ -241,8 +237,7 @@ Response CGALRenderer::visit(const State &state, const AbstractPolyNode &node)
|
|||
node.progress_report();
|
||||
|
||||
ps->unlink();
|
||||
QString cacheid = mk_cache_id(node);
|
||||
this->cache.insert(cacheid, N);
|
||||
this->cache.insert(this->dumpcache[node], N);
|
||||
}
|
||||
catch (...) { // Don't leak the PolySet on ProgressCancelException
|
||||
ps->unlink();
|
||||
|
@ -261,35 +256,10 @@ Response CGALRenderer::visit(const State &state, const AbstractPolyNode &node)
|
|||
void CGALRenderer::addToParent(const State &state, const AbstractNode &node)
|
||||
{
|
||||
assert(state.isPostfix());
|
||||
QString cacheid = mk_cache_id(node);
|
||||
this->visitedchildren.erase(node.index());
|
||||
if (!state.parent()) {
|
||||
this->root = &node;
|
||||
if (state.parent()) {
|
||||
this->visitedchildren[state.parent()->index()].push_back(std::make_pair(&node, this->dumpcache[node]));
|
||||
}
|
||||
else {
|
||||
this->visitedchildren[state.parent()->index()].push_back(std::make_pair(&node, cacheid));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Create a cache id of the entire tree under this node. This cache id
|
||||
is a non-whitespace plaintext of the evaluated scad tree and is used
|
||||
for lookup in cgal_nef_cache.
|
||||
*/
|
||||
QString CGALRenderer::mk_cache_id(const AbstractNode &node) const
|
||||
{
|
||||
// FIXME: should we keep a cache of cache_id's to avoid recalculating this?
|
||||
// -> check how often we recalculate it.
|
||||
|
||||
// FIXME: Get dump from dump cache
|
||||
// FIXME: assert that cache contains node
|
||||
QString cache_id = QString::fromStdString(this->dumpcache[node]);
|
||||
// Remove all node indices and whitespace
|
||||
cache_id.remove(QRegExp("[a-zA-Z_][a-zA-Z_0-9]*:"));
|
||||
cache_id.remove(' ');
|
||||
cache_id.remove('\t');
|
||||
cache_id.remove('\n');
|
||||
return cache_id;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -22,8 +22,8 @@ class CGALRenderer : public Visitor
|
|||
{
|
||||
public:
|
||||
enum CsgOp {UNION, INTERSECTION, DIFFERENCE, MINKOWSKI};
|
||||
// FIXME: If a cache is not give, we need to fix this ourselves
|
||||
CGALRenderer(const NodeCache<string> &dumpcache) : root(NULL), dumpcache(dumpcache) {}
|
||||
// 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) {}
|
||||
virtual ~CGALRenderer() {}
|
||||
|
||||
virtual Response visit(const State &state, const AbstractNode &node);
|
||||
|
@ -32,14 +32,9 @@ public:
|
|||
virtual Response visit(const State &state, const TransformNode &node);
|
||||
virtual Response visit(const State &state, const AbstractPolyNode &node);
|
||||
|
||||
QHash<QString, CGAL_Nef_polyhedron> &getCache() { return this->cache; }
|
||||
|
||||
CGAL_Nef_polyhedron renderCGALMesh(const AbstractNode &node);
|
||||
CGAL_Nef_polyhedron renderCGALMesh(const PolySet &polyset);
|
||||
|
||||
// FIXME: Questionable design...
|
||||
static CGALRenderer *renderer() { return global_renderer; }
|
||||
static void setRenderer(CGALRenderer *r) { global_renderer = r; }
|
||||
private:
|
||||
void addToParent(const State &state, const AbstractNode &node);
|
||||
bool isCached(const AbstractNode &node) const;
|
||||
|
@ -48,15 +43,11 @@ private:
|
|||
void applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp op);
|
||||
|
||||
string currindent;
|
||||
const AbstractNode *root;
|
||||
typedef list<pair<const AbstractNode *, QString> > ChildList;
|
||||
map<int, ChildList> visitedchildren;
|
||||
|
||||
// FIXME: enforce some maximum cache size (old version had 100K vertices as limit)
|
||||
QHash<QString, CGAL_Nef_polyhedron> cache;
|
||||
QHash<QString, CGAL_Nef_polyhedron> &cache;
|
||||
const NodeCache<string> &dumpcache;
|
||||
|
||||
static CGALRenderer *global_renderer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,7 @@ public:
|
|||
ModuleInstantiation root_inst; // Top level instance
|
||||
AbstractNode *absolute_root_node; // Result of tree evaluation
|
||||
AbstractNode *root_node; // Root if the root modifier (!) is used
|
||||
class NodeDumper *dumper;
|
||||
|
||||
class CSGTerm *root_raw_term; // Result of CSG term rendering
|
||||
CSGTerm *root_norm_term; // Normalized CSG products
|
||||
|
@ -76,6 +77,7 @@ private:
|
|||
void compileCSG(bool procevents);
|
||||
bool maybeSave();
|
||||
bool checkModified();
|
||||
QString dumpCSGTree(AbstractNode *root);
|
||||
static void consoleOutput(const QString &msg, void *userdata) {
|
||||
static_cast<MainWindow*>(userdata)->console->append(msg);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
|
||||
PolySet *PolySetCGALRenderer::renderPolySet(const ProjectionNode &node, AbstractPolyNode::render_mode_e)
|
||||
{
|
||||
// FIXME: create cacheid from node
|
||||
QString cacheid;
|
||||
if (this->cache.contains(cacheid)) return this->cache[cacheid]->ps->link();
|
||||
|
||||
CGAL_Nef_polyhedron N = this->cgalrenderer.renderCGALMesh(node);
|
||||
|
||||
PolySet *ps = new PolySet();
|
||||
|
@ -155,6 +159,7 @@ PolySet *PolySetCGALRenderer::renderPolySet(const ProjectionNode &node, Abstract
|
|||
|
||||
cant_project_non_simple_polyhedron:
|
||||
|
||||
this->cache.insert(cacheid, new cache_entry(ps->link()));
|
||||
return ps;
|
||||
}
|
||||
|
||||
|
@ -232,6 +237,10 @@ static void add_slice(PolySet *ps, DxfData::Path *pt, double rot1, double rot2,
|
|||
|
||||
PolySet *PolySetCGALRenderer::renderPolySet(const DxfLinearExtrudeNode &node, AbstractPolyNode::render_mode_e)
|
||||
{
|
||||
// FIXME: create cacheid from node
|
||||
QString cacheid;
|
||||
if (this->cache.contains(cacheid)) return this->cache[cacheid]->ps->link();
|
||||
|
||||
DxfData *dxf;
|
||||
|
||||
if (node.filename.isEmpty())
|
||||
|
@ -305,11 +314,16 @@ PolySet *PolySetCGALRenderer::renderPolySet(const DxfLinearExtrudeNode &node, Ab
|
|||
|
||||
delete dxf;
|
||||
|
||||
this->cache.insert(cacheid, new cache_entry(ps->link()));
|
||||
return ps;
|
||||
}
|
||||
|
||||
PolySet *PolySetCGALRenderer::renderPolySet(const DxfRotateExtrudeNode &node, AbstractPolyNode::render_mode_e)
|
||||
{
|
||||
// FIXME: create cacheid from node
|
||||
QString cacheid;
|
||||
if (this->cache.contains(cacheid)) return this->cache[cacheid]->ps->link();
|
||||
|
||||
DxfData *dxf;
|
||||
|
||||
if (node.filename.isEmpty())
|
||||
|
@ -380,5 +394,6 @@ PolySet *PolySetCGALRenderer::renderPolySet(const DxfRotateExtrudeNode &node, Ab
|
|||
|
||||
delete dxf;
|
||||
|
||||
this->cache.insert(cacheid, new cache_entry(ps->link()));
|
||||
return ps;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
#include "PolySetRenderer.h"
|
||||
#include "printutils.h"
|
||||
#include "polyset.h"
|
||||
|
||||
PolySetRenderer *PolySetRenderer::global_renderer = NULL;
|
||||
|
||||
PolySetRenderer::cache_entry::cache_entry(PolySet *ps) :
|
||||
ps(ps), msg(print_messages_stack.last())
|
||||
{
|
||||
}
|
||||
|
||||
PolySetRenderer::cache_entry::~cache_entry()
|
||||
{
|
||||
ps->unlink();
|
||||
}
|
||||
|
|
|
@ -2,20 +2,37 @@
|
|||
#define POLYSETRENDERER_H_
|
||||
|
||||
#include "node.h"
|
||||
#include <QCache>
|
||||
|
||||
class PolySetRenderer
|
||||
{
|
||||
public:
|
||||
enum RenderMode { RENDER_CGAL, RENDER_OPENCSG };
|
||||
PolySetRenderer() {}
|
||||
PolySetRenderer() : cache(100) {}
|
||||
|
||||
virtual ~PolySetRenderer() {}
|
||||
|
||||
virtual PolySet *renderPolySet(const class ProjectionNode &node, AbstractPolyNode::render_mode_e) = 0;
|
||||
virtual PolySet *renderPolySet(const class DxfLinearExtrudeNode &node, AbstractPolyNode::render_mode_e) = 0;
|
||||
virtual PolySet *renderPolySet(const class DxfRotateExtrudeNode &node, AbstractPolyNode::render_mode_e) = 0;
|
||||
virtual PolySet *renderPolySet(const class ProjectionNode &, AbstractPolyNode::render_mode_e) = 0;
|
||||
virtual PolySet *renderPolySet(const class DxfLinearExtrudeNode &, AbstractPolyNode::render_mode_e) = 0;
|
||||
virtual PolySet *renderPolySet(const class DxfRotateExtrudeNode &, AbstractPolyNode::render_mode_e) = 0;
|
||||
|
||||
void clearCache() {
|
||||
this->cache.clear();
|
||||
}
|
||||
|
||||
static PolySetRenderer *renderer() { return global_renderer; }
|
||||
static void setRenderer(PolySetRenderer *r) { global_renderer = r; }
|
||||
protected:
|
||||
|
||||
struct cache_entry {
|
||||
class PolySet *ps;
|
||||
QString msg;
|
||||
cache_entry(PolySet *ps);
|
||||
~cache_entry();
|
||||
};
|
||||
|
||||
QCache<QString, cache_entry> cache;
|
||||
|
||||
private:
|
||||
static PolySetRenderer *global_renderer;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#include "Tree.h"
|
||||
#include "nodedumper.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
const std::string &Tree::getString(const AbstractNode &node) const
|
||||
{
|
||||
assert(this->root_node);
|
||||
if (!this->nodecache.contains(node)) {
|
||||
NodeDumper dumper(this->nodecache, false);
|
||||
Traverser trav(dumper, *this->root_node, Traverser::PRE_AND_POSTFIX);
|
||||
trav.execute();
|
||||
assert(this->nodecache.contains(*this->root_node) &&
|
||||
"NodeDumper failed to create a cache");
|
||||
}
|
||||
return this->nodecache[node];
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef TREE_H_
|
||||
#define TREE_H_
|
||||
|
||||
#include "nodecache.h"
|
||||
//#include "cgal.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
class Tree
|
||||
{
|
||||
public:
|
||||
Tree() {
|
||||
this->root_node = NULL;
|
||||
}
|
||||
~Tree() {}
|
||||
|
||||
void setRoot(const AbstractNode *root) { this->root_node = root; }
|
||||
const AbstractNode *root() const { return this->root_node; }
|
||||
|
||||
// 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;
|
||||
mutable NodeCache nodecache;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -160,7 +160,6 @@ CSGTerm *CgaladvNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlight
|
|||
std::string CgaladvNode::toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "n" << this->index() << ": ";
|
||||
|
||||
switch (type) {
|
||||
case MINKOWSKI:
|
||||
|
|
|
@ -80,7 +80,6 @@ CSGTerm *CsgNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, Q
|
|||
std::string CsgNode::toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "n" << this->index() << ": ";
|
||||
|
||||
switch (this->type) {
|
||||
case CSG_TYPE_UNION:
|
||||
|
|
|
@ -136,16 +136,9 @@ PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e mode) const
|
|||
return ps;
|
||||
}
|
||||
|
||||
QString key = mk_cache_id();
|
||||
if (PolySet::ps_cache.contains(key)) {
|
||||
PRINT(PolySet::ps_cache[key]->msg);
|
||||
return PolySet::ps_cache[key]->ps->link();
|
||||
}
|
||||
|
||||
print_messages_push();
|
||||
|
||||
PolySet *ps = renderer->renderPolySet(*this, mode);
|
||||
PolySet::ps_cache.insert(key, new PolySet::ps_cache_entry(ps->link()));
|
||||
|
||||
print_messages_pop();
|
||||
|
||||
|
@ -155,7 +148,6 @@ PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e mode) const
|
|||
std::string DxfLinearExtrudeNode::toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "n" << this->index() << ": ";
|
||||
|
||||
QString text;
|
||||
struct stat st;
|
||||
|
|
|
@ -112,18 +112,10 @@ PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e mode) const
|
|||
return ps;
|
||||
}
|
||||
|
||||
QString key = mk_cache_id();
|
||||
if (PolySet::ps_cache.contains(key)) {
|
||||
PRINT(PolySet::ps_cache[key]->msg);
|
||||
return PolySet::ps_cache[key]->ps->link();
|
||||
}
|
||||
|
||||
print_messages_push();
|
||||
|
||||
PolySet *ps = renderer->renderPolySet(*this, mode);
|
||||
|
||||
PolySet::ps_cache.insert(key, new PolySet::ps_cache_entry(ps->link()));
|
||||
|
||||
print_messages_pop();
|
||||
|
||||
return ps;
|
||||
|
@ -132,7 +124,6 @@ PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e mode) const
|
|||
std::string DxfRotateExtrudeNode::toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "n" << this->index() << ": ";
|
||||
|
||||
struct stat st;
|
||||
memset(&st, 0, sizeof(struct stat));
|
||||
|
|
|
@ -192,7 +192,6 @@ PolySet *ImportNode::render_polyset(render_mode_e) const
|
|||
std::string ImportNode::toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "n" << this->index() << ": ";
|
||||
|
||||
QString text;
|
||||
struct stat st;
|
||||
|
|
|
@ -151,6 +151,7 @@ MainWindow::MainWindow(const QString &filename)
|
|||
root_raw_term = NULL;
|
||||
root_norm_term = NULL;
|
||||
root_chain = NULL;
|
||||
this->dumper = new NodeDumper;
|
||||
#ifdef ENABLE_CGAL
|
||||
this->root_N = NULL;
|
||||
this->recreate_cgal_ogl_p = false;
|
||||
|
@ -538,6 +539,13 @@ AbstractNode *MainWindow::find_root_tag(AbstractNode *n)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
QString MainWindow::dumpCSGTree(AbstractNode *root)
|
||||
{
|
||||
Traverser trav(*this->dumper, *root, Traverser::PRE_AND_POSTFIX);
|
||||
trav.execute();
|
||||
return QString::fromStdString(this->dumper->getDump() + "\n");
|
||||
}
|
||||
|
||||
/*!
|
||||
Parse and evaluate the design -> this->root_node
|
||||
*/
|
||||
|
@ -653,11 +661,11 @@ void MainWindow::compile(bool procevents)
|
|||
if (!(this->root_node = find_root_tag(absolute_root_node))) {
|
||||
this->root_node = absolute_root_node;
|
||||
}
|
||||
// Dump the tree (to initialize caches). I guess we wouldn't really need to do
|
||||
// this explicitly..
|
||||
root_node->dump();
|
||||
// Dump the tree (to initialize caches).
|
||||
// FIXME: We shouldn't really need to do this explicitly..
|
||||
dumpCSGTree(this->root_node);
|
||||
|
||||
if (1) {
|
||||
if (1) {
|
||||
PRINT("Compilation finished.");
|
||||
if (procevents)
|
||||
QApplication::processEvents();
|
||||
|
@ -1131,7 +1139,11 @@ void MainWindow::actionRenderCGAL()
|
|||
|
||||
progress_report_prep(root_node, report_func, pd);
|
||||
try {
|
||||
this->root_N = new CGAL_Nef_polyhedron(CGALRenderer::renderer()->renderCGALMesh(*root_node));
|
||||
// this->root_N = new CGAL_Nef_polyhedron(CGALRenderer::renderer()->renderCGALMesh(*root_node));
|
||||
|
||||
Tree *tree = this->tree;
|
||||
CGALRenderDriver renderer(tree);
|
||||
this->root_N = new CGAL_Nef_polyhedron(renderer->renderCGALMesh());
|
||||
}
|
||||
catch (ProgressCancelException e) {
|
||||
PRINT("Rendering cancelled.");
|
||||
|
@ -1234,7 +1246,7 @@ void MainWindow::actionDisplayCSGTree()
|
|||
e->setWindowTitle("CSG Tree Dump");
|
||||
e->setReadOnly(true);
|
||||
if (root_node) {
|
||||
e->setPlainText(root_node->dump());
|
||||
e->setPlainText(QString::fromStdString(this->dumper->getDump()));
|
||||
} else {
|
||||
e->setPlainText("No CSG to dump. Please try compiling first...");
|
||||
}
|
||||
|
@ -1359,10 +1371,10 @@ void MainWindow::actionExportDXF()
|
|||
void MainWindow::actionFlushCaches()
|
||||
{
|
||||
// FIXME: Polycache -> PolySetRenderer
|
||||
PolySet::ps_cache.clear();
|
||||
PolySetRenderer::renderer()->clearCache();
|
||||
#ifdef ENABLE_CGAL
|
||||
CGALRenderer::renderer()->getCache().clear();
|
||||
NodeDumper::dumper()->clearCache();
|
||||
this->dumper->clearCache();
|
||||
#endif
|
||||
dxf_dim_cache.clear();
|
||||
dxf_cross_cache.clear();
|
||||
|
|
23
src/node.cc
23
src/node.cc
|
@ -64,26 +64,17 @@ Response AbstractPolyNode::accept(const class State &state, Visitor &visitor) co
|
|||
return visitor.visit(state, *this);
|
||||
}
|
||||
|
||||
// FIXME: Temporarily offer a top-level dump function to keep existing code running
|
||||
QString AbstractNode::dump() const
|
||||
{
|
||||
NodeDumper dumper;
|
||||
Traverser trav(dumper, *this, Traverser::PRE_AND_POSTFIX);
|
||||
trav.execute();
|
||||
return QString::fromStdString(dumper.getDump() + "\n");
|
||||
}
|
||||
|
||||
std::string AbstractNode::toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "n" << this->index() << ": group()";
|
||||
stream << "group()";
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
std::string AbstractIntersectionNode::toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "n" << this->index() << ": intersection()";
|
||||
stream << "intersection()";
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
|
@ -161,13 +152,3 @@ std::ostream &operator<<(std::ostream &stream, const AbstractNode &node)
|
|||
stream << node.toString();
|
||||
return stream;
|
||||
}
|
||||
|
||||
QString AbstractNode::mk_cache_id() const
|
||||
{
|
||||
QString cache_id = dump();
|
||||
cache_id.remove(QRegExp("[a-zA-Z_][a-zA-Z_0-9]*:"));
|
||||
cache_id.remove(' ');
|
||||
cache_id.remove('\t');
|
||||
cache_id.remove('\n');
|
||||
return cache_id;
|
||||
}
|
||||
|
|
|
@ -51,10 +51,6 @@ public:
|
|||
|
||||
int idx; // Node index (unique per tree)
|
||||
|
||||
// FIXME: Remove these three with dump() method
|
||||
virtual QString mk_cache_id() const;
|
||||
QString dump() const;
|
||||
|
||||
// FIXME: Rewrite to visitor
|
||||
virtual class CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const;
|
||||
|
||||
|
|
|
@ -2,27 +2,36 @@
|
|||
#define NODECACHE_H_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "node.h"
|
||||
|
||||
template <class T>
|
||||
/*!
|
||||
Caches values per node based on the node.index().
|
||||
The node index guaranteed to be unique per node tree since the index is reset
|
||||
every time a new tree is generated.
|
||||
*/
|
||||
class NodeCache
|
||||
{
|
||||
public:
|
||||
NodeCache() { }
|
||||
virtual ~NodeCache() { }
|
||||
|
||||
const T & operator[](const AbstractNode &node) const {
|
||||
bool contains(const AbstractNode &node) const {
|
||||
return !(*this)[node].empty();
|
||||
}
|
||||
|
||||
const std::string & operator[](const AbstractNode &node) const {
|
||||
if (this->cache.size() > node.index()) return this->cache[node.index()];
|
||||
else return nullvalue;
|
||||
else return this->nullvalue;
|
||||
}
|
||||
|
||||
void insert(const class AbstractNode &node, const T & value) {
|
||||
void insert(const class AbstractNode &node, const std::string & value) {
|
||||
if (this->cache.size() <= node.index()) 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;
|
||||
if (this->cache.size() > node.index()) this->cache[node.index()] = std::string();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
|
@ -30,8 +39,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
std::vector<T> cache;
|
||||
T nullvalue;
|
||||
std::vector<std::string> cache;
|
||||
std::string nullvalue;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,21 +10,31 @@
|
|||
#include <iostream>
|
||||
#include <assert.h>
|
||||
|
||||
// For compatibility with old dump() output
|
||||
#define NODEDUMPER_COMPAT_MODE
|
||||
// For compatibility with old dump() output.
|
||||
// FIXME: Only needed for testing.
|
||||
//#define NODEDUMPER_COMPAT_MODE
|
||||
#ifdef NODEDUMPER_COMPAT_MODE
|
||||
#include "dxflinextrudenode.h"
|
||||
#include "dxfrotextrudenode.h"
|
||||
#include "projectionnode.h"
|
||||
#endif
|
||||
|
||||
NodeDumper *NodeDumper::global_dumper = NULL;
|
||||
/*!
|
||||
\class NodeDumper
|
||||
|
||||
bool NodeDumper::isCached(const AbstractNode &node)
|
||||
A visitor responsible for creating a text dump of a node tree. Also
|
||||
contains a cache for fast retrieval of the text representation of
|
||||
any node or subtree.
|
||||
*/
|
||||
|
||||
bool NodeDumper::isCached(const AbstractNode &node) const
|
||||
{
|
||||
return !this->cache[node].empty();
|
||||
}
|
||||
|
||||
/*!
|
||||
Indent or deindent. Must be called before we output any children.
|
||||
*/
|
||||
void NodeDumper::handleIndent(const State &state)
|
||||
{
|
||||
if (state.isPrefix()) {
|
||||
|
@ -36,6 +46,11 @@ void NodeDumper::handleIndent(const State &state)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Dumps the block of children contained in this->visitedchildren,
|
||||
including braces and indentation.
|
||||
All children are assumed to be cached already.
|
||||
*/
|
||||
string NodeDumper::dumpChildren(const AbstractNode &node)
|
||||
{
|
||||
std::stringstream dump;
|
||||
|
@ -45,7 +60,7 @@ string NodeDumper::dumpChildren(const AbstractNode &node)
|
|||
for (ChildList::const_iterator iter = this->visitedchildren[node.index()].begin();
|
||||
iter != this->visitedchildren[node.index()].end();
|
||||
iter++) {
|
||||
// FIXME: assert that cache contains **iter
|
||||
assert(isCached(**iter));
|
||||
dump << this->cache[**iter] << "\n";
|
||||
}
|
||||
|
||||
|
@ -65,14 +80,20 @@ string NodeDumper::dumpChildren(const AbstractNode &node)
|
|||
return dump.str();
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Called for each node in the tree.
|
||||
Will abort traversal if we're cached
|
||||
*/
|
||||
Response NodeDumper::visit(const State &state, const AbstractNode &node)
|
||||
{
|
||||
if (isCached(node)) return PruneTraversal;
|
||||
else handleIndent(state);
|
||||
|
||||
handleIndent(state);
|
||||
if (state.isPostfix()) {
|
||||
std::stringstream dump;
|
||||
dump << this->currindent << node;
|
||||
dump << this->currindent;
|
||||
if (this->idprefix) dump << "n" << node.index() << ":";
|
||||
dump << node;
|
||||
dump << dumpChildren(node);
|
||||
this->cache.insert(node, dump.str());
|
||||
}
|
||||
|
@ -81,13 +102,6 @@ Response NodeDumper::visit(const State &state, const AbstractNode &node)
|
|||
return ContinueTraversal;
|
||||
}
|
||||
|
||||
const string &NodeDumper::getDump() const
|
||||
{
|
||||
assert(this->root);
|
||||
// FIXME: assert that cache contains root
|
||||
return this->cache[*this->root];
|
||||
}
|
||||
|
||||
/*!
|
||||
Adds this given node to its parent's child list.
|
||||
Should be called for all nodes, including leaf nodes.
|
||||
|
|
|
@ -14,31 +14,27 @@ using std::list;
|
|||
class NodeDumper : public Visitor
|
||||
{
|
||||
public:
|
||||
NodeDumper() : root(NULL) {}
|
||||
/*! If idPrefix is true, we will output "n<id>:" in front of each node,
|
||||
which is useful for debugging. */
|
||||
NodeDumper(NodeCache &cache, bool idPrefix = false) :
|
||||
cache(cache), idprefix(idPrefix), root(NULL) { }
|
||||
virtual ~NodeDumper() {}
|
||||
|
||||
virtual Response visit(const State &state, const AbstractNode &node);
|
||||
|
||||
const string &getDump() const;
|
||||
const NodeCache<string> &getCache() const { return this->cache; }
|
||||
void clearCache() { this->cache.clear(); }
|
||||
|
||||
// FIXME: Questionable design...
|
||||
static NodeDumper *dumper() { return global_dumper; }
|
||||
static void setDumper(NodeDumper *d) { global_dumper = d; }
|
||||
private:
|
||||
void handleVisitedChildren(const State &state, const AbstractNode &node);
|
||||
bool isCached(const AbstractNode &node);
|
||||
bool isCached(const AbstractNode &node) const;
|
||||
void handleIndent(const State &state);
|
||||
string dumpChildren(const AbstractNode &node);
|
||||
|
||||
NodeCache &cache;
|
||||
bool idprefix;
|
||||
|
||||
string currindent;
|
||||
const AbstractNode *root;
|
||||
typedef list<const AbstractNode *> ChildList;
|
||||
map<int, ChildList> visitedchildren;
|
||||
NodeCache<string> cache;
|
||||
|
||||
static NodeDumper *global_dumper;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -241,7 +241,6 @@ int main(int argc, char **argv)
|
|||
NodeDumper dumper;
|
||||
CGALRenderer cgalrenderer(dumper.getCache());
|
||||
PolySetCGALRenderer psrenderer(cgalrenderer);
|
||||
NodeDumper::setDumper(&dumper);
|
||||
CGALRenderer::setRenderer(&cgalrenderer);
|
||||
PolySetRenderer::setRenderer(&psrenderer);
|
||||
|
||||
|
@ -297,9 +296,11 @@ int main(int argc, char **argv)
|
|||
|
||||
// FIXME: It shouldn't be necessary to dump manually, only when
|
||||
// the dumper and the renderer wants to share a cache
|
||||
Traverser trav(*NodeDumper::dumper(), *root_node, Traverser::PRE_AND_POSTFIX);
|
||||
trav.execute();
|
||||
CGAL_Nef_polyhedron root_N = CGALRenderer::renderer()->renderCGALMesh(*root_node);
|
||||
// FIXME: Rewrite to non-global dumper
|
||||
// Traverser trav(*NodeDumper::dumper(), *root_node, Traverser::PRE_AND_POSTFIX);
|
||||
// trav.execute();
|
||||
// CGAL_Nef_polyhedron root_N = CGALRenderer::renderer()->renderCGALMesh(*root_node);
|
||||
CGAL_Nef_polyhedron root_N;
|
||||
|
||||
QDir::setCurrent(original_path.absolutePath());
|
||||
|
||||
|
|
|
@ -33,15 +33,6 @@
|
|||
#include <Eigen/Core>
|
||||
#include <Eigen/LU>
|
||||
|
||||
QCache<QString,PolySet::ps_cache_entry> PolySet::ps_cache(100);
|
||||
|
||||
PolySet::ps_cache_entry::ps_cache_entry(PolySet *ps) :
|
||||
ps(ps), msg(print_messages_stack.last()) { }
|
||||
|
||||
PolySet::ps_cache_entry::~ps_cache_entry() {
|
||||
ps->unlink();
|
||||
}
|
||||
|
||||
PolySet::PolySet() : grid(GRID_FINE)
|
||||
{
|
||||
is2d = false;
|
||||
|
|
|
@ -62,15 +62,6 @@ public:
|
|||
CSGMODE_HIGHLIGHT_DIFFERENCE = 22
|
||||
};
|
||||
|
||||
struct ps_cache_entry {
|
||||
PolySet *ps;
|
||||
QString msg;
|
||||
ps_cache_entry(PolySet *ps);
|
||||
~ps_cache_entry();
|
||||
};
|
||||
|
||||
static QCache<QString,ps_cache_entry> ps_cache;
|
||||
|
||||
void render_surface(colormode_e colormode, csgmode_e csgmode, double *m, GLint *shaderinfo = NULL) const;
|
||||
void render_edges(colormode_e colormode, csgmode_e csgmode) const;
|
||||
|
||||
|
|
|
@ -529,7 +529,6 @@ sphere_next_r2:
|
|||
std::string PrimitiveNode::toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "n" << this->index() << ": ";
|
||||
|
||||
switch (this->type) {
|
||||
case CUBE:
|
||||
|
|
|
@ -85,11 +85,6 @@ AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstant
|
|||
return node;
|
||||
}
|
||||
|
||||
void register_builtin_projection()
|
||||
{
|
||||
builtin_modules["projection"] = new ProjectionModule();
|
||||
}
|
||||
|
||||
PolySet *ProjectionNode::render_polyset(render_mode_e mode) const
|
||||
{
|
||||
PolySetRenderer *renderer = PolySetRenderer::renderer();
|
||||
|
@ -100,16 +95,9 @@ PolySet *ProjectionNode::render_polyset(render_mode_e mode) const
|
|||
return ps;
|
||||
}
|
||||
|
||||
QString key = mk_cache_id();
|
||||
if (PolySet::ps_cache.contains(key)) {
|
||||
PRINT(PolySet::ps_cache[key]->msg);
|
||||
return PolySet::ps_cache[key]->ps->link();
|
||||
}
|
||||
|
||||
print_messages_push();
|
||||
|
||||
PolySet *ps = renderer->renderPolySet(*this, mode);
|
||||
PolySet::ps_cache.insert(key, new PolySet::ps_cache_entry(ps->link()));
|
||||
|
||||
print_messages_pop();
|
||||
|
||||
|
@ -119,10 +107,14 @@ PolySet *ProjectionNode::render_polyset(render_mode_e mode) const
|
|||
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();
|
||||
}
|
||||
|
||||
void register_builtin_projection()
|
||||
{
|
||||
builtin_modules["projection"] = new ProjectionModule();
|
||||
}
|
||||
|
|
|
@ -206,7 +206,6 @@ CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights
|
|||
std::string RenderNode::toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "n" << this->index() << ": ";
|
||||
|
||||
stream << "render(convexity = " << convexity << ")";
|
||||
|
||||
|
|
|
@ -206,7 +206,6 @@ PolySet *SurfaceNode::render_polyset(render_mode_e) const
|
|||
std::string SurfaceNode::toString() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "n" << this->index() << ": ";
|
||||
|
||||
stream << "surface(file = \"" << this->filename
|
||||
<< "\", center = " << (this->center ? "true" : "false") << ")";
|
||||
|
|
|
@ -266,7 +266,6 @@ CSGTerm *TransformNode::render_csg_term(double c[20], QVector<CSGTerm*> *highlig
|
|||
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] << "])";
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "CSGTextRenderer.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include "visitor.h"
|
||||
#include "state.h"
|
||||
#include "nodecache.h"
|
||||
#include "module.h" // FIXME: Temporarily for ModuleInstantiation
|
||||
|
||||
#include "csgnode.h"
|
||||
|
@ -15,23 +15,9 @@
|
|||
#include <assert.h>
|
||||
#include <QRegExp>
|
||||
|
||||
string CSGTextRenderer::getCSGString() const
|
||||
{
|
||||
assert(this->root);
|
||||
// FIXME: assert that cache contains root
|
||||
return this->cache[mk_cache_id(*this->root)];
|
||||
}
|
||||
|
||||
// CGAL_Nef_polyhedron CSGTextRenderer::getCGALMesh() const
|
||||
// {
|
||||
// assert(this->root);
|
||||
// // FIXME: assert that cache contains root
|
||||
// return this->cache[*this->root];
|
||||
// }
|
||||
|
||||
bool CSGTextRenderer::isCached(const AbstractNode &node)
|
||||
{
|
||||
return this->cache.contains(mk_cache_id(node));
|
||||
return this->cache.contains(this->tree.getString(node));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -118,7 +104,7 @@ void CSGTextRenderer::applyToChildren(const AbstractNode &node, CSGTextRenderer:
|
|||
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;
|
||||
if (first) {
|
||||
|
@ -132,8 +118,7 @@ void CSGTextRenderer::applyToChildren(const AbstractNode &node, CSGTextRenderer:
|
|||
}
|
||||
N += ")";
|
||||
}
|
||||
QString cacheid = mk_cache_id(node);
|
||||
this->cache.insert(cacheid, N);
|
||||
this->cache.insert(this->tree.getString(node), N);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -235,8 +220,7 @@ Response CSGTextRenderer::visit(const State &state, const AbstractPolyNode &node
|
|||
// }
|
||||
|
||||
string N = typeid(node).name();
|
||||
QString cacheid = mk_cache_id(node);
|
||||
this->cache.insert(cacheid, N);
|
||||
this->cache.insert(this->tree.getString(node), N);
|
||||
|
||||
// std::cout << "Insert: " << N << "\n";
|
||||
// std::cout << "Node: " << cacheid.toStdString() << "\n\n";
|
||||
|
@ -254,33 +238,28 @@ Response CSGTextRenderer::visit(const State &state, const AbstractPolyNode &node
|
|||
void CSGTextRenderer::addToParent(const State &state, const AbstractNode &node)
|
||||
{
|
||||
assert(state.isPostfix());
|
||||
QString cacheid = mk_cache_id(node);
|
||||
this->visitedchildren.erase(node.index());
|
||||
if (!state.parent()) {
|
||||
this->root = &node;
|
||||
}
|
||||
else {
|
||||
this->visitedchildren[state.parent()->index()].push_back(std::make_pair(&node, cacheid));
|
||||
if (state.parent()) {
|
||||
this->visitedchildren[state.parent()->index()].push_back(std::make_pair(&node, this->tree.getString(node)));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Create a cache id of the entire tree under this node. This cache id
|
||||
is a non-whitespace plaintext of the evaluated scad tree and is used
|
||||
for lookup in cgal_nef_cache.
|
||||
*/
|
||||
QString CSGTextRenderer::mk_cache_id(const AbstractNode &node) const
|
||||
|
||||
|
||||
static uint hash(const uchar *p, int n)
|
||||
{
|
||||
// FIXME: should we keep a cache of cache_id's to avoid recalculating this?
|
||||
// -> check how often we recalculate it.
|
||||
uint h = 0;
|
||||
uint g;
|
||||
|
||||
// FIXME: Get dump from dump cache
|
||||
// FIXME: assert that cache contains node
|
||||
QString cache_id = QString::fromStdString(this->dumpcache[node]);
|
||||
// Remove all node indices and whitespace
|
||||
cache_id.remove(QRegExp("[a-zA-Z_][a-zA-Z_0-9]*:"));
|
||||
cache_id.remove(' ');
|
||||
cache_id.remove('\t');
|
||||
cache_id.remove('\n');
|
||||
return cache_id;
|
||||
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());
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
#ifndef CSGTEXTRENDERER_H_
|
||||
#define CSGTEXTRENDERER_H_
|
||||
|
||||
#include <qglobal.h>
|
||||
#include <string>
|
||||
extern uint qHash(const std::string &);
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <QHash>
|
||||
#include "visitor.h"
|
||||
#include "nodecache.h"
|
||||
#include "Tree.h"
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
|
@ -15,8 +19,8 @@ using std::pair;
|
|||
class CSGTextRenderer : public Visitor
|
||||
{
|
||||
public:
|
||||
enum CsgOp {UNION, INTERSECTION, DIFFERENCE, MINKOWSKI};
|
||||
CSGTextRenderer(const NodeCache<string> &dumpcache) : root(NULL), dumpcache(dumpcache) {}
|
||||
CSGTextRenderer(QHash<string, string> &cache, const Tree &tree) :
|
||||
cache(cache), tree(tree) {}
|
||||
virtual ~CSGTextRenderer() {}
|
||||
|
||||
virtual Response visit(const State &state, const AbstractNode &node);
|
||||
|
@ -25,21 +29,19 @@ public:
|
|||
virtual Response visit(const State &state, const TransformNode &node);
|
||||
virtual Response visit(const State &state, const AbstractPolyNode &node);
|
||||
|
||||
string getCSGString() const;
|
||||
private:
|
||||
enum CsgOp {UNION, INTERSECTION, DIFFERENCE, MINKOWSKI};
|
||||
void addToParent(const State &state, const AbstractNode &node);
|
||||
bool isCached(const AbstractNode &node);
|
||||
QString mk_cache_id(const AbstractNode &node) const;
|
||||
void process(string &target, const string &src, CSGTextRenderer::CsgOp op);
|
||||
void applyToChildren(const AbstractNode &node, CSGTextRenderer::CsgOp op);
|
||||
|
||||
string currindent;
|
||||
const AbstractNode *root;
|
||||
typedef list<pair<const AbstractNode *, QString> > ChildList;
|
||||
typedef list<pair<const AbstractNode *, string> > ChildList;
|
||||
map<int, ChildList> visitedchildren;
|
||||
|
||||
QHash<QString, string> cache;
|
||||
const NodeCache<string> &dumpcache;
|
||||
QHash<string, string> &cache;
|
||||
const Tree &tree;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "nodedumper.h"
|
||||
#include "CGALRenderer.h"
|
||||
#include "PolySetCGALRenderer.h"
|
||||
#include "Tree.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFile>
|
||||
|
@ -61,6 +62,24 @@ void handle_dep(QString filename)
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: enforce some maximum cache size (old version had 100K vertices as limit)
|
||||
QHash<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());
|
||||
|
||||
CSGTextRenderer renderer(csgcache, cache);
|
||||
Traverser render(renderer, *root, Traverser::PRE_AND_POSTFIX);
|
||||
render.execute();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
|
@ -146,11 +165,12 @@ 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::string dumpstdstr = dumper.getDump() + "\n";
|
||||
std::cout << dumpstdstr << "\n";
|
||||
Tree tree;
|
||||
tree.setRoot(root_node);
|
||||
|
||||
cgalTree(tree);
|
||||
|
||||
std::cout << cache[tree.cache()[*root_node]] << "\n";
|
||||
|
||||
CGALRenderer cgalrenderer(dumper.getCache());
|
||||
PolySetCGALRenderer psrenderer(cgalrenderer);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
DEFINES += OPENSCAD_VERSION=test
|
||||
TEMPLATE = app
|
||||
|
||||
OBJECTS_DIR = objects
|
||||
MOC_DIR = objects
|
||||
UI_DIR = objects
|
||||
RCC_DIR = objects
|
||||
OBJECTS_DIR = cgal-objects
|
||||
MOC_DIR = cgal-objects
|
||||
UI_DIR = cgal-objects
|
||||
RCC_DIR = cgal-objects
|
||||
INCLUDEPATH += ../src
|
||||
|
||||
macx {
|
||||
|
@ -61,7 +61,8 @@ HEADERS += ../src/builtin.h \
|
|||
../src/importnode.h \
|
||||
../src/state.h \
|
||||
../src/PolySetRenderer.h \
|
||||
../src/PolySetCGALRenderer.h
|
||||
../src/PolySetCGALRenderer.h \
|
||||
../src/Tree.h
|
||||
|
||||
SOURCES += cgaltest.cc \
|
||||
../src/export.cc \
|
||||
|
@ -98,4 +99,5 @@ SOURCES += cgaltest.cc \
|
|||
../src/CGALRenderer.cc \
|
||||
../src/traverser.cc \
|
||||
../src/PolySetRenderer.cc \
|
||||
../src/PolySetCGALRenderer.cc
|
||||
../src/PolySetCGALRenderer.cc \
|
||||
../src/Tree.cc
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "CSGTextRenderer.h"
|
||||
#include "openscad.h"
|
||||
#include "node.h"
|
||||
#include "module.h"
|
||||
|
@ -30,14 +31,14 @@
|
|||
#include "value.h"
|
||||
#include "export.h"
|
||||
#include "builtin.h"
|
||||
#include "nodedumper.h"
|
||||
#include "CSGTextRenderer.h"
|
||||
#include "Tree.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QSet>
|
||||
#include <getopt.h>
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
|
||||
QString commandline_commands;
|
||||
|
@ -60,6 +61,17 @@ void handle_dep(QString filename)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
QHash<string, string> csgcache;
|
||||
void csgTree(Tree &tree)
|
||||
{
|
||||
assert(tree.root());
|
||||
|
||||
CSGTextRenderer renderer(csgcache, tree);
|
||||
Traverser render(renderer, *tree.root(), Traverser::PRE_AND_POSTFIX);
|
||||
render.execute();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
|
@ -145,17 +157,13 @@ int main(int argc, char **argv)
|
|||
AbstractNode::resetIndexCounter();
|
||||
root_node = root_module->evaluate(&root_ctx, &root_inst);
|
||||
|
||||
Tree tree;
|
||||
tree.setRoot(root_node);
|
||||
|
||||
NodeDumper dumper;
|
||||
Traverser trav(dumper, *root_node, Traverser::PRE_AND_POSTFIX);
|
||||
trav.execute();
|
||||
std::string dumpstdstr = dumper.getDump() + "\n";
|
||||
std::cout << dumpstdstr << "\n";
|
||||
csgTree(tree);
|
||||
std::cout << tree.getString(*root_node) << "\n";
|
||||
|
||||
CSGTextRenderer renderer(dumper.getCache());
|
||||
Traverser render(renderer, *root_node, Traverser::PRE_AND_POSTFIX);
|
||||
render.execute();
|
||||
std::cout << renderer.getCSGString() << "\n";
|
||||
std::cout << csgcache[tree.getString(*root_node)] << "\n";
|
||||
|
||||
destroy_builtin_functions();
|
||||
destroy_builtin_modules();
|
||||
|
|
|
@ -61,11 +61,12 @@ HEADERS += ../src/builtin.h \
|
|||
../src/csgnode.h \
|
||||
../src/visitor.h \
|
||||
../src/nodedumper.h \
|
||||
../src/CSGTextRenderer.h \
|
||||
../src/nodecache.h \
|
||||
../src/importnode.h \
|
||||
../src/state.h \
|
||||
../src/PolySetRenderer.h
|
||||
../src/PolySetRenderer.h \
|
||||
../src/Tree.h \
|
||||
CSGTextRenderer.h
|
||||
|
||||
SOURCES += csgtexttest.cc \
|
||||
../src/export.cc \
|
||||
|
@ -96,6 +97,7 @@ SOURCES += csgtexttest.cc \
|
|||
../src/printutils.cc \
|
||||
../src/progress.cc \
|
||||
../src/nodedumper.cc \
|
||||
../src/CSGTextRenderer.cc \
|
||||
../src/traverser.cc \
|
||||
../src/PolySetRenderer.cc
|
||||
../src/PolySetRenderer.cc \
|
||||
../src/Tree.cc \
|
||||
CSGTextRenderer.cc
|
||||
|
|
|
@ -31,12 +31,17 @@
|
|||
#include "export.h"
|
||||
#include "builtin.h"
|
||||
#include "nodedumper.h"
|
||||
#include "Tree.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QSet>
|
||||
#include <getopt.h>
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
|
||||
using std::string;
|
||||
|
||||
QString commandline_commands;
|
||||
const char *make_command = NULL;
|
||||
|
@ -144,23 +149,15 @@ int main(int argc, char **argv)
|
|||
root_node = root_module->evaluate(&root_ctx, &root_inst);
|
||||
|
||||
// Cache test
|
||||
QString dumpstr = root_node->dump();
|
||||
QString dumpstr_cached = root_node->dump();
|
||||
if (dumpstr != dumpstr_cached) rc = 1;
|
||||
QString teststr("test");
|
||||
Tree tree;
|
||||
tree.setRoot(root_node);
|
||||
|
||||
NodeDumper dumper;
|
||||
Traverser trav(dumper, *root_node, Traverser::PRE_AND_POSTFIX);
|
||||
trav.execute();
|
||||
std::string dumpstdstr = dumper.getDump() + "\n";
|
||||
trav.execute();
|
||||
std::string dumpstdstr_cached = dumper.getDump() + "\n";
|
||||
string dumpstdstr = tree.getString(*root_node);
|
||||
string dumpstdstr_cached = tree.getString(*root_node);
|
||||
if (dumpstdstr != dumpstdstr_cached) rc = 1;
|
||||
|
||||
if (QString::fromStdString(dumpstdstr) != dumpstr) {
|
||||
printf(dumpstr.toUtf8());
|
||||
printf(dumpstdstr.c_str());
|
||||
rc = 1;
|
||||
}
|
||||
std::cout << dumpstdstr << "\n";
|
||||
|
||||
destroy_builtin_functions();
|
||||
destroy_builtin_modules();
|
||||
|
|
|
@ -67,7 +67,8 @@ HEADERS += ../src/builtin.h \
|
|||
../src/nodecache.h \
|
||||
../src/importnode.h \
|
||||
../src/state.h \
|
||||
../src/PolySetRenderer.h
|
||||
../src/PolySetRenderer.h \
|
||||
../src/Tree.h
|
||||
|
||||
SOURCES += dumptest.cc \
|
||||
../src/export.cc \
|
||||
|
@ -99,4 +100,5 @@ SOURCES += dumptest.cc \
|
|||
../src/progress.cc \
|
||||
../src/nodedumper.cc \
|
||||
../src/traverser.cc \
|
||||
../src/PolySetRenderer.cc
|
||||
../src/PolySetRenderer.cc \
|
||||
../src/Tree.cc
|
||||
|
|
Loading…
Reference in New Issue