Use GeometryEvaluator instead of CGALEvaluator. A bunch of refactoring and fixes as a result of that. Renamed GUI menu items to reflect preview vs. render

customizer
Marius Kintel 2013-12-22 01:43:08 -05:00
parent 4ac6d079b2
commit dc9429acac
37 changed files with 356 additions and 321 deletions

View File

@ -379,7 +379,6 @@ cgal {
HEADERS += src/cgal.h \
src/cgalfwd.h \
src/cgalutils.h \
src/CGALEvaluator.h \
src/CGALCache.h \
src/CGALRenderer.h \
src/CGAL_Nef_polyhedron.h \
@ -388,7 +387,6 @@ HEADERS += src/cgal.h \
src/Polygon2d-CGAL.h
SOURCES += src/cgalutils.cc \
src/CGALEvaluator.cc \
src/CGALCache.cc \
src/CGALRenderer.cc \
src/CGAL_Nef_polyhedron.cc \

View File

@ -15,7 +15,7 @@ OSErr eventHandler(const AppleEvent *, AppleEvent *, SRefCon )
if (mainwin) break;
}
if (mainwin) {
mainwin->actionReloadRenderCSG();
mainwin->actionReloadRenderPreview();
}
return noErr;
}

View File

@ -41,21 +41,21 @@
//#include "Preferences.h"
CGALRenderer::CGALRenderer(const CGAL_Nef_polyhedron &root) : root(root)
CGALRenderer::CGALRenderer(shared_ptr<const CGAL_Nef_polyhedron> root) : root(root)
{
if (this->root.isNull()) {
if (this->root->isNull()) {
this->polyhedron = NULL;
this->polyset = NULL;
}
else if (root.getDimension() == 2) {
DxfData *dd = root.convertToDxfData();
else if (root->getDimension() == 2) {
DxfData *dd = root->convertToDxfData();
this->polyhedron = NULL;
this->polyset = new PolySet();
this->polyset->is2d = true;
dxf_tesselate(this->polyset, *dd, 0, Vector2d(1,1), true, false, 0);
delete dd;
}
else if (root.getDimension() == 3) {
else if (root->getDimension() == 3) {
this->polyset = NULL;
this->polyhedron = new Polyhedron();
// FIXME: Make independent of Preferences
@ -68,7 +68,7 @@ CGALRenderer::CGALRenderer(const CGAL_Nef_polyhedron &root) : root(root)
// Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).green(),
// Preferences::inst()->color(Preferences::CGAL_FACE_FRONT_COLOR).blue());
CGAL::OGL::Nef3_Converter<CGAL_Nef_polyhedron3>::convert_to_OGLPolyhedron(*this->root.p3, this->polyhedron);
CGAL::OGL::Nef3_Converter<CGAL_Nef_polyhedron3>::convert_to_OGLPolyhedron(*this->root->p3, this->polyhedron);
this->polyhedron->init();
}
}
@ -81,8 +81,8 @@ CGALRenderer::~CGALRenderer()
void CGALRenderer::draw(bool showfaces, bool showedges) const
{
if (this->root.isNull()) return;
if (this->root.getDimension() == 2) {
if (this->root->isNull()) return;
if (this->root->getDimension() == 2) {
// Draw 2D polygons
glDisable(GL_LIGHTING);
// FIXME: const QColor &col = Preferences::inst()->color(Preferences::CGAL_FACE_2D_COLOR);
@ -101,7 +101,7 @@ void CGALRenderer::draw(bool showfaces, bool showedges) const
typedef Explorer::Face_const_iterator fci_t;
typedef Explorer::Halfedge_around_face_const_circulator heafcc_t;
typedef Explorer::Point Point;
Explorer E = this->root.p2->explorer();
Explorer E = this->root->p2->explorer();
// Draw 2D edges
glDisable(GL_DEPTH_TEST);
@ -135,7 +135,7 @@ void CGALRenderer::draw(bool showfaces, bool showedges) const
glEnable(GL_DEPTH_TEST);
}
else if (this->root.getDimension() == 3) {
else if (this->root->getDimension() == 3) {
if (showfaces) this->polyhedron->set_style(SNC_BOUNDARY);
else this->polyhedron->set_style(SNC_SKELETON);

View File

@ -6,12 +6,12 @@
class CGALRenderer : public Renderer
{
public:
CGALRenderer(const class CGAL_Nef_polyhedron &root);
CGALRenderer(shared_ptr<const class CGAL_Nef_polyhedron> root);
~CGALRenderer();
void draw(bool showfaces, bool showedges) const;
public:
const CGAL_Nef_polyhedron &root;
const shared_ptr<const CGAL_Nef_polyhedron> root;
class Polyhedron *polyhedron;
class PolySet *polyset;
};

View File

@ -16,7 +16,8 @@ public:
~CGAL_Nef_polyhedron() {}
virtual size_t memsize() const;
virtual BoundingBox getBoundingBox() const {}; // FIXME: Implement
// FIXME: Implement, but we probably want a high-resolution BBox..
virtual BoundingBox getBoundingBox() const { assert(false && "not implemented"); }
virtual std::string dump() const;
virtual unsigned int getDimension() const { return this->dim; }

View File

@ -33,7 +33,6 @@
#include <boost/variant.hpp>
#include "polyset.h"
#include "dxftess.h"
#include "CGALEvaluator.h"
#include "Tree.h"
#ifdef ENABLE_CGAL

View File

@ -113,11 +113,9 @@ Response CSGTermEvaluator::visit(State &state, const AbstractPolyNode &node)
shared_ptr<CSGTerm> t1;
if (this->geomevaluator) {
shared_ptr<const Geometry> geom = this->geomevaluator->evaluateGeometry(node, false);
if (geom) {
t1 = evaluate_csg_term_from_geometry(state, this->highlights, this->background,
geom, node.modinst, node);
node.progress_report();
}
t1 = evaluate_csg_term_from_geometry(state, this->highlights, this->background,
geom, node.modinst, node);
node.progress_report();
}
this->stored_term[node.index()] = t1;
addToParent(state, node);
@ -182,10 +180,8 @@ Response CSGTermEvaluator::visit(State &state, const RenderNode &node)
geom = this->geomevaluator->evaluateGeometry(node, false);
node.progress_report();
}
if (geom) {
t1 = evaluate_csg_term_from_geometry(state, this->highlights, this->background,
geom, node.modinst, node);
}
t1 = evaluate_csg_term_from_geometry(state, this->highlights, this->background,
geom, node.modinst, node);
this->stored_term[node.index()] = t1;
addToParent(state, node);
}
@ -201,11 +197,9 @@ Response CSGTermEvaluator::visit(State &state, const CgaladvNode &node)
if (this->geomevaluator) {
geom = this->geomevaluator->evaluateGeometry(node, false);
}
if (geom) {
t1 = evaluate_csg_term_from_geometry(state, this->highlights, this->background,
geom, node.modinst, node);
node.progress_report();
}
t1 = evaluate_csg_term_from_geometry(state, this->highlights, this->background,
geom, node.modinst, node);
node.progress_report();
this->stored_term[node.index()] = t1;
addToParent(state, node);
}

View File

@ -17,7 +17,6 @@
#include "rendernode.h"
#include "clipper-utils.h"
#include "polyset-utils.h"
#include "CGALEvaluator.h"
#include "PolySet.h"
#include "openscad.h" // get_fragments_from_r()
#include "printutils.h"
@ -32,7 +31,6 @@
GeometryEvaluator::GeometryEvaluator(const class Tree &tree):
tree(tree)
{
this->cgalevaluator = new CGALEvaluator(tree, *this);
}
/*!
@ -80,6 +78,7 @@ shared_ptr<const Geometry> GeometryEvaluator::evaluateGeometry(const AbstractNod
if (!allownef) {
shared_ptr<const CGAL_Nef_polyhedron> N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(this->root);
if (N) {
assert(N->getDimension() != 2); // FIXME: Remove 2D code
if (N->getDimension() == 2) this->root.reset(N->convertToPolygon2d());
else if (N->getDimension() == 3) this->root.reset(N->convertToPolyset());
else this->root.reset();
@ -99,7 +98,8 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren(const Abstrac
if (item.second) {
if (!dim) dim = item.second->getDimension();
else if (dim != item.second->getDimension()) {
return ResultObject();
PRINT("WARNING: Mixing 2D and 3D objects is not supported.");
break;
}
}
}
@ -128,17 +128,22 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren3D(const Abstr
CGAL_Nef_polyhedron *N = new CGAL_Nef_polyhedron;
BOOST_FOREACH(const Geometry::ChildItem &item, children) {
const shared_ptr<const Geometry> &chgeom = item.second;
shared_ptr<const CGAL_Nef_polyhedron> chN = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(chgeom);
if (!chN) {
const PolySet *chps = dynamic_cast<const PolySet*>(chgeom.get());
if (chps) chN.reset(createNefPolyhedronFromGeometry(*chps));
shared_ptr<const CGAL_Nef_polyhedron> chN;
if (!chgeom) {
chN.reset(new CGAL_Nef_polyhedron(3)); // Create null polyhedron
}
else {
chN = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(chgeom);
if (!chN) {
const PolySet *chps = dynamic_cast<const PolySet*>(chgeom.get());
if (chps) chN.reset(createNefPolyhedronFromGeometry(*chps));
}
}
if (chN) {
// Initialize N on first iteration with first expected geometric object
if (N->isNull() && !N->isEmpty()) *N = chN->copy();
else CGALUtils::applyBinaryOperator(*N, *chN, op);
}
// Initialize N on first iteration with first expected geometric object
if (N->isNull() && !N->isEmpty()) *N = chN->copy();
else CGALUtils::applyBinaryOperator(*N, *chN, op);
item.first->progress_report();
}
@ -225,6 +230,7 @@ void GeometryEvaluator::applyResize3D(CGAL_Nef_polyhedron &N,
const Vector3d &newsize,
const Eigen::Matrix<bool,3,1> &autosize)
{
assert(N.getDimension() != 2); // FIXME: Remove 2D code
// Based on resize() in Giles Bathgate's RapCAD (but not exactly)
if (N.isNull() || N.isEmpty()) return;
@ -312,15 +318,13 @@ std::vector<const class Polygon2d *> GeometryEvaluator::collectChildren2D(const
GeometryCache::instance()->insert(this->tree.getIdString(*chnode), chgeom);
}
if (chgeom) {
if (chgeom->getDimension() == 2) {
if (chgeom && chgeom->getDimension() == 2) {
const Polygon2d *polygons = dynamic_cast<const Polygon2d *>(chgeom.get());
assert(polygons);
children.push_back(polygons);
}
else {
PRINT("ERROR: Only 2D children are supported by this operation!");
}
}
else {
PRINT("ERROR: Only 2D children are supported by this operation!");
}
}
return children;
@ -361,13 +365,13 @@ Geometry::ChildList GeometryEvaluator::collectChildren3D(const AbstractNode &nod
// sibling object.
smartCache(*chnode, chgeom);
if (chgeom) {
if (chgeom->getDimension() == 3) {
if (chgeom && chgeom->getDimension() == 3) {
children.push_back(item);
}
else {
PRINT("ERROR: Only 3D children are supported by this operation!");
}
}
else {
PRINT("ERROR: Only 3D children are supported by this operation!");
shared_ptr<const Geometry> nullptr;
children.push_back(Geometry::ChildItem(item.first, nullptr));
}
}
return children;
@ -594,43 +598,44 @@ Response GeometryEvaluator::visit(State &state, const TransformNode &node)
else {
// First union all children
ResultObject res = applyToChildren(node, OPENSCAD_UNION);
geom = res.constptr();
if (geom->getDimension() == 2) {
shared_ptr<const Polygon2d> polygons = dynamic_pointer_cast<const Polygon2d>(geom);
assert(polygons);
// If we got a const object, make a copy
shared_ptr<Polygon2d> newpoly;
if (res.isConst()) newpoly.reset(new Polygon2d(*polygons));
else newpoly = dynamic_pointer_cast<Polygon2d>(res.ptr());
Transform2d mat2;
mat2.matrix() <<
node.matrix(0,0), node.matrix(0,1), node.matrix(0,3),
node.matrix(1,0), node.matrix(1,1), node.matrix(1,3),
node.matrix(3,0), node.matrix(3,1), node.matrix(3,3);
newpoly->transform(mat2);
geom = newpoly;
}
else if (geom->getDimension() == 3) {
shared_ptr<const PolySet> ps = dynamic_pointer_cast<const PolySet>(geom);
if (ps) {
if ((geom = res.constptr())) {
if (geom->getDimension() == 2) {
shared_ptr<const Polygon2d> polygons = dynamic_pointer_cast<const Polygon2d>(geom);
assert(polygons);
// If we got a const object, make a copy
shared_ptr<PolySet> newps;
if (res.isConst()) newps.reset(new PolySet(*ps));
else newps = dynamic_pointer_cast<PolySet>(res.ptr());
newps->transform(node.matrix);
geom = newps;
shared_ptr<Polygon2d> newpoly;
if (res.isConst()) newpoly.reset(new Polygon2d(*polygons));
else newpoly = dynamic_pointer_cast<Polygon2d>(res.ptr());
Transform2d mat2;
mat2.matrix() <<
node.matrix(0,0), node.matrix(0,1), node.matrix(0,3),
node.matrix(1,0), node.matrix(1,1), node.matrix(1,3),
node.matrix(3,0), node.matrix(3,1), node.matrix(3,3);
newpoly->transform(mat2);
geom = newpoly;
}
else {
shared_ptr<const CGAL_Nef_polyhedron> N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(geom);
assert(N);
// If we got a const object, make a copy
shared_ptr<CGAL_Nef_polyhedron> newN;
if (res.isConst()) newN.reset(new CGAL_Nef_polyhedron(*N));
else newN = dynamic_pointer_cast<CGAL_Nef_polyhedron>(res.ptr());
newN->transform(node.matrix);
geom = newN;
else if (geom->getDimension() == 3) {
shared_ptr<const PolySet> ps = dynamic_pointer_cast<const PolySet>(geom);
if (ps) {
// If we got a const object, make a copy
shared_ptr<PolySet> newps;
if (res.isConst()) newps.reset(new PolySet(*ps));
else newps = dynamic_pointer_cast<PolySet>(res.ptr());
newps->transform(node.matrix);
geom = newps;
}
else {
shared_ptr<const CGAL_Nef_polyhedron> N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(geom);
assert(N);
// If we got a const object, make a copy
shared_ptr<CGAL_Nef_polyhedron> newN;
if (res.isConst()) newN.reset(new CGAL_Nef_polyhedron(*N));
else newN = dynamic_pointer_cast<CGAL_Nef_polyhedron>(res.ptr());
newN->transform(node.matrix);
geom = newN;
}
}
}
}
@ -1096,6 +1101,7 @@ Response GeometryEvaluator::visit(State &state, const RenderNode &node)
geom = applyToChildren(node, OPENSCAD_UNION).constptr();
shared_ptr<const CGAL_Nef_polyhedron> N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(geom);
if (N) {
assert(N->getDimension() != 2); // FIXME: Remove 2D code
PolySet *ps = NULL;
if (!N->isNull()) {
if (N->getDimension() == 3 && !N->p3->is_simple()) {

View File

@ -70,8 +70,6 @@ private:
shared_ptr<const Geometry> root;
public:
// FIXME: Deal with visibility
class CGALEvaluator *cgalevaluator;
};

View File

@ -41,7 +41,7 @@ public:
shared_ptr<CSGTerm> root_norm_term; // Normalized CSG products
class CSGChain *root_chain;
#ifdef ENABLE_CGAL
shared_ptr<const class CGAL_Nef_polyhedron> root_N;
shared_ptr<const class Geometry> root_geom;
class CGALRenderer *cgalRenderer;
#endif
#ifdef ENABLE_OPENCSG
@ -116,12 +116,12 @@ private slots:
void preferences();
private slots:
void actionRenderCSG();
void actionRenderPreview();
void csgRender();
void csgReloadRender();
#ifdef ENABLE_CGAL
void actionRenderCGAL();
void actionRenderCGALDone(shared_ptr<const class CGAL_Nef_polyhedron>);
void actionRender();
void actionRenderDone(shared_ptr<const class Geometry>);
void cgalRender();
#endif
void actionDisplayAST();
@ -142,13 +142,13 @@ public:
void clearCurrentOutput();
public slots:
void actionReloadRenderCSG();
void actionReloadRenderPreview();
#ifdef ENABLE_OPENCSG
void viewModeOpenCSG();
void viewModePreview();
#endif
#ifdef ENABLE_CGAL
void viewModeCGALSurface();
void viewModeCGALGrid();
void viewModeSurface();
void viewModeWireframe();
#endif
void viewModeThrownTogether();
void viewModeShowEdges();

View File

@ -174,9 +174,9 @@
<string>&amp;Design</string>
</property>
<addaction name="designActionAutoReload"/>
<addaction name="designActionReloadAndCompile"/>
<addaction name="designActionCompile"/>
<addaction name="designActionCompileAndRender"/>
<addaction name="designActionReloadAndPreview"/>
<addaction name="designActionPreview"/>
<addaction name="designActionRender"/>
<addaction name="separator"/>
<addaction name="designActionDisplayAST"/>
<addaction name="designActionDisplayCSGTree"/>
@ -194,9 +194,9 @@
<property name="title">
<string>&amp;View</string>
</property>
<addaction name="viewActionOpenCSG"/>
<addaction name="viewActionCGALSurfaces"/>
<addaction name="viewActionCGALGrid"/>
<addaction name="viewActionPreview"/>
<addaction name="viewActionSurfaces"/>
<addaction name="viewActionWireframe"/>
<addaction name="viewActionThrownTogether"/>
<addaction name="separator"/>
<addaction name="viewActionShowEdges"/>
@ -233,8 +233,8 @@
</widget>
<addaction name="menu_File"/>
<addaction name="menu_Edit"/>
<addaction name="menu_Design"/>
<addaction name="menu_View"/>
<addaction name="menu_Design"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
@ -395,25 +395,25 @@
<string>Hide editor</string>
</property>
</action>
<action name="designActionReloadAndCompile">
<action name="designActionReloadAndPreview">
<property name="text">
<string>&amp;Reload and Compile</string>
<string>&amp;Reload and Preview</string>
</property>
<property name="shortcut">
<string>F4</string>
</property>
</action>
<action name="designActionCompile">
<action name="designActionPreview">
<property name="text">
<string>&amp;Compile</string>
<string>&amp;Preview</string>
</property>
<property name="shortcut">
<string>F5</string>
</property>
</action>
<action name="designActionCompileAndRender">
<action name="designActionRender">
<property name="text">
<string>Compile and &amp;Render (CGAL)</string>
<string>&amp;Render</string>
</property>
<property name="shortcut">
<string>F6</string>
@ -444,34 +444,34 @@
<string>Export as &amp;OFF...</string>
</property>
</action>
<action name="viewActionOpenCSG">
<action name="viewActionPreview">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>OpenCSG</string>
<string>Preview</string>
</property>
<property name="shortcut">
<string>F9</string>
</property>
</action>
<action name="viewActionCGALSurfaces">
<action name="viewActionSurfaces">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>CGAL Surfaces</string>
<string>Surfaces</string>
</property>
<property name="shortcut">
<string>F10</string>
</property>
</action>
<action name="viewActionCGALGrid">
<action name="viewActionWireframe">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>CGAL Grid Only</string>
<string>Wireframe</string>
</property>
<property name="shortcut">
<string>F11</string>
@ -668,7 +668,7 @@
<bool>true</bool>
</property>
<property name="text">
<string>Automatic Reload and Compile</string>
<string>Automatic Reload and Preview</string>
</property>
</action>
<action name="designActionExportImage">

View File

@ -133,15 +133,17 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
if (last) break;
OpenCSGPrim *prim = new OpenCSGPrim(i_obj.type == CSGTerm::TYPE_DIFFERENCE ?
OpenCSG::Subtraction : OpenCSG::Intersection, i_obj.geom->getConvexity());
prim->geom = i_obj.geom;
prim->m = i_obj.matrix;
prim->csgmode = i_obj.type == CSGTerm::TYPE_DIFFERENCE ? CSGMODE_DIFFERENCE : CSGMODE_NORMAL;
if (highlight) prim->csgmode = csgmode_e(prim->csgmode + 20);
else if (background) prim->csgmode = csgmode_e(prim->csgmode + 10);
primitives.push_back(prim);
if (i_obj.geom) {
OpenCSGPrim *prim = new OpenCSGPrim(i_obj.type == CSGTerm::TYPE_DIFFERENCE ?
OpenCSG::Subtraction : OpenCSG::Intersection, i_obj.geom->getConvexity());
prim->geom = i_obj.geom;
prim->m = i_obj.matrix;
prim->csgmode = i_obj.type == CSGTerm::TYPE_DIFFERENCE ? CSGMODE_DIFFERENCE : CSGMODE_NORMAL;
if (highlight) prim->csgmode = csgmode_e(prim->csgmode + 20);
else if (background) prim->csgmode = csgmode_e(prim->csgmode + 10);
primitives.push_back(prim);
}
}
std::for_each(primitives.begin(), primitives.end(), del_fun<OpenCSG::Primitive>());
}

View File

@ -28,7 +28,6 @@
#include "module.h"
#include "evalcontext.h"
#include "builtin.h"
#include "PolySetEvaluator.h"
#include "polyset.h"
#include <sstream>
#include <assert.h>
@ -117,11 +116,6 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant
return node;
}
Geometry *CgaladvNode::evaluate_geometry(PolySetEvaluator *ps) const
{
return ps->evaluateGeometry(*this);
}
std::string CgaladvNode::name() const
{
switch (this->type) {

View File

@ -26,7 +26,6 @@ public:
}
virtual std::string toString() const;
virtual std::string name() const;
Geometry *evaluate_geometry(class PolySetEvaluator *ps) const;
Value path;
std::string subdiv_type;

View File

@ -692,7 +692,7 @@ CGAL_Nef_polyhedron *createNefPolyhedronFromGeometry(const Geometry &geom)
const Polygon2d *poly2d = dynamic_cast<const Polygon2d*>(&geom);
if (poly2d) return createNefPolyhedronFromPolygon2d(*poly2d);
}
assert(false && "CGALEvaluator::evaluateCGALMesh(): Unsupported geometry type");
assert(false && "createNefPolyhedronFromGeometry(): Unsupported geometry type");
return NULL;
}

View File

@ -3,7 +3,6 @@
#include "Tree.h"
#include "GeometryEvaluator.h"
#include "CGALEvaluator.h"
#include "progress.h"
#include "printutils.h"
@ -28,15 +27,15 @@ void CGALWorker::start(const Tree &tree)
void CGALWorker::work()
{
shared_ptr<const CGAL_Nef_polyhedron> root_N;
shared_ptr<const Geometry> root_geom;
try {
GeometryEvaluator evaluator(*this->tree);
root_N = evaluator.cgalevaluator->evaluateCGALMesh(*this->tree->root());
root_geom = evaluator.evaluateGeometry(*this->tree->root(), true);
}
catch (const ProgressCancelException &e) {
PRINT("Rendering cancelled.");
}
emit done(root_N);
emit done(root_geom);
thread->quit();
}

View File

@ -18,7 +18,7 @@ protected slots:
void work();
signals:
void done(shared_ptr<const class CGAL_Nef_polyhedron>);
void done(shared_ptr<const class Geometry>);
protected:

View File

@ -38,6 +38,11 @@
may or may not have a subtree which is already evaluated (e.g. using
the render() module).
Note: To distinguish between geometry evaluated to an empty volume
and non-geometric nodes (e.g. echo), a NULL CSGTerm is considered a
non-geometric node, while a CSGTerm with a NULL geometry is
considered empty geometry. This is important when e.g. establishing
positive vs. negative volumes using the difference operator.
*/
/*!
@ -128,6 +133,7 @@ CSGTerm::~CSGTerm()
void CSGTerm::initBoundingBox()
{
if (this->type == TYPE_PRIMITIVE) {
if (!this->geom) return;
this->bbox = this->m * this->geom->getBoundingBox();
}
else {
@ -223,9 +229,11 @@ BoundingBox CSGChain::getBoundingBox() const
BoundingBox bbox;
BOOST_FOREACH(const CSGChainObject &obj, this->objects) {
if (obj.type != CSGTerm::TYPE_DIFFERENCE) {
BoundingBox psbox = obj.geom->getBoundingBox();
if (!psbox.isNull()) {
bbox.extend(obj.matrix * psbox);
if (obj.geom) {
BoundingBox psbox = obj.geom->getBoundingBox();
if (!psbox.isNull()) {
bbox.extend(obj.matrix * psbox);
}
}
}
}

View File

@ -29,16 +29,72 @@
#include "polyset.h"
#include "dxfdata.h"
#include <boost/foreach.hpp>
#ifdef ENABLE_CGAL
#include "CGAL_Nef_polyhedron.h"
#include "cgal.h"
void exportFile(const class Geometry *root_geom, std::ostream &output, FileFormat format)
{
if (const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(root_geom)) {
switch (format) {
case OPENSCAD_STL:
export_stl(N, output);
break;
case OPENSCAD_OFF:
export_off(N, output);
break;
case OPENSCAD_DXF:
export_dxf(N, output);
break;
default:
assert(false && "Unknown file format");
}
}
else {
if (const PolySet *ps = dynamic_cast<const PolySet *>(root_geom)) {
switch (format) {
case OPENSCAD_STL:
export_stl(ps, output);
break;
default:
assert(false && "Unsupported file format");
}
}
else {
assert(false && "Not implemented");
}
}
}
void export_stl(const PolySet *ps, std::ostream &output)
{
setlocale(LC_NUMERIC, "C"); // Ensure radix is . (not ,) in output
output << "solid OpenSCAD_Model\n";
BOOST_FOREACH(const PolySet::Polygon &p, ps->polygons) {
output << " facet normal 0 0 0\n";
output << " outer loop\n";
BOOST_FOREACH(const Vector3d &v, p) {
output << "vertex" << v[0] << " " << v[1] << " " << v[2] << "\n";
}
output << " endloop\n";
output << " endfacet\n";
}
output << "endsolid OpenSCAD_Model\n";
setlocale(LC_NUMERIC, ""); // Set default locale
}
/*!
Saves the current 3D CGAL Nef polyhedron as STL to the given file.
The file must be open.
*/
void export_stl(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
{
if (!root_N->p3->is_simple()) {
PRINT("Object isn't a valid 2-manifold! Modify your design.\n");
}
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
CGAL_Polyhedron P;
@ -127,6 +183,9 @@ void export_stl(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
void export_off(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
{
if (!root_N->p3->is_simple()) {
PRINT("Object isn't a valid 2-manifold! Modify your design.\n");
}
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
CGAL_Polyhedron P;

View File

@ -7,10 +7,20 @@
#ifdef ENABLE_CGAL
enum FileFormat {
OPENSCAD_STL,
OPENSCAD_OFF,
OPENSCAD_DXF
};
void exportFile(const class Geometry *root_geom, std::ostream &output, FileFormat format);
void export_png(const class Geometry *root_geom, Camera &c, std::ostream &output);
void export_stl(const class CGAL_Nef_polyhedron *root_N, std::ostream &output);
void export_stl(const class PolySet *ps, std::ostream &output);
void export_off(const CGAL_Nef_polyhedron *root_N, std::ostream &output);
void export_dxf(const CGAL_Nef_polyhedron *root_N, std::ostream &output);
void export_png_with_cgal(const CGAL_Nef_polyhedron *root_N, Camera &c, std::ostream &output);
void export_png(const CGAL_Nef_polyhedron *root_N, Camera &c, std::ostream &output);
void export_png_with_opencsg(Tree &tree, Camera &c, std::ostream &output);
void export_png_with_throwntogether(Tree &tree, Camera &c, std::ostream &output);

View File

@ -10,8 +10,20 @@
#include "CGALRenderer.h"
#include "CGAL_renderer.h"
#include "cgal.h"
#include "cgalutils.h"
#include "CGAL_Nef_polyhedron.h"
void export_png_with_cgal(const CGAL_Nef_polyhedron *root_N, Camera &cam, std::ostream &output)
void export_png(const Geometry *root_geom, Camera &cam, std::ostream &output)
{
const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(root_geom);
if (!N) {
// FIXME: Support rendering non-Nef directly
N = createNefPolyhedronFromGeometry(*root_geom);
}
export_png(N, cam, output);
}
void export_png(const CGAL_Nef_polyhedron *root_N, Camera &cam, std::ostream &output)
{
OffscreenView *glview;
try {
@ -20,7 +32,8 @@ void export_png_with_cgal(const CGAL_Nef_polyhedron *root_N, Camera &cam, std::o
fprintf(stderr,"Can't create OpenGL OffscreenView. Code: %i.\n", error);
return;
}
CGALRenderer cgalRenderer(*root_N);
shared_ptr<const CGAL_Nef_polyhedron> ptr(root_N);
CGALRenderer cgalRenderer(ptr);
BoundingBox bbox;
if (cgalRenderer.polyhedron) {

View File

@ -31,8 +31,8 @@
#include "printutils.h"
#include "fileutils.h"
#include "builtin.h"
#include "PolySetEvaluator.h"
#include "calc.h"
#include "polyset.h"
#include "mathc99.h"
#include <sstream>
@ -127,22 +127,6 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
return node;
}
class Geometry *LinearExtrudeNode::evaluate_geometry(PolySetEvaluator *evaluator) const
{
if (!evaluator) {
PRINTB("WARNING: No suitable PolySetEvaluator found for %s module!", this->name());
return NULL;
}
print_messages_push();
Geometry *ps = evaluator->evaluateGeometry(*this);
print_messages_pop();
return ps;
}
std::string LinearExtrudeNode::toString() const
{
std::stringstream stream;

View File

@ -27,7 +27,6 @@ public:
bool center, has_twist;
Filename filename;
std::string layername;
virtual Geometry *evaluate_geometry(class PolySetEvaluator *) const;
};
#endif

View File

@ -86,12 +86,12 @@
#ifdef ENABLE_CGAL
#include "CGALCache.h"
#include "CGALEvaluator.h"
#include "GeometryEvaluator.h"
#include "CGALRenderer.h"
#include "CGAL_Nef_polyhedron.h"
#include "cgal.h"
#include "cgalworker.h"
#include "cgalutils.h"
#else
@ -160,8 +160,8 @@ MainWindow::MainWindow(const QString &filename)
#ifdef ENABLE_CGAL
this->cgalworker = new CGALWorker();
connect(this->cgalworker, SIGNAL(done(shared_ptr<const CGAL_Nef_polyhedron>)),
this, SLOT(actionRenderCGALDone(shared_ptr<const CGAL_Nef_polyhedron>)));
connect(this->cgalworker, SIGNAL(done(shared_ptr<const Geometry>)),
this, SLOT(actionRenderDone(shared_ptr<const Geometry>)));
#endif
top_ctx.registerBuiltin();
@ -206,7 +206,7 @@ MainWindow::MainWindow(const QString &filename)
waitAfterReloadTimer->setInterval(200);
connect(waitAfterReloadTimer, SIGNAL(timeout()), this, SLOT(waitAfterReload()));
connect(this->e_tval, SIGNAL(textChanged(QString)), this, SLOT(actionRenderCSG()));
connect(this->e_tval, SIGNAL(textChanged(QString)), this, SLOT(actionRenderPreview()));
connect(this->e_fps, SIGNAL(textChanged(QString)), this, SLOT(updatedFps()));
animate_panel->hide();
@ -285,12 +285,12 @@ MainWindow::MainWindow(const QString &filename)
// Design menu
connect(this->designActionAutoReload, SIGNAL(toggled(bool)), this, SLOT(autoReloadSet(bool)));
connect(this->designActionReloadAndCompile, SIGNAL(triggered()), this, SLOT(actionReloadRenderCSG()));
connect(this->designActionCompile, SIGNAL(triggered()), this, SLOT(actionRenderCSG()));
connect(this->designActionReloadAndPreview, SIGNAL(triggered()), this, SLOT(actionReloadRenderPreview()));
connect(this->designActionPreview, SIGNAL(triggered()), this, SLOT(actionRenderPreview()));
#ifdef ENABLE_CGAL
connect(this->designActionCompileAndRender, SIGNAL(triggered()), this, SLOT(actionRenderCGAL()));
connect(this->designActionRender, SIGNAL(triggered()), this, SLOT(actionRender()));
#else
this->designActionCompileAndRender->setVisible(false);
this->designActionRender->setVisible(false);
#endif
connect(this->designActionDisplayAST, SIGNAL(triggered()), this, SLOT(actionDisplayAST()));
connect(this->designActionDisplayCSGTree, SIGNAL(triggered()), this, SLOT(actionDisplayCSGTree()));
@ -304,20 +304,20 @@ MainWindow::MainWindow(const QString &filename)
// View menu
#ifndef ENABLE_OPENCSG
this->viewActionOpenCSG->setVisible(false);
this->viewActionPreview->setVisible(false);
#else
connect(this->viewActionOpenCSG, SIGNAL(triggered()), this, SLOT(viewModeOpenCSG()));
connect(this->viewActionPreview, SIGNAL(triggered()), this, SLOT(viewModePreview()));
if (!this->qglview->hasOpenCSGSupport()) {
this->viewActionOpenCSG->setEnabled(false);
this->viewActionPreview->setEnabled(false);
}
#endif
#ifdef ENABLE_CGAL
connect(this->viewActionCGALSurfaces, SIGNAL(triggered()), this, SLOT(viewModeCGALSurface()));
connect(this->viewActionCGALGrid, SIGNAL(triggered()), this, SLOT(viewModeCGALGrid()));
connect(this->viewActionSurfaces, SIGNAL(triggered()), this, SLOT(viewModeSurface()));
connect(this->viewActionWireframe, SIGNAL(triggered()), this, SLOT(viewModeWireframe()));
#else
this->viewActionCGALSurfaces->setVisible(false);
this->viewActionCGALGrid->setVisible(false);
this->viewActionSurfaces->setVisible(false);
this->viewActionWireframe->setVisible(false);
#endif
connect(this->viewActionThrownTogether, SIGNAL(triggered()), this, SLOT(viewModeThrownTogether()));
connect(this->viewActionShowEdges, SIGNAL(triggered()), this, SLOT(viewModeShowEdges()));
@ -385,7 +385,7 @@ MainWindow::MainWindow(const QString &filename)
show();
#ifdef ENABLE_OPENCSG
viewModeOpenCSG();
viewModePreview();
#else
viewModeThrownTogether();
#endif
@ -446,7 +446,7 @@ MainWindow::~MainWindow()
if (root_module) delete root_module;
if (root_node) delete root_node;
#ifdef ENABLE_CGAL
this->root_N.reset();
this->root_geom.reset();
delete this->cgalRenderer;
#endif
#ifdef ENABLE_OPENCSG
@ -581,7 +581,7 @@ void MainWindow::updateTVal()
double fps = this->e_fps->text().toDouble(&fps_ok);
if (fps_ok) {
if (fps <= 0) {
actionRenderCSG();
actionRenderPreview();
} else {
double s = this->e_fsteps->text().toDouble();
double t = this->e_tval->text().toDouble() + 1/s;
@ -1159,7 +1159,7 @@ void MainWindow::compileTopLevelDocument()
void MainWindow::checkAutoReload()
{
if (!this->fileName.isEmpty()) {
actionReloadRenderCSG();
actionReloadRenderPreview();
}
}
@ -1190,7 +1190,7 @@ bool MainWindow::checkEditorModified()
return true;
}
void MainWindow::actionReloadRenderCSG()
void MainWindow::actionReloadRenderPreview()
{
if (GuiLocker::isLocked()) return;
GuiLocker::lock();
@ -1214,7 +1214,7 @@ void MainWindow::csgReloadRender()
}
else {
#ifdef ENABLE_OPENCSG
viewModeOpenCSG();
viewModePreview();
#else
viewModeThrownTogether();
#endif
@ -1222,7 +1222,7 @@ void MainWindow::csgReloadRender()
compileEnded();
}
void MainWindow::actionRenderCSG()
void MainWindow::actionRenderPreview()
{
if (GuiLocker::isLocked()) return;
GuiLocker::lock();
@ -1246,7 +1246,7 @@ void MainWindow::csgRender()
}
else {
#ifdef ENABLE_OPENCSG
viewModeOpenCSG();
viewModePreview();
#else
viewModeThrownTogether();
#endif
@ -1266,7 +1266,7 @@ void MainWindow::csgRender()
#ifdef ENABLE_CGAL
void MainWindow::actionRenderCGAL()
void MainWindow::actionRender()
{
if (GuiLocker::isLocked()) return;
GuiLocker::lock();
@ -1289,7 +1289,7 @@ void MainWindow::cgalRender()
this->qglview->setRenderer(NULL);
delete this->cgalRenderer;
this->cgalRenderer = NULL;
this->root_N.reset();
this->root_geom.reset();
PRINT("Rendering Polygon Mesh using CGAL...");
@ -1301,60 +1301,75 @@ void MainWindow::cgalRender()
this->cgalworker->start(this->tree);
}
void MainWindow::actionRenderCGALDone(shared_ptr<const CGAL_Nef_polyhedron> root_N)
void MainWindow::actionRenderDone(shared_ptr<const Geometry> root_geom)
{
progress_report_fin();
if (root_N) {
if (root_geom) {
GeometryCache::instance()->print();
#ifdef ENABLE_CGAL
CGALCache::instance()->print();
#endif
if (!root_N->isNull()) {
if (root_N->getDimension() == 2) {
PRINT(" Top level object is a 2D object:");
PRINTB(" Empty: %6s", (root_N->p2->is_empty() ? "yes" : "no"));
PRINTB(" Plane: %6s", (root_N->p2->is_plane() ? "yes" : "no"));
PRINTB(" Vertices: %6d", root_N->p2->explorer().number_of_vertices());
PRINTB(" Halfedges: %6d", root_N->p2->explorer().number_of_halfedges());
PRINTB(" Edges: %6d", root_N->p2->explorer().number_of_edges());
PRINTB(" Faces: %6d", root_N->p2->explorer().number_of_faces());
PRINTB(" FaceCycles: %6d", root_N->p2->explorer().number_of_face_cycles());
PRINTB(" ConnComp: %6d", root_N->p2->explorer().number_of_connected_components());
}
if (root_N->getDimension() == 3) {
PRINT(" Top level object is a 3D object:");
PRINTB(" Simple: %6s", (root_N->p3->is_simple() ? "yes" : "no"));
PRINTB(" Valid: %6s", (root_N->p3->is_valid() ? "yes" : "no"));
PRINTB(" Vertices: %6d", root_N->p3->number_of_vertices());
PRINTB(" Halfedges: %6d", root_N->p3->number_of_halfedges());
PRINTB(" Edges: %6d", root_N->p3->number_of_edges());
PRINTB(" Halffacets: %6d", root_N->p3->number_of_halffacets());
PRINTB(" Facets: %6d", root_N->p3->number_of_facets());
PRINTB(" Volumes: %6d", root_N->p3->number_of_volumes());
}
}
int s = this->progresswidget->elapsedTime() / 1000;
PRINTB("Total rendering time: %d hours, %d minutes, %d seconds", (s / (60*60)) % ((s / 60) % 60) % (s % 60));
this->root_N = root_N;
if (!this->root_N->isNull()) {
this->cgalRenderer = new CGALRenderer(*this->root_N);
// Go to CGAL view mode
if (viewActionCGALGrid->isChecked()) {
viewModeCGALGrid();
}
else {
viewModeCGALSurface();
}
PRINT("Rendering finished.");
if (const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(root_geom.get())) {
if (!N->isNull()) {
if (N->getDimension() == 2) {
PRINT(" Top level object is a 2D object:");
PRINTB(" Empty: %6s", (N->p2->is_empty() ? "yes" : "no"));
PRINTB(" Plane: %6s", (N->p2->is_plane() ? "yes" : "no"));
PRINTB(" Vertices: %6d", N->p2->explorer().number_of_vertices());
PRINTB(" Halfedges: %6d", N->p2->explorer().number_of_halfedges());
PRINTB(" Edges: %6d", N->p2->explorer().number_of_edges());
PRINTB(" Faces: %6d", N->p2->explorer().number_of_faces());
PRINTB(" FaceCycles: %6d", N->p2->explorer().number_of_face_cycles());
PRINTB(" ConnComp: %6d", N->p2->explorer().number_of_connected_components());
}
if (N->getDimension() == 3) {
PRINT(" Top level object is a 3D object:");
PRINTB(" Simple: %6s", (N->p3->is_simple() ? "yes" : "no"));
PRINTB(" Valid: %6s", (N->p3->is_valid() ? "yes" : "no"));
PRINTB(" Vertices: %6d", N->p3->number_of_vertices());
PRINTB(" Halfedges: %6d", N->p3->number_of_halfedges());
PRINTB(" Edges: %6d", N->p3->number_of_edges());
PRINTB(" Halffacets: %6d", N->p3->number_of_halffacets());
PRINTB(" Facets: %6d", N->p3->number_of_facets());
PRINTB(" Volumes: %6d", N->p3->number_of_volumes());
}
}
}
else {
PRINT("WARNING: No top level geometry to render");
else if (const PolySet *ps = dynamic_cast<const PolySet *>(root_geom.get())) {
assert(ps->getDimension() == 3);
PRINT(" Top level object is a 3D object:");
PRINTB(" Facets: %6d", ps->numPolygons());
} else if (const Polygon2d *poly = dynamic_cast<const Polygon2d *>(root_geom.get())) {
PRINT(" Top level object is a 2D object:");
PRINTB(" Contours: %6d", poly->outlines().size());
} else {
assert(false && "Unknown geometry type");
}
PRINT("Rendering finished.");
this->root_geom = root_geom;
if (this->root_geom) {
// FIXME: Support rendering PolySets and Polygon2d roots
shared_ptr<const CGAL_Nef_polyhedron> new_N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(this->root_geom);
if (!new_N) {
new_N.reset(createNefPolyhedronFromGeometry(*this->root_geom));
}
this->cgalRenderer = new CGALRenderer(new_N);
// Go to CGAL view mode
if (viewActionWireframe->isChecked()) viewModeWireframe();
else viewModeSurface();
}
}
else {
PRINT("WARNING: No top level geometry to render");
}
this->statusBar()->removeWidget(this->progresswidget);
@ -1431,19 +1446,20 @@ void MainWindow::actionExportSTLorOFF(bool)
#ifdef ENABLE_CGAL
setCurrentOutput();
if (!this->root_N) {
if (!this->root_geom) {
PRINT("Nothing to export! Try building first (press F6).");
clearCurrentOutput();
return;
}
if (this->root_N->getDimension() != 3) {
if (this->root_geom->getDimension() != 3) {
PRINT("Current top level object is not a 3D object.");
clearCurrentOutput();
return;
}
if (!this->root_N->p3->is_simple()) {
const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(this->root_geom.get());
if (N && N->p3->is_simple()) {
PRINT("Object isn't a valid 2-manifold! Modify your design. See http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/STL_Import_and_Export");
clearCurrentOutput();
return;
@ -1465,8 +1481,8 @@ void MainWindow::actionExportSTLorOFF(bool)
PRINTB("Can't open file \"%s\" for export", stl_filename.toLocal8Bit().constData());
}
else {
if (stl_mode) export_stl(this->root_N.get(), fstream);
else export_off(this->root_N.get(), fstream);
if (stl_mode) exportFile(this->root_geom.get(), fstream, OPENSCAD_STL);
else exportFile(this->root_geom.get(), fstream, OPENSCAD_OFF);
fstream.close();
PRINTB("%s export finished.", (stl_mode ? "STL" : "OFF"));
@ -1491,13 +1507,13 @@ void MainWindow::actionExportDXF()
#ifdef ENABLE_CGAL
setCurrentOutput();
if (!this->root_N) {
if (!this->root_geom) {
PRINT("Nothing to export! Try building first (press F6).");
clearCurrentOutput();
return;
}
if (this->root_N->getDimension() != 2) {
if (this->root_geom->getDimension() != 2) {
PRINT("Current top level object is not a 2D object.");
clearCurrentOutput();
return;
@ -1518,7 +1534,7 @@ void MainWindow::actionExportDXF()
PRINTB("Can't open file \"%s\" for export", dxf_filename.toLocal8Bit().constData());
}
else {
export_dxf(this->root_N.get(), fstream);
exportFile(this->root_geom.get(), fstream, OPENSCAD_DXF);
fstream.close();
PRINT("DXF export finished.");
}
@ -1587,10 +1603,10 @@ void MainWindow::actionFlushCaches()
void MainWindow::viewModeActionsUncheck()
{
viewActionOpenCSG->setChecked(false);
viewActionPreview->setChecked(false);
#ifdef ENABLE_CGAL
viewActionCGALSurfaces->setChecked(false);
viewActionCGALGrid->setChecked(false);
viewActionSurfaces->setChecked(false);
viewActionWireframe->setChecked(false);
#endif
viewActionThrownTogether->setChecked(false);
}
@ -1601,11 +1617,11 @@ void MainWindow::viewModeActionsUncheck()
Go to the OpenCSG view mode.
Falls back to thrown together mode if OpenCSG is not available
*/
void MainWindow::viewModeOpenCSG()
void MainWindow::viewModePreview()
{
if (this->qglview->hasOpenCSGSupport()) {
viewModeActionsUncheck();
viewActionOpenCSG->setChecked(true);
viewActionPreview->setChecked(true);
this->qglview->setRenderer(this->opencsgRenderer ? (Renderer *)this->opencsgRenderer : (Renderer *)this->thrownTogetherRenderer);
this->qglview->updateGL();
} else {
@ -1617,19 +1633,19 @@ void MainWindow::viewModeOpenCSG()
#ifdef ENABLE_CGAL
void MainWindow::viewModeCGALSurface()
void MainWindow::viewModeSurface()
{
viewModeActionsUncheck();
viewActionCGALSurfaces->setChecked(true);
viewActionSurfaces->setChecked(true);
this->qglview->setShowFaces(true);
this->qglview->setRenderer(this->cgalRenderer);
this->qglview->updateGL();
}
void MainWindow::viewModeCGALGrid()
void MainWindow::viewModeWireframe()
{
viewModeActionsUncheck();
viewActionCGALGrid->setChecked(true);
viewActionWireframe->setChecked(true);
this->qglview->setShowFaces(false);
this->qglview->setRenderer(this->cgalRenderer);
this->qglview->updateGL();
@ -1673,7 +1689,7 @@ void MainWindow::viewModeAnimate()
{
if (viewActionAnimate->isChecked()) {
animate_panel->show();
actionRenderCSG();
actionRenderPreview();
updatedFps();
} else {
animate_panel->hide();

View File

@ -46,7 +46,6 @@
#ifdef ENABLE_CGAL
#include "CGAL_Nef_polyhedron.h"
#include "CGALEvaluator.h"
#endif
#include "csgterm.h"
@ -249,7 +248,7 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
ModuleInstantiation root_inst("group");
AbstractNode *root_node;
AbstractNode *absolute_root_node;
shared_ptr<const CGAL_Nef_polyhedron> root_N;
shared_ptr<const Geometry> root_geom;
handle_dep(filename.c_str());
@ -333,7 +332,13 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
if ((echo_output_file || png_output_file) && !(renderer==Render::CGAL)) {
// echo or OpenCSG png -> don't necessarily need CGALMesh evaluation
} else {
root_N = geomevaluator.cgalevaluator->evaluateCGALMesh(*tree.root());
root_geom = geomevaluator.evaluateGeometry(*tree.root(), true);
const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron*>(root_geom.get());
if (!root_geom || (N && N->isNull())) {
PRINT("Empty top-level object");
return 1;
}
}
fs::current_path(original_path);
@ -358,45 +363,37 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
}
if (stl_output_file) {
if (root_N->getDimension() != 3) {
if (root_geom->getDimension() != 3) {
PRINT("Current top level object is not a 3D object.\n");
return 1;
}
if (!root_N->p3->is_simple()) {
PRINT("Object isn't a valid 2-manifold! Modify your design.\n");
return 1;
}
std::ofstream fstream(stl_output_file);
if (!fstream.is_open()) {
PRINTB("Can't open file \"%s\" for export", stl_output_file);
}
else {
export_stl(root_N.get(), fstream);
exportFile(root_geom.get(), fstream, OPENSCAD_STL);
fstream.close();
}
}
if (off_output_file) {
if (root_N->getDimension() != 3) {
if (root_geom->getDimension() != 3) {
PRINT("Current top level object is not a 3D object.\n");
return 1;
}
if (!root_N->p3->is_simple()) {
PRINT("Object isn't a valid 2-manifold! Modify your design.\n");
return 1;
}
std::ofstream fstream(off_output_file);
if (!fstream.is_open()) {
PRINTB("Can't open file \"%s\" for export", off_output_file);
}
else {
export_off(root_N.get(), fstream);
exportFile(root_geom.get(), fstream, OPENSCAD_OFF);
fstream.close();
}
}
if (dxf_output_file) {
if (root_N->getDimension() != 2) {
if (root_geom->getDimension() != 2) {
PRINT("Current top level object is not a 2D object.\n");
return 1;
}
@ -405,7 +402,7 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
PRINTB("Can't open file \"%s\" for export", dxf_output_file);
}
else {
export_dxf(root_N.get(), fstream);
exportFile(root_geom.get(), fstream, OPENSCAD_DXF);
fstream.close();
}
}
@ -417,12 +414,13 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
}
else {
if (renderer==Render::CGAL) {
export_png_with_cgal(root_N.get(), camera, fstream);
export_png(root_geom.get(), camera, fstream);
} else if (renderer==Render::THROWNTOGETHER) {
export_png_with_throwntogether(tree, camera, fstream);
} else {
export_png_with_opencsg(tree, camera, fstream);
}
PRINTB("Camera eye: %f %f %f\n", camera.eye[0] % camera.eye[1] % camera.eye[2]);
fstream.close();
}
}
@ -452,7 +450,7 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
#include <QDir>
#include <QMetaType>
Q_DECLARE_METATYPE(shared_ptr<const CGAL_Nef_polyhedron>);
Q_DECLARE_METATYPE(shared_ptr<const Geometry>);
// Only if "fileName" is not absolute, prepend the "absoluteBase".
static QString assemblePath(const fs::path& absoluteBase,
@ -496,7 +494,7 @@ int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, cha
QCoreApplication::setApplicationVersion(TOSTRING(OPENSCAD_VERSION));
// Other global settings
qRegisterMetaType<shared_ptr<const CGAL_Nef_polyhedron> >();
qRegisterMetaType<shared_ptr<const Geometry> >();
const QString &app_path = app.applicationDirPath();

View File

@ -27,6 +27,7 @@ public:
virtual unsigned int getDimension() const { return this->is2d ? 2 : 3; }
bool empty() const { return polygons.size() == 0; }
size_t numPolygons() const { return polygons.size(); }
void append_poly();
void append_vertex(double x, double y, double z = 0.0);
void append_vertex(Vector3d v);

View File

@ -107,7 +107,6 @@ public:
primitive_type_e type;
int convexity;
Value points, paths, faces;
virtual Geometry *evaluate_geometry(class PolySetEvaluator *) const { return createGeometry(); }
virtual Geometry *createGeometry() const;
};
@ -293,6 +292,10 @@ static void generate_circle(point2d *circle, double r, int fragments)
}
}
/*!
Creates geometry for this node.
May return NULL if geometry creation failed.
*/
Geometry *PrimitiveNode::createGeometry() const
{
Geometry *g = NULL;
@ -575,8 +578,6 @@ sphere_next_r2:
p->setConvexity(convexity);
}
// FIXME: IF the above failed, create an empty polyset as that's required later on
if (!g) g = new PolySet();
return g;
}

View File

@ -30,7 +30,6 @@
#include "printutils.h"
#include "builtin.h"
#include "visitor.h"
#include "PolySetEvaluator.h"
#include "polyset.h"
#include <assert.h>
@ -69,22 +68,6 @@ AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInst
return node;
}
Geometry *ProjectionNode::evaluate_geometry(PolySetEvaluator *evaluator) const
{
if (!evaluator) {
PRINTB("WARNING: No suitable PolySetEvaluator found for %s module!", this->name());
return NULL;
}
print_messages_push();
Geometry *ps = evaluator->evaluateGeometry(*this);
print_messages_pop();
return ps;
}
std::string ProjectionNode::toString() const
{
std::stringstream stream;

View File

@ -19,7 +19,6 @@ public:
int convexity;
bool cut_mode;
virtual class Geometry *evaluate_geometry(class PolySetEvaluator *evaluator) const;
};
#endif

View File

@ -28,7 +28,6 @@
#include "module.h"
#include "evalcontext.h"
#include "builtin.h"
#include "PolySetEvaluator.h"
#include "polyset.h"
#include <sstream>
@ -62,11 +61,6 @@ AbstractNode *RenderModule::instantiate(const Context *ctx, const ModuleInstanti
return node;
}
class Geometry *RenderNode::evaluate_geometry(PolySetEvaluator *ps) const
{
return ps->evaluateGeometry(*this);
}
std::string RenderNode::toString() const
{
std::stringstream stream;

View File

@ -14,7 +14,6 @@ public:
}
virtual std::string toString() const;
virtual std::string name() const { return "render"; }
Geometry *evaluate_geometry(class PolySetEvaluator *ps) const;
int convexity;
};

View File

@ -32,7 +32,6 @@
#include "builtin.h"
#include "polyset.h"
#include "visitor.h"
#include "PolySetEvaluator.h"
#include <sstream>
#include <boost/assign/std/vector.hpp>
@ -92,22 +91,6 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI
return node;
}
Geometry *RotateExtrudeNode::evaluate_geometry(PolySetEvaluator *evaluator) const
{
if (!evaluator) {
PRINTB("WARNING: No suitable PolySetEvaluator found for %s module!", this->name());
return NULL;
}
print_messages_push();
Geometry *ps = evaluator->evaluateGeometry(*this);
print_messages_pop();
return ps;
}
std::string RotateExtrudeNode::toString() const
{
std::stringstream stream;

View File

@ -24,7 +24,6 @@ public:
double origin_x, origin_y, scale;
Filename filename;
std::string layername;
virtual Geometry *evaluate_geometry(class PolySetEvaluator *) const;
};
#endif

View File

@ -67,7 +67,6 @@ public:
Filename filename;
bool center;
int convexity;
virtual Geometry *evaluate_geometry(class PolySetEvaluator *) const { return createGeometry(); }
virtual Geometry *createGeometry() const;
};

View File

@ -556,7 +556,6 @@ set(CGAL_SOURCES
../src/CSGTermEvaluator.cc
../src/CGAL_Nef_polyhedron.cc
../src/cgalutils.cc
../src/CGALEvaluator.cc
../src/CGALCache.cc
../src/CGAL_Nef_polyhedron_DxfData.cc
../src/cgaladv_minkowski2.cc

View File

@ -43,6 +43,8 @@ CSGTextRenderer::process(string &target, const string &src, OpenSCADOperator op)
case OPENSCAD_MINKOWSKI:
target += "M" + src;
break;
default:
assert(false);
}
}

View File

@ -38,7 +38,6 @@
#include "CGAL_Nef_polyhedron.h"
#include "GeometryEvaluator.h"
#include "CGALEvaluator.h"
#include "PolySetCGALEvaluator.h"
#include "CGALCache.h"
#ifndef _MSC_VER
@ -149,9 +148,9 @@ int main(int argc, char **argv)
print_messages_push();
std::cout << "First evaluation:\n";
shared_ptr<const CGAL_Nef_polyhedron> N = geomevaluator.cgalevaluator->evaluateCGALMesh(*root_node);
shared_ptr<const Geometry> geom = geomevaluator.evaluateGeometry(*root_node, true);
std::cout << "Second evaluation:\n";
shared_ptr<const CGAL_Nef_polyhedron> N2 = geomevaluator.cgalevaluator->evaluateCGALMesh(*root_node);
shared_ptr<const Geometry> geom2 = geomevaluator.evaluateGeometry(*root_node, true);
// FIXME:
// Evaluate again to make cache kick in
// Record printed output and compare it