summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorkintel <kintel@b57f626f-c46c-0410-a088-ec61d464b74c>2010-02-09 13:48:09 (GMT)
committerkintel <kintel@b57f626f-c46c-0410-a088-ec61d464b74c>2010-02-09 13:48:09 (GMT)
commitc7b9a49c15f10ee76258f735ff66c1ed32e64c51 (patch)
treeebc9ef37dc44c0eed9c144441f5f763c381fdb08 /src
parent66ac9239767dd2151e61a11bc3fb9605c2a4d917 (diff)
Cleaned up progress handling, implemented cancel function. Needs more testing
git-svn-id: http://svn.clifford.at/openscad/trunk@420 b57f626f-c46c-0410-a088-ec61d464b74c
Diffstat (limited to 'src')
-rw-r--r--src/MainWindow.h1
-rw-r--r--src/dxflinextrude.cc37
-rw-r--r--src/dxfrotextrude.cc36
-rw-r--r--src/mainwin.cc350
-rw-r--r--src/node.cc65
-rw-r--r--src/node.h8
-rw-r--r--src/openscad.cc2
-rw-r--r--src/polyset.cc52
-rw-r--r--src/progress.cc28
-rw-r--r--src/progress.h16
-rw-r--r--src/projection.cc37
-rw-r--r--src/render.cc22
12 files changed, 309 insertions, 345 deletions
diff --git a/src/MainWindow.h b/src/MainWindow.h
index de738ca..216b7e2 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -68,6 +68,7 @@ private:
void load();
AbstractNode *find_root_tag(AbstractNode *n);
void compile(bool procevents);
+ void compileCSG(bool procevents);
bool maybeSave();
private slots:
diff --git a/src/dxflinextrude.cc b/src/dxflinextrude.cc
index f1aaf8c..ff270da 100644
--- a/src/dxflinextrude.cc
+++ b/src/dxflinextrude.cc
@@ -31,6 +31,7 @@
#include "dxfdata.h"
#include "dxftess.h"
#include "polyset.h"
+#include "progress.h"
#include "openscad.h" // get_fragments_from_r()
#include <sys/types.h>
@@ -209,17 +210,6 @@ static void add_slice(PolySet *ps, DxfData::Path *pt, double rot1, double rot2,
}
}
-static void report_func(const class AbstractNode*, void *vp, int mark)
-{
- QProgressDialog *pd = (QProgressDialog*)vp;
- int v = (int)((mark*100.0) / progress_report_count);
- pd->setValue(v < 100 ? v : 99);
- QString label;
- label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count);
- pd->setLabelText(label);
- QApplication::processEvents();
-}
-
PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e rm) const
{
QString key = mk_cache_id();
@@ -234,26 +224,9 @@ PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e rm) const
if (filename.isEmpty())
{
#ifdef ENABLE_CGAL
- QTime t;
- QProgressDialog *pd = NULL;
-
- if (rm == RENDER_OPENCSG)
- {
- PRINT_NOCACHE("Processing uncached linear_extrude outline...");
- QApplication::processEvents();
-
- t.start();
- pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100);
- pd->setValue(0);
- pd->setAutoClose(false);
- pd->show();
- QApplication::processEvents();
-
- progress_report_prep((AbstractNode*)this, report_func, pd);
- }
// Before extruding, union all (2D) children nodes
- // to a single DxfData, then tessealte this into a PolySet
+ // to a single DxfData, then tesselate this into a PolySet
CGAL_Nef_polyhedron N;
N.dim = 2;
foreach(AbstractNode * v, children) {
@@ -263,12 +236,6 @@ PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e rm) const
}
dxf = new DxfData(N);
- if (rm == RENDER_OPENCSG) {
- progress_report_fin();
- int s = t.elapsed() / 1000;
- PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
- delete pd;
- }
#else // ENABLE_CGAL
PRINT("WARNING: Found linear_extrude() statement without dxf file but compiled without CGAL support!");
dxf = new DxfData();
diff --git a/src/dxfrotextrude.cc b/src/dxfrotextrude.cc
index 21718ac..ba0d420 100644
--- a/src/dxfrotextrude.cc
+++ b/src/dxfrotextrude.cc
@@ -30,6 +30,7 @@
#include "builtin.h"
#include "polyset.h"
#include "dxfdata.h"
+#include "progress.h"
#include "openscad.h" // get_fragments_from_r()
#include <sys/types.h>
@@ -112,17 +113,6 @@ void register_builtin_dxf_rotate_extrude()
builtin_modules["rotate_extrude"] = new DxfRotateExtrudeModule();
}
-static void report_func(const class AbstractNode*, void *vp, int mark)
-{
- QProgressDialog *pd = (QProgressDialog*)vp;
- int v = (int)((mark*100.0) / progress_report_count);
- pd->setValue(v < 100 ? v : 99);
- QString label;
- label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count);
- pd->setLabelText(label);
- QApplication::processEvents();
-}
-
PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e rm) const
{
QString key = mk_cache_id();
@@ -137,24 +127,6 @@ PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e rm) const
if (filename.isEmpty())
{
#ifdef ENABLE_CGAL
- QTime t;
- QProgressDialog *pd;
-
- if (rm == RENDER_OPENCSG)
- {
- PRINT_NOCACHE("Processing uncached rotate_extrude outline...");
- QApplication::processEvents();
-
- t.start();
- pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100);
- pd->setValue(0);
- pd->setAutoClose(false);
- pd->show();
- QApplication::processEvents();
-
- progress_report_prep((AbstractNode*)this, report_func, pd);
- }
-
CGAL_Nef_polyhedron N;
N.dim = 2;
foreach(AbstractNode * v, children) {
@@ -164,12 +136,6 @@ PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e rm) const
}
dxf = new DxfData(N);
- if (rm == RENDER_OPENCSG) {
- progress_report_fin();
- int s = t.elapsed() / 1000;
- PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
- delete pd;
- }
#else // ENABLE_CGAL
PRINT("WARNING: Found rotate_extrude() statement without dxf file but compiled without CGAL support!");
dxf = new DxfData();
diff --git a/src/mainwin.cc b/src/mainwin.cc
index e9bbdaa..02ea445 100644
--- a/src/mainwin.cc
+++ b/src/mainwin.cc
@@ -37,6 +37,7 @@
#include "export.h"
#include "builtin.h"
#include "dxftess.h"
+#include "progress.h"
#include <QMenu>
#include <QTime>
@@ -45,6 +46,7 @@
#include <QFileDialog>
#include <QApplication>
#include <QProgressDialog>
+#include <QProgressBar>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
@@ -336,6 +338,20 @@ MainWindow::~MainWindow()
#endif
}
+typedef QPair<QProgressBar*, QProgressDialog*> ProgressData;
+
+static void report_func(const class AbstractNode*, void *vp, int mark)
+{
+ ProgressData *progpair = static_cast<ProgressData*>(vp);
+ int v = (int)((mark*100.0) / progress_report_count);
+ progpair->first->setValue(v < 100 ? v : 99);
+ QString label;
+ label.sprintf("Rendering Polygon Mesh (%d/%d)", mark, progress_report_count);
+ progpair->second->setLabelText(label);
+ QApplication::processEvents();
+ if (progpair->second->wasCanceled()) throw ProgressCancelException();
+}
+
/*!
Requests to open a file from an external event, e.g. by double-clicking a filename.
*/
@@ -458,6 +474,9 @@ AbstractNode *MainWindow::find_root_tag(AbstractNode *n)
return NULL;
}
+/*!
+ Parse and evaluate the design -> this->root_node
+*/
void MainWindow::compile(bool procevents)
{
PRINT("Parsing design (AST generation)...");
@@ -554,7 +573,7 @@ void MainWindow::compile(bool procevents)
if (procevents)
QApplication::processEvents();
- AbstractNode::idx_counter = 1;
+ AbstractNode::resetIndexCounter();
root_inst = ModuleInstantiation();
absolute_root_node = root_module->evaluate(&root_ctx, &root_inst);
@@ -567,6 +586,40 @@ void MainWindow::compile(bool procevents)
}
root_node->dump("");
+ if (1) {
+ PRINT("Compilation finished.");
+ if (procevents)
+ QApplication::processEvents();
+ } else {
+fail:
+ if (parser_error_pos < 0) {
+ PRINT("ERROR: Compilation failed! (no top level object found)");
+ } else {
+ int line = 1;
+ QByteArray pb = last_compiled_doc.toAscii();
+ char *p = pb.data();
+ for (int i = 0; i < parser_error_pos; i++) {
+ if (p[i] == '\n')
+ line++;
+ if (p[i] == 0) {
+ line = -1;
+ break;
+ }
+ }
+ PRINTF("ERROR: Compilation failed! (parser error in line %d)", line);
+ }
+ if (procevents)
+ QApplication::processEvents();
+ }
+}
+
+/*!
+ Generates CSG tree for OpenCSG evaluation.
+ Assumes that the design has been parsed and evaluated
+*/
+void MainWindow::compileCSG(bool procevents)
+{
+ assert(this->root_node);
PRINT("Compiling design (CSG Products generation)...");
if (procevents)
QApplication::processEvents();
@@ -579,99 +632,102 @@ void MainWindow::compile(bool procevents)
m[i] = -1;
// Main CSG evaluation
- root_raw_term = root_node->render_csg_term(m, &highlight_terms, &background_terms);
-
- if (!root_raw_term)
- goto fail;
-
- PRINT("Compiling design (CSG Products normalization)...");
- if (procevents)
- QApplication::processEvents();
+ QTime t;
+ t.start();
- root_norm_term = root_raw_term->link();
+ QProgressDialog *pd = new QProgressDialog("Rendering CSG products...", "Cancel", 0, 100);
+ QProgressBar *bar = new QProgressBar(pd);
+ bar->setRange(0, 100);
+ bar->setValue(0);
+ pd->setBar(bar);
+ pd->setAutoClose(false);
+ pd->show();
+ ProgressData progpair(bar, pd);
+ QApplication::processEvents();
- // CSG normalization
- while (1) {
- CSGTerm *n = root_norm_term->normalize();
- root_norm_term->unlink();
- if (root_norm_term == n)
- break;
- root_norm_term = n;
+ progress_report_prep(root_node, report_func, &progpair);
+ try {
+ root_raw_term = root_node->render_csg_term(m, &highlight_terms, &background_terms);
+ if (!root_raw_term) {
+ PRINT("ERROR: CSG generation failed! (no top level object found)");
+ if (procevents)
+ QApplication::processEvents();
+ }
}
-
- if (!root_norm_term)
- goto fail;
-
- root_chain = new CSGChain();
- root_chain->import(root_norm_term);
-
- if (root_chain->polysets.size() > 1000) {
- PRINTF("WARNING: Normalized tree has %d elements!", root_chain->polysets.size());
- PRINTF("WARNING: OpenCSG rendering has been disabled.");
- } else {
- enableOpenCSG = true;
+ catch (ProgressCancelException e) {
}
+ progress_report_fin();
+ delete pd;
- if (highlight_terms.size() > 0)
- {
- PRINTF("Compiling highlights (%d CSG Trees)...", highlight_terms.size());
+ if (root_raw_term) {
+ PRINT("Compiling design (CSG Products normalization)...");
if (procevents)
QApplication::processEvents();
-
- highlights_chain = new CSGChain();
- for (int i = 0; i < highlight_terms.size(); i++) {
- while (1) {
- CSGTerm *n = highlight_terms[i]->normalize();
- highlight_terms[i]->unlink();
- if (highlight_terms[i] == n)
- break;
- highlight_terms[i] = n;
- }
- highlights_chain->import(highlight_terms[i]);
+
+ root_norm_term = root_raw_term->link();
+
+ // CSG normalization
+ while (1) {
+ CSGTerm *n = root_norm_term->normalize();
+ root_norm_term->unlink();
+ if (root_norm_term == n)
+ break;
+ root_norm_term = n;
}
- }
-
- if (background_terms.size() > 0)
- {
- PRINTF("Compiling background (%d CSG Trees)...", background_terms.size());
- if (procevents)
- QApplication::processEvents();
+
+ assert(root_norm_term);
- background_chain = new CSGChain();
- for (int i = 0; i < background_terms.size(); i++) {
- while (1) {
- CSGTerm *n = background_terms[i]->normalize();
- background_terms[i]->unlink();
- if (background_terms[i] == n)
- break;
- background_terms[i] = n;
+ root_chain = new CSGChain();
+ root_chain->import(root_norm_term);
+
+ if (root_chain->polysets.size() > 1000) {
+ PRINTF("WARNING: Normalized tree has %d elements!", root_chain->polysets.size());
+ PRINTF("WARNING: OpenCSG rendering has been disabled.");
+ } else {
+ enableOpenCSG = true;
+ }
+
+ if (highlight_terms.size() > 0)
+ {
+ PRINTF("Compiling highlights (%d CSG Trees)...", highlight_terms.size());
+ if (procevents)
+ QApplication::processEvents();
+
+ highlights_chain = new CSGChain();
+ for (int i = 0; i < highlight_terms.size(); i++) {
+ while (1) {
+ CSGTerm *n = highlight_terms[i]->normalize();
+ highlight_terms[i]->unlink();
+ if (highlight_terms[i] == n)
+ break;
+ highlight_terms[i] = n;
+ }
+ highlights_chain->import(highlight_terms[i]);
}
- background_chain->import(background_terms[i]);
}
- }
-
- if (1) {
- PRINT("Compilation finished.");
- if (procevents)
- QApplication::processEvents();
- } else {
-fail:
- if (parser_error_pos < 0) {
- PRINT("ERROR: Compilation failed! (no top level object found)");
- } else {
- int line = 1;
- QByteArray pb = last_compiled_doc.toAscii();
- char *p = pb.data();
- for (int i = 0; i < parser_error_pos; i++) {
- if (p[i] == '\n')
- line++;
- if (p[i] == 0) {
- line = -1;
- break;
+
+ if (background_terms.size() > 0)
+ {
+ PRINTF("Compiling background (%d CSG Trees)...", background_terms.size());
+ if (procevents)
+ QApplication::processEvents();
+
+ background_chain = new CSGChain();
+ for (int i = 0; i < background_terms.size(); i++) {
+ while (1) {
+ CSGTerm *n = background_terms[i]->normalize();
+ background_terms[i]->unlink();
+ if (background_terms[i] == n)
+ break;
+ background_terms[i] = n;
}
+ background_chain->import(background_terms[i]);
}
- PRINTF("ERROR: Compilation failed! (parser error in line %d)", line);
}
+
+ PRINT("CSG generation finished.");
+ int s = t.elapsed() / 1000;
+ PRINTF("Total rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
if (procevents)
QApplication::processEvents();
}
@@ -909,6 +965,7 @@ void MainWindow::actionReloadCompile()
current_win = this;
compile(true);
+ if (this->root_node) compileCSG(true);
#ifdef ENABLE_OPENCSG
if (!(viewActionOpenCSG->isVisible() && viewActionOpenCSG->isChecked()) &&
@@ -929,6 +986,7 @@ void MainWindow::actionCompile()
console->clear();
compile(!viewActionAnimate->isChecked());
+ if (this->root_node) compileCSG(!viewActionAnimate->isChecked());
// Go to non-CGAL view mode
if (!viewActionOpenCSG->isChecked() && !viewActionThrownTogether->isChecked()) {
@@ -952,17 +1010,6 @@ void MainWindow::actionCompile()
#ifdef ENABLE_CGAL
-static void report_func(const class AbstractNode*, void *vp, int mark)
-{
- QProgressDialog *pd = (QProgressDialog*)vp;
- int v = (int)((mark*100.0) / progress_report_count);
- pd->setValue(v < 100 ? v : 99);
- QString label;
- label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count);
- pd->setLabelText(label);
- QApplication::processEvents();
-}
-
void MainWindow::actionRenderCGAL()
{
current_win = this;
@@ -985,71 +1032,84 @@ void MainWindow::actionRenderCGAL()
QTime t;
t.start();
- QProgressDialog *pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100);
- pd->setValue(0);
+ QProgressDialog *pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", "Cancel", 0, 100);
+ QProgressBar *bar = new QProgressBar(pd);
+ bar->setRange(0, 100);
+ bar->setValue(0);
+ pd->setBar(bar);
pd->setAutoClose(false);
pd->show();
+// this->statusBar()->addPermanentWidget(bar);
+ ProgressData progpair(bar, pd);
QApplication::processEvents();
- progress_report_prep(root_node, report_func, pd);
- this->root_N = new CGAL_Nef_polyhedron(root_node->render_cgal_nef_polyhedron());
+ progress_report_prep(root_node, report_func, &progpair);
+ try {
+ this->root_N = new CGAL_Nef_polyhedron(root_node->render_cgal_nef_polyhedron());
+ }
+ catch (ProgressCancelException e) {
+ }
progress_report_fin();
+// this->statusBar()->removeWidget(bar);
- PRINTF("Number of vertices currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.totalCost());
- PRINTF("Number of objects currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.size());
- QApplication::processEvents();
-
- if (this->root_N->dim == 2) {
- PRINTF(" Top level object is a 2D object:");
- QApplication::processEvents();
- PRINTF(" Empty: %6s", this->root_N->p2.is_empty() ? "yes" : "no");
- QApplication::processEvents();
- PRINTF(" Plane: %6s", this->root_N->p2.is_plane() ? "yes" : "no");
- QApplication::processEvents();
- PRINTF(" Vertices: %6d", (int)this->root_N->p2.explorer().number_of_vertices());
- QApplication::processEvents();
- PRINTF(" Halfedges: %6d", (int)this->root_N->p2.explorer().number_of_halfedges());
- QApplication::processEvents();
- PRINTF(" Edges: %6d", (int)this->root_N->p2.explorer().number_of_edges());
- QApplication::processEvents();
- PRINTF(" Faces: %6d", (int)this->root_N->p2.explorer().number_of_faces());
- QApplication::processEvents();
- PRINTF(" FaceCycles: %6d", (int)this->root_N->p2.explorer().number_of_face_cycles());
- QApplication::processEvents();
- PRINTF(" ConnComp: %6d", (int)this->root_N->p2.explorer().number_of_connected_components());
+ if (this->root_N)
+ {
+ PRINTF("Number of vertices currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.totalCost());
+ PRINTF("Number of objects currently in CGAL cache: %d", AbstractNode::cgal_nef_cache.size());
QApplication::processEvents();
- }
- if (this->root_N->dim == 3) {
- PRINTF(" Top level object is a 3D object:");
- PRINTF(" Simple: %6s", this->root_N->p3.is_simple() ? "yes" : "no");
- QApplication::processEvents();
- PRINTF(" Valid: %6s", this->root_N->p3.is_valid() ? "yes" : "no");
- QApplication::processEvents();
- PRINTF(" Vertices: %6d", (int)this->root_N->p3.number_of_vertices());
- QApplication::processEvents();
- PRINTF(" Halfedges: %6d", (int)this->root_N->p3.number_of_halfedges());
- QApplication::processEvents();
- PRINTF(" Edges: %6d", (int)this->root_N->p3.number_of_edges());
- QApplication::processEvents();
- PRINTF(" Halffacets: %6d", (int)this->root_N->p3.number_of_halffacets());
- QApplication::processEvents();
- PRINTF(" Facets: %6d", (int)this->root_N->p3.number_of_facets());
- QApplication::processEvents();
- PRINTF(" Volumes: %6d", (int)this->root_N->p3.number_of_volumes());
- QApplication::processEvents();
- }
+ if (this->root_N->dim == 2) {
+ PRINTF(" Top level object is a 2D object:");
+ QApplication::processEvents();
+ PRINTF(" Empty: %6s", this->root_N->p2.is_empty() ? "yes" : "no");
+ QApplication::processEvents();
+ PRINTF(" Plane: %6s", this->root_N->p2.is_plane() ? "yes" : "no");
+ QApplication::processEvents();
+ PRINTF(" Vertices: %6d", (int)this->root_N->p2.explorer().number_of_vertices());
+ QApplication::processEvents();
+ PRINTF(" Halfedges: %6d", (int)this->root_N->p2.explorer().number_of_halfedges());
+ QApplication::processEvents();
+ PRINTF(" Edges: %6d", (int)this->root_N->p2.explorer().number_of_edges());
+ QApplication::processEvents();
+ PRINTF(" Faces: %6d", (int)this->root_N->p2.explorer().number_of_faces());
+ QApplication::processEvents();
+ PRINTF(" FaceCycles: %6d", (int)this->root_N->p2.explorer().number_of_face_cycles());
+ QApplication::processEvents();
+ PRINTF(" ConnComp: %6d", (int)this->root_N->p2.explorer().number_of_connected_components());
+ QApplication::processEvents();
+ }
+
+ if (this->root_N->dim == 3) {
+ PRINTF(" Top level object is a 3D object:");
+ PRINTF(" Simple: %6s", this->root_N->p3.is_simple() ? "yes" : "no");
+ QApplication::processEvents();
+ PRINTF(" Valid: %6s", this->root_N->p3.is_valid() ? "yes" : "no");
+ QApplication::processEvents();
+ PRINTF(" Vertices: %6d", (int)this->root_N->p3.number_of_vertices());
+ QApplication::processEvents();
+ PRINTF(" Halfedges: %6d", (int)this->root_N->p3.number_of_halfedges());
+ QApplication::processEvents();
+ PRINTF(" Edges: %6d", (int)this->root_N->p3.number_of_edges());
+ QApplication::processEvents();
+ PRINTF(" Halffacets: %6d", (int)this->root_N->p3.number_of_halffacets());
+ QApplication::processEvents();
+ PRINTF(" Facets: %6d", (int)this->root_N->p3.number_of_facets());
+ QApplication::processEvents();
+ PRINTF(" Volumes: %6d", (int)this->root_N->p3.number_of_volumes());
+ QApplication::processEvents();
+ }
- int s = t.elapsed() / 1000;
- PRINTF("Total rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
+ int s = t.elapsed() / 1000;
+ PRINTF("Total rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
- if (!viewActionCGALSurfaces->isChecked() && !viewActionCGALGrid->isChecked()) {
- viewModeCGALSurface();
- } else {
- screen->updateGL();
- }
+ if (!viewActionCGALSurfaces->isChecked() && !viewActionCGALGrid->isChecked()) {
+ viewModeCGALSurface();
+ } else {
+ screen->updateGL();
+ }
- PRINT("Rendering finished.");
+ PRINT("Rendering finished.");
+ }
delete pd;
current_win = NULL;
diff --git a/src/node.cc b/src/node.cc
index e4d1477..3121549 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -27,6 +27,8 @@
#include "node.h"
#include "module.h"
#include "csgterm.h"
+#include "progress.h"
+#include "polyset.h"
#include <QRegExp>
int AbstractNode::idx_counter;
@@ -55,7 +57,7 @@ QString AbstractNode::mk_cache_id() const
#ifdef ENABLE_CGAL
-AbstractNode::cgal_nef_cache_entry::cgal_nef_cache_entry(CGAL_Nef_polyhedron N) :
+AbstractNode::cgal_nef_cache_entry::cgal_nef_cache_entry(const CGAL_Nef_polyhedron &N) :
N(N), msg(print_messages_stack.last()) { };
QCache<QString, AbstractNode::cgal_nef_cache_entry> AbstractNode::cgal_nef_cache(100000);
@@ -167,35 +169,64 @@ QString AbstractIntersectionNode::dump(QString indent) const
return dump_cache;
}
-int progress_report_count;
-void (*progress_report_f)(const class AbstractNode*, void*, int);
-void *progress_report_vp;
-
void AbstractNode::progress_prepare()
{
foreach (AbstractNode *v, children)
v->progress_prepare();
- progress_mark = ++progress_report_count;
+ this->progress_mark = ++progress_report_count;
}
void AbstractNode::progress_report() const
{
- if (progress_report_f)
- progress_report_f(this, progress_report_vp, progress_mark);
+ progress_update(this, this->progress_mark);
+}
+
+#ifdef ENABLE_CGAL
+
+CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const
+{
+ QString cache_id = mk_cache_id();
+ if (cgal_nef_cache.contains(cache_id)) {
+ progress_report();
+ PRINT(cgal_nef_cache[cache_id]->msg);
+ return cgal_nef_cache[cache_id]->N;
+ }
+
+ print_messages_push();
+
+ PolySet *ps = render_polyset(RENDER_CGAL);
+ try {
+ 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();
+
+ ps->unlink();
+ return N;
+ }
+ catch (...) { // Don't leak the PolySet on ProgressCancelException
+ ps->unlink();
+ throw;
+ }
}
-void progress_report_prep(AbstractNode *root, void (*f)(const class AbstractNode *node, void *vp, int mark), void *vp)
+#endif /* ENABLE_CGAL */
+
+CSGTerm *AbstractPolyNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
{
- progress_report_count = 0;
- progress_report_f = f;
- progress_report_vp = vp;
- root->progress_prepare();
+ PolySet *ps = render_polyset(RENDER_OPENCSG);
+ return render_csg_term_from_ps(m, highlights, background, ps, modinst, idx);
}
-void progress_report_fin()
+CSGTerm *AbstractPolyNode::render_csg_term_from_ps(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, PolySet *ps, const ModuleInstantiation *modinst, int idx)
{
- progress_report_count = 0;
- progress_report_f = NULL;
- progress_report_vp = NULL;
+ CSGTerm *t = new CSGTerm(ps, m, QString("n%1").arg(idx));
+ if (modinst->tag_highlight && highlights)
+ highlights->append(t->link());
+ if (modinst->tag_background && background) {
+ background->append(t);
+ return NULL;
+ }
+ return t;
}
diff --git a/src/node.h b/src/node.h
index 9121a3b..969c80e 100644
--- a/src/node.h
+++ b/src/node.h
@@ -17,7 +17,10 @@ void progress_report_fin();
class AbstractNode
{
+ static int idx_counter; // Node instantiation index
public:
+ static void resetIndexCounter() { idx_counter = 1; }
+
QVector<AbstractNode*> children;
const class ModuleInstantiation *modinst;
@@ -26,7 +29,6 @@ public:
void progress_report() const;
int idx;
- static int idx_counter;
QString dump_cache;
AbstractNode(const ModuleInstantiation *mi);
@@ -36,7 +38,7 @@ public:
struct cgal_nef_cache_entry {
CGAL_Nef_polyhedron N;
QString msg;
- cgal_nef_cache_entry(CGAL_Nef_polyhedron N);
+ cgal_nef_cache_entry(const CGAL_Nef_polyhedron &N);
};
static QCache<QString, cgal_nef_cache_entry> cgal_nef_cache;
virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
@@ -64,7 +66,7 @@ public:
RENDER_OPENCSG
};
AbstractPolyNode(const ModuleInstantiation *mi) : AbstractNode(mi) { };
- virtual class PolySet *render_polyset(render_mode_e mode) const;
+ virtual class PolySet *render_polyset(render_mode_e mode) const = 0;
#ifdef ENABLE_CGAL
virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
#endif
diff --git a/src/openscad.cc b/src/openscad.cc
index 44c4e3c..f2e1afc 100644
--- a/src/openscad.cc
+++ b/src/openscad.cc
@@ -227,7 +227,7 @@ int main(int argc, char **argv)
QString original_path = QDir::currentPath();
QDir::setCurrent(fileInfo.absolutePath());
- AbstractNode::idx_counter = 1;
+ AbstractNode::resetIndexCounter();
root_node = root_module->evaluate(&root_ctx, &root_inst);
CGAL_Nef_polyhedron *root_N;
diff --git a/src/polyset.cc b/src/polyset.cc
index 0285b95..8eccf37 100644
--- a/src/polyset.cc
+++ b/src/polyset.cc
@@ -24,9 +24,6 @@
*/
#include "polyset.h"
-#include "node.h"
-#include "module.h"
-#include "csgterm.h"
#include "printutils.h"
#include "Preferences.h"
@@ -666,52 +663,3 @@ CGAL_Nef_polyhedron PolySet::render_cgal_nef_polyhedron() const
#endif /* ENABLE_CGAL */
-PolySet *AbstractPolyNode::render_polyset(render_mode_e) const
-{
- return NULL;
-}
-
-#ifdef ENABLE_CGAL
-
-CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const
-{
- QString cache_id = mk_cache_id();
- if (cgal_nef_cache.contains(cache_id)) {
- progress_report();
- PRINT(cgal_nef_cache[cache_id]->msg);
- return cgal_nef_cache[cache_id]->N;
- }
-
- print_messages_push();
-
- PolySet *ps = render_polyset(RENDER_CGAL);
- 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();
-
- ps->unlink();
- return N;
-}
-
-#endif /* ENABLE_CGAL */
-
-CSGTerm *AbstractPolyNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
-{
- PolySet *ps = render_polyset(RENDER_OPENCSG);
- return render_csg_term_from_ps(m, highlights, background, ps, modinst, idx);
-}
-
-CSGTerm *AbstractPolyNode::render_csg_term_from_ps(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, PolySet *ps, const ModuleInstantiation *modinst, int idx)
-{
- CSGTerm *t = new CSGTerm(ps, m, QString("n%1").arg(idx));
- if (modinst->tag_highlight && highlights)
- highlights->append(t->link());
- if (modinst->tag_background && background) {
- background->append(t);
- return NULL;
- }
- return t;
-}
-
diff --git a/src/progress.cc b/src/progress.cc
new file mode 100644
index 0000000..300147d
--- /dev/null
+++ b/src/progress.cc
@@ -0,0 +1,28 @@
+#include "progress.h"
+#include "node.h"
+
+int progress_report_count;
+void (*progress_report_f)(const class AbstractNode*, void*, int);
+void *progress_report_userdata;
+
+void progress_report_prep(AbstractNode *root, void (*f)(const class AbstractNode *node, void *userdata, int mark), void *userdata)
+{
+ progress_report_count = 0;
+ progress_report_f = f;
+ progress_report_userdata = userdata;
+ root->progress_prepare();
+}
+
+void progress_report_fin()
+{
+ progress_report_count = 0;
+ progress_report_f = NULL;
+ progress_report_userdata = NULL;
+}
+
+void progress_update(const AbstractNode *node, int mark)
+{
+ if (progress_report_f)
+ progress_report_f(node, progress_report_userdata, mark);
+}
+
diff --git a/src/progress.h b/src/progress.h
new file mode 100644
index 0000000..33c340c
--- /dev/null
+++ b/src/progress.h
@@ -0,0 +1,16 @@
+#ifndef PROGRESS_H_
+#define PROGRESS_H_
+
+// Reset to 0 in _prep() and increased for each Node instance in progress_prepare()
+extern int progress_report_count;
+
+extern void (*progress_report_f)(const class AbstractNode*, void*, int);
+extern void *progress_report_userdata;
+
+void progress_report_prep(AbstractNode *root, void (*f)(const class AbstractNode *node, void *userdata, int mark), void *userdata);
+void progress_report_fin();
+void progress_update(const AbstractNode *node, int mark);
+
+class ProgressCancelException { };
+
+#endif
diff --git a/src/projection.cc b/src/projection.cc
index 75aaf44..fa45ff3 100644
--- a/src/projection.cc
+++ b/src/projection.cc
@@ -32,6 +32,7 @@
#include "dxftess.h"
#include "polyset.h"
#include "export.h"
+#include "progress.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -95,17 +96,6 @@ void register_builtin_projection()
#ifdef ENABLE_CGAL
-static void report_func(const class AbstractNode*, void *vp, int mark)
-{
- QProgressDialog *pd = (QProgressDialog*)vp;
- int v = (int)((mark*100.0) / progress_report_count);
- pd->setValue(v < 100 ? v : 99);
- QString label;
- label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count);
- pd->setLabelText(label);
- QApplication::processEvents();
-}
-
PolySet *ProjectionNode::render_polyset(render_mode_e rm) const
{
QString key = mk_cache_id();
@@ -116,24 +106,6 @@ PolySet *ProjectionNode::render_polyset(render_mode_e rm) const
print_messages_push();
- QTime t;
- QProgressDialog *pd = NULL;
-
- if (rm == RENDER_OPENCSG)
- {
- PRINT_NOCACHE("Processing uncached projection body...");
- QApplication::processEvents();
-
- t.start();
- pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100);
- pd->setValue(0);
- pd->setAutoClose(false);
- pd->show();
- QApplication::processEvents();
-
- progress_report_prep((AbstractNode*)this, report_func, pd);
- }
-
CGAL_Nef_polyhedron N;
N.dim = 3;
foreach(AbstractNode *v, this->children) {
@@ -142,13 +114,6 @@ PolySet *ProjectionNode::render_polyset(render_mode_e rm) const
N.p3 += v->render_cgal_nef_polyhedron().p3;
}
- if (rm == RENDER_OPENCSG) {
- progress_report_fin();
- int s = t.elapsed() / 1000;
- PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
- delete pd;
- }
-
PolySet *ps = new PolySet();
ps->convexity = this->convexity;
ps->is2d = true;
diff --git a/src/render.cc b/src/render.cc
index 27a9aa5..1081f5b 100644
--- a/src/render.cc
+++ b/src/render.cc
@@ -32,6 +32,7 @@
#include "csgterm.h"
#include "builtin.h"
#include "printutils.h"
+#include "progress.h"
#ifdef ENABLE_CGAL
# include "cgal.h"
#endif
@@ -124,17 +125,6 @@ CGAL_Nef_polyhedron RenderNode::render_cgal_nef_polyhedron() const
return N;
}
-static void report_func(const class AbstractNode*, void *vp, int mark)
-{
- QProgressDialog *pd = (QProgressDialog*)vp;
- int v = (int)((mark*100.0) / progress_report_count);
- pd->setValue(v < 100 ? v : 99);
- QString label;
- label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count);
- pd->setLabelText(label);
- QApplication::processEvents();
-}
-
CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
{
QString key = mk_cache_id();
@@ -162,20 +152,10 @@ CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights
QTime t;
t.start();
- QProgressDialog *pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100);
- pd->setValue(0);
- pd->setAutoClose(false);
- pd->show();
- QApplication::processEvents();
-
- progress_report_prep((AbstractNode*)this, report_func, pd);
N = this->render_cgal_nef_polyhedron();
- progress_report_fin();
int s = t.elapsed() / 1000;
PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
-
- delete pd;
}
PolySet *ps = NULL;
contact: Jan Huwald // Impressum