Refactoring to facilitate more sharing of code between CGALEvaluator, GeometryEvaluator and CGALUtils

customizer
Marius Kintel 2013-12-02 01:48:22 -05:00
parent c507db461d
commit 1f488f851d
18 changed files with 378 additions and 328 deletions

View File

@ -251,7 +251,6 @@ HEADERS += src/typedefs.h \
src/nodedumper.h \
src/ModuleCache.h \
src/GeometryCache.h \
src/PolySetEvaluator.h \
src/GeometryEvaluator.h \
src/CSGTermEvaluator.h \
src/Tree.h \
@ -320,7 +319,6 @@ SOURCES += src/version_check.cc \
\
src/nodedumper.cc \
src/traverser.cc \
src/PolySetEvaluator.cc \
src/GeometryEvaluator.cc \
src/ModuleCache.cc \
src/GeometryCache.cc \
@ -384,7 +382,6 @@ HEADERS += src/cgal.h \
src/cgalutils.h \
src/CGALEvaluator.h \
src/CGALCache.h \
src/PolySetCGALEvaluator.h \
src/CGALRenderer.h \
src/CGAL_Nef_polyhedron.h \
src/CGAL_Nef3_workaround.h \
@ -393,7 +390,6 @@ HEADERS += src/cgal.h \
SOURCES += src/cgalutils.cc \
src/CGALEvaluator.cc \
src/PolySetCGALEvaluator.cc \
src/CGALCache.cc \
src/CGALRenderer.cc \
src/CGAL_Nef_polyhedron.cc \

View File

@ -8,21 +8,21 @@ CGALCache::CGALCache(size_t limit) : cache(limit)
{
}
const CGAL_Nef_polyhedron &CGALCache::get(const std::string &id) const
shared_ptr<const CGAL_Nef_polyhedron> CGALCache::get(const std::string &id) const
{
const CGAL_Nef_polyhedron &N = *this->cache[id];
const shared_ptr<const CGAL_Nef_polyhedron> &N = this->cache[id]->N;
#ifdef DEBUG
PRINTB("CGAL Cache hit: %s (%d bytes)", id.substr(0, 40) % N.memsize());
PRINTB("CGAL Cache hit: %s (%d bytes)", id.substr(0, 40) % (N ? N->memsize() : 0));
#endif
return N;
}
bool CGALCache::insert(const std::string &id, const CGAL_Nef_polyhedron &N)
bool CGALCache::insert(const std::string &id, const shared_ptr<const CGAL_Nef_polyhedron> &N)
{
bool inserted = this->cache.insert(id, new CGAL_Nef_polyhedron(N), N.memsize());
bool inserted = this->cache.insert(id, new cache_entry(N), N ? N->memsize() : 0);
#ifdef DEBUG
if (inserted) PRINTB("CGAL Cache insert: %s (%d bytes)", id.substr(0, 40) % N.memsize());
else PRINTB("CGAL Cache insert failed: %s (%d bytes)", id.substr(0, 40) % N.memsize());
if (inserted) PRINTB("CGAL Cache insert: %s (%d bytes)", id.substr(0, 40) % (N ? N->memsize() : 0));
else PRINTB("CGAL Cache insert failed: %s (%d bytes)", id.substr(0, 40) % (N ? N->memsize() : 0));
#endif
return inserted;
}
@ -47,3 +47,9 @@ void CGALCache::print()
PRINTB("CGAL Polyhedrons in cache: %d", this->cache.size());
PRINTB("CGAL cache size in bytes: %d", this->cache.totalCost());
}
CGALCache::cache_entry::cache_entry(const shared_ptr<const CGAL_Nef_polyhedron> &N)
: N(N)
{
if (print_messages_stack.size() > 0) this->msg = print_messages_stack.back();
}

View File

@ -2,6 +2,7 @@
#define CGALCACHE_H_
#include "cache.h"
#include "memory.h"
/*!
*/
@ -13,8 +14,8 @@ public:
static CGALCache *instance() { if (!inst) inst = new CGALCache; return inst; }
bool contains(const std::string &id) const { return this->cache.contains(id); }
const class CGAL_Nef_polyhedron &get(const std::string &id) const;
bool insert(const std::string &id, const CGAL_Nef_polyhedron &N);
shared_ptr<const class CGAL_Nef_polyhedron> get(const std::string &id) const;
bool insert(const std::string &id, const shared_ptr<const CGAL_Nef_polyhedron> &N);
size_t maxSize() const;
void setMaxSize(size_t limit);
void clear();
@ -23,7 +24,14 @@ public:
private:
static CGALCache *inst;
Cache<std::string, CGAL_Nef_polyhedron> cache;
struct cache_entry {
shared_ptr<const CGAL_Nef_polyhedron> N;
std::string msg;
cache_entry(const shared_ptr<const CGAL_Nef_polyhedron> &N);
~cache_entry() { }
};
Cache<std::string, cache_entry> cache;
};
#endif

View File

@ -16,15 +16,15 @@
#include "dxftess.h"
#include "Tree.h"
#include "CGALCache.h"
#include "cgal.h"
#include "cgalutils.h"
#include <CGAL/convex_hull_2.h>
#ifdef NDEBUG
#define PREV_NDEBUG NDEBUG
#undef NDEBUG
#endif
#include <CGAL/convex_hull_3.h>
#ifdef PREV_NDEBUG
#define NDEBUG PREV_NDEBUG
#endif
@ -40,7 +40,7 @@
#include <boost/bind.hpp>
#include <map>
CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const AbstractNode &node)
shared_ptr<const CGAL_Nef_polyhedron> CGALEvaluator::evaluateCGALMesh(const AbstractNode &node)
{
if (!isCached(node)) {
Traverser evaluate(*this, node, Traverser::PRE_AND_POSTFIX);
@ -57,12 +57,12 @@ bool CGALEvaluator::isCached(const AbstractNode &node) const
/*!
*/
CGAL_Nef_polyhedron CGALEvaluator::applyToChildren(const AbstractNode &node, OpenSCADOperator op)
CGAL_Nef_polyhedron *CGALEvaluator::applyToChildren(const AbstractNode &node, OpenSCADOperator op)
{
CGAL_Nef_polyhedron N;
CGAL_Nef_polyhedron *N = new CGAL_Nef_polyhedron;
BOOST_FOREACH(const ChildItem &item, this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const CGAL_Nef_polyhedron &chN = item.second;
const shared_ptr<const CGAL_Nef_polyhedron> chN = item.second;
// FIXME: Don't use deep access to modinst members
if (chnode->modinst->isBackground()) continue;
@ -74,94 +74,93 @@ CGAL_Nef_polyhedron CGALEvaluator::applyToChildren(const AbstractNode &node, Ope
CGALCache::instance()->insert(this->tree.getIdString(*chnode), chN);
}
// Initialize N on first iteration with first expected geometric object
if (N.isNull() && !N.isEmpty()) N = chN.copy();
else CGAL_binary_operator(N, chN, op);
if (chN) {
if (N->isNull() && !N->isEmpty()) *N = chN->copy();
else CGALUtils::applyBinaryOperator(*N, *chN, op);
}
chnode->progress_report();
}
return N;
}
CGAL_Nef_polyhedron CGALEvaluator::applyHull(const CgaladvNode &node)
const CGAL_Nef_polyhedron *CGALEvaluator::applyHull(const CgaladvNode &node)
{
CGAL_Nef_polyhedron N;
std::list<CGAL_Nef_polyhedron2*> polys;
std::list<CGAL_Nef_polyhedron2::Point> points2d;
std::list<CGAL_Polyhedron::Vertex::Point_3> points3d;
int dim = 0;
unsigned int dim = 0;
BOOST_FOREACH(const ChildItem &item, this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const CGAL_Nef_polyhedron &chN = item.second;
// FIXME: Don't use deep access to modinst members
if (chnode->modinst->isBackground()) continue;
if (chN.getDimension() == 0) continue; // Ignore object with dimension 0 (e.g. echo)
if (dim == 0) {
dim = chN.getDimension();
if (!dim) {
dim = item.second->getDimension();
if (dim) break;
}
else if (dim != chN.getDimension()) {
PRINT("WARNING: hull() does not support mixing 2D and 3D objects.");
continue;
}
if (chN.isNull()) { // If one of the children evaluated to a null object
continue;
}
if (dim == 2) {
CGAL_Nef_polyhedron2::Explorer explorer = chN.p2->explorer();
}
CGAL_Nef_polyhedron *N = NULL;
if (dim == 2) {
std::list<CGAL_Nef_polyhedron2*> polys;
std::list<CGAL_Nef_polyhedron2::Point> points2d;
std::list<CGAL_Polyhedron::Vertex::Point_3> points3d;
BOOST_FOREACH(const ChildItem &item, this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const shared_ptr<const CGAL_Nef_polyhedron> chN = item.second;
// FIXME: Don't use deep access to modinst members
if (chnode->modinst->isBackground()) continue;
if (chN->getDimension() == 0) continue; // Ignore object with dimension 0 (e.g. echo)
if (dim != chN->getDimension()) {
PRINT("WARNING: hull() does not support mixing 2D and 3D objects.");
continue;
}
if (chN->isNull()) { // If one of the children evaluated to a null object
continue;
}
CGAL_Nef_polyhedron2::Explorer explorer = chN->p2->explorer();
BOOST_FOREACH(const CGAL_Nef_polyhedron2::Explorer::Vertex &vh,
std::make_pair(explorer.vertices_begin(), explorer.vertices_end())) {
if (explorer.is_standard(&vh)) {
points2d.push_back(explorer.point(&vh));
}
}
chnode->progress_report();
}
else if (dim == 3) {
CGAL_Polyhedron P;
if (!chN.p3->is_simple()) {
PRINT("Hull() currently requires a valid 2-manifold. Please modify your design. See http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/STL_Import_and_Export");
}
else {
bool err = false;
std::string errmsg("");
try {
err = nefworkaround::convert_to_Polyhedron<CGAL_Kernel3>( *(chN.p3), P );
//chN.p3->convert_to_Polyhedron(P);
} catch (const CGAL::Failure_exception &e) {
err = true;
errmsg = std::string(e.what());
}
if (err) {
PRINTB("ERROR: CGAL NefPolyhedron->Polyhedron conversion failed. %s", errmsg);
} else {
std::transform(P.vertices_begin(), P.vertices_end(), std::back_inserter(points3d),
boost::bind(static_cast<const CGAL_Polyhedron::Vertex::Point_3&(CGAL_Polyhedron::Vertex::*)() const>(&CGAL_Polyhedron::Vertex::point), _1));
}
}
}
chnode->progress_report();
}
if (dim == 2) {
std::list<CGAL_Nef_polyhedron2::Point> result;
CGAL::convex_hull_2(points2d.begin(), points2d.end(),std:: back_inserter(result));
N = CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron2(result.begin(), result.end(),
CGAL_Nef_polyhedron2::INCLUDED));
N = new CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron2(result.begin(), result.end(),
CGAL_Nef_polyhedron2::INCLUDED));
}
else if (dim == 3) {
Geometry::ChildList children;
BOOST_FOREACH(const ChildItem &item, this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const shared_ptr<const CGAL_Nef_polyhedron> chN = item.second;
// FIXME: Don't use deep access to modinst members
if (chnode->modinst->isBackground()) continue;
if (chN->getDimension() == 0) continue; // Ignore object with dimension 0 (e.g. echo)
if (dim == 0) {
dim = chN->getDimension();
}
else if (dim != chN->getDimension()) {
PRINT("WARNING: hull() does not support mixing 2D and 3D objects.");
continue;
}
if (chN->isNull()) { // If one of the children evaluated to a null object
continue;
}
children.push_back(std::make_pair(chnode, chN));
}
CGAL_Polyhedron P;
if (points3d.size()>3)
CGAL::convex_hull_3(points3d.begin(), points3d.end(), P);
N = CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron3(P));
if (CGALUtils::applyHull(children, P)) {
N = new CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron3(P));
}
}
return N;
}
CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node)
const CGAL_Nef_polyhedron *CGALEvaluator::applyResize(const CgaladvNode &node)
{
// Based on resize() in Giles Bathgate's RapCAD (but not exactly)
CGAL_Nef_polyhedron N;
N = applyToChildren(node, OPENSCAD_UNION);
CGAL_Nef_polyhedron *N = applyToChildren(node, OPENSCAD_UNION);
if ( N.isNull() || N.isEmpty() ) return N;
if (N->isNull() || N->isEmpty()) return N;
for (int i=0;i<3;i++) {
if (node.newsize[i]<0) {
@ -172,15 +171,15 @@ CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node)
CGAL_Iso_cuboid_3 bb;
if ( N.getDimension() == 2 ) {
CGAL_Iso_rectangle_2e bbox = bounding_box( *N.p2 );
if (N->getDimension() == 2) {
CGAL_Iso_rectangle_2e bbox = bounding_box(*N->p2);
CGAL_Point_2e min2(bbox.min()), max2(bbox.max());
CGAL_Point_3 min3(CGAL::to_double(min2.x()), CGAL::to_double(min2.y()), 0),
max3(CGAL::to_double(max2.x()), CGAL::to_double(max2.y()), 0);
bb = CGAL_Iso_cuboid_3( min3, max3 );
}
else {
bb = bounding_box( *N.p3 );
bb = bounding_box(*N->p3);
}
std::vector<NT3> scale, bbox_size;
@ -189,7 +188,7 @@ CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node)
bbox_size.push_back( bb.ymax()-bb.ymin() );
bbox_size.push_back( bb.zmax()-bb.zmin() );
int newsizemax_index = 0;
for (int i=0;i<N.getDimension();i++) {
for (int i=0;i<N->getDimension();i++) {
if (node.newsize[i]) {
if (bbox_size[i]==NT3(0)) {
PRINT("WARNING: Resize in direction normal to flat object is not implemented");
@ -206,7 +205,7 @@ CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node)
NT3 autoscale = NT3( 1 );
if ( node.newsize[ newsizemax_index ] != 0 )
autoscale = NT3( node.newsize[ newsizemax_index ] ) / bbox_size[ newsizemax_index ];
for (int i=0;i<N.getDimension();i++) {
for (int i=0;i<N->getDimension();i++) {
if (node.autosize[i] && node.newsize[i]==0)
scale[i] = autoscale;
}
@ -217,7 +216,7 @@ CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node)
0, 0, CGAL::to_double(scale[2]), 0,
0, 0, 0, 1;
N.transform( Transform3d( t ) );
N->transform( Transform3d( t ) );
return N;
}
@ -234,8 +233,8 @@ Response CGALEvaluator::visit(State &state, const AbstractNode &node)
{
if (state.isPrefix() && isCached(node)) return PruneTraversal;
if (state.isPostfix()) {
CGAL_Nef_polyhedron N;
if (!isCached(node)) N = applyToChildren(node, OPENSCAD_UNION);
shared_ptr<const CGAL_Nef_polyhedron> N;
if (!isCached(node)) N.reset(applyToChildren(node, OPENSCAD_UNION));
else N = CGALCache::instance()->get(this->tree.getIdString(node));
addToParent(state, node, N);
}
@ -246,8 +245,8 @@ Response CGALEvaluator::visit(State &state, const AbstractIntersectionNode &node
{
if (state.isPrefix() && isCached(node)) return PruneTraversal;
if (state.isPostfix()) {
CGAL_Nef_polyhedron N;
if (!isCached(node)) N = applyToChildren(node, OPENSCAD_INTERSECTION);
shared_ptr<const CGAL_Nef_polyhedron> N;
if (!isCached(node)) N.reset(applyToChildren(node, OPENSCAD_INTERSECTION));
else N = CGALCache::instance()->get(this->tree.getIdString(node));
addToParent(state, node, N);
}
@ -258,13 +257,9 @@ Response CGALEvaluator::visit(State &state, const CsgNode &node)
{
if (state.isPrefix() && isCached(node)) return PruneTraversal;
if (state.isPostfix()) {
CGAL_Nef_polyhedron N;
if (!isCached(node)) {
N = applyToChildren(node, node.type);
}
else {
N = CGALCache::instance()->get(this->tree.getIdString(node));
}
shared_ptr<const CGAL_Nef_polyhedron> N;
if (!isCached(node)) N.reset(applyToChildren(node, node.type));
else N = CGALCache::instance()->get(this->tree.getIdString(node));
addToParent(state, node, N);
}
return ContinueTraversal;
@ -274,16 +269,19 @@ Response CGALEvaluator::visit(State &state, const TransformNode &node)
{
if (state.isPrefix() && isCached(node)) return PruneTraversal;
if (state.isPostfix()) {
CGAL_Nef_polyhedron N;
shared_ptr<const CGAL_Nef_polyhedron> N;
if (!isCached(node)) {
// First union all children
N = applyToChildren(node, OPENSCAD_UNION);
if ( matrix_contains_infinity( node.matrix ) || matrix_contains_nan( node.matrix ) ) {
CGAL_Nef_polyhedron *tmpN = applyToChildren(node, OPENSCAD_UNION);
if (matrix_contains_infinity(node.matrix) || matrix_contains_nan(node.matrix)) {
// due to the way parse/eval works we can't currently distinguish between NaN and Inf
PRINT("Warning: Transformation matrix contains Not-a-Number and/or Infinity - removing object.");
N.reset();
}
N.transform( node.matrix );
else {
tmpN->transform(node.matrix);
N.reset(tmpN);
}
}
else {
N = CGALCache::instance()->get(this->tree.getIdString(node));
@ -300,7 +298,7 @@ Response CGALEvaluator::visit(State &state, const AbstractPolyNode &node)
{
if (state.isPrefix() && isCached(node)) return PruneTraversal;
if (state.isPostfix()) {
CGAL_Nef_polyhedron N;
shared_ptr<const CGAL_Nef_polyhedron> N;
if (!isCached(node)) {
// Apply polyset operation
shared_ptr<const Geometry> geom = this->geomevaluator.evaluateGeometry(node, true);
@ -309,7 +307,7 @@ Response CGALEvaluator::visit(State &state, const AbstractPolyNode &node)
if (!Nptr) {
Nptr.reset(createNefPolyhedronFromGeometry(*geom));
}
N = *Nptr;
N = Nptr;
}
node.progress_report();
}
@ -325,13 +323,13 @@ Response CGALEvaluator::visit(State &state, const CgaladvNode &node)
{
if (state.isPrefix() && isCached(node)) return PruneTraversal;
if (state.isPostfix()) {
CGAL_Nef_polyhedron N;
shared_ptr<const CGAL_Nef_polyhedron> N;
if (!isCached(node)) {
OpenSCADOperator op;
switch (node.type) {
case MINKOWSKI:
op = OPENSCAD_MINKOWSKI;
N = applyToChildren(node, op);
N.reset(applyToChildren(node, op));
break;
case GLIDE:
PRINT("WARNING: glide() is not implemented yet!");
@ -342,10 +340,10 @@ Response CGALEvaluator::visit(State &state, const CgaladvNode &node)
return PruneTraversal;
break;
case HULL:
N = applyHull(node);
N.reset(applyHull(node));
break;
case RESIZE:
N = applyResize(node);
N.reset(applyResize(node));
break;
}
}
@ -361,7 +359,9 @@ Response CGALEvaluator::visit(State &state, const CgaladvNode &node)
Adds ourself to out parent's list of traversed children.
Call this for _every_ node which affects output during the postfix traversal.
*/
void CGALEvaluator::addToParent(const State &state, const AbstractNode &node, const CGAL_Nef_polyhedron &N)
void CGALEvaluator::addToParent(const State &state,
const AbstractNode &node,
const shared_ptr<const CGAL_Nef_polyhedron> &N)
{
assert(state.isPostfix());
this->visitedchildren.erase(node.index());

View File

@ -24,24 +24,24 @@ public:
virtual Response visit(State &state, const AbstractPolyNode &node);
virtual Response visit(State &state, const CgaladvNode &node);
CGAL_Nef_polyhedron evaluateCGALMesh(const AbstractNode &node);
shared_ptr<const CGAL_Nef_polyhedron> evaluateCGALMesh(const AbstractNode &node);
const Tree &getTree() const { return this->tree; }
private:
void addToParent(const State &state, const AbstractNode &node, const CGAL_Nef_polyhedron &N);
void addToParent(const State &state, const AbstractNode &node, const shared_ptr<const CGAL_Nef_polyhedron> &N);
bool isCached(const AbstractNode &node) const;
void process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, OpenSCADOperator op);
CGAL_Nef_polyhedron applyToChildren(const AbstractNode &node, OpenSCADOperator op);
CGAL_Nef_polyhedron applyHull(const CgaladvNode &node);
CGAL_Nef_polyhedron applyResize(const CgaladvNode &node);
CGAL_Nef_polyhedron *applyToChildren(const AbstractNode &node, OpenSCADOperator op);
const CGAL_Nef_polyhedron *applyHull(const CgaladvNode &node);
const CGAL_Nef_polyhedron *applyResize(const CgaladvNode &node);
typedef std::pair<const AbstractNode *, CGAL_Nef_polyhedron> ChildItem;
typedef std::pair<const AbstractNode *, shared_ptr<const CGAL_Nef_polyhedron> > ChildItem;
typedef std::list<ChildItem> ChildList;
std::map<int, ChildList> visitedchildren;
const Tree &tree;
CGAL_Nef_polyhedron root;
shared_ptr<const CGAL_Nef_polyhedron> root;
public:
// FIXME: Do we need to make this visible? Used for cache management
// Note: psevaluator constructor needs this->tree to be initialized first

View File

@ -3,11 +3,17 @@
#include <stddef.h>
#include <string>
#include <list>
#include "linalg.h"
#include "memory.h"
class Geometry
{
public:
typedef std::pair<const class AbstractNode *, shared_ptr<const Geometry> > ChildItem;
typedef std::list<ChildItem> ChildList;
Geometry() : convexity(1) {}
virtual ~Geometry() {}

View File

@ -28,7 +28,6 @@
#include <boost/foreach.hpp>
#include <CGAL/convex_hull_2.h>
#include <CGAL/convex_hull_3.h>
GeometryEvaluator::GeometryEvaluator(const class Tree &tree):
tree(tree)
@ -96,7 +95,7 @@ shared_ptr<const Geometry> GeometryEvaluator::evaluateGeometry(const AbstractNod
Geometry *GeometryEvaluator::applyToChildren(const AbstractNode &node, OpenSCADOperator op)
{
unsigned int dim = 0;
BOOST_FOREACH(const ChildItem &item, this->visitedchildren[node.index()]) {
BOOST_FOREACH(const Geometry::ChildItem &item, this->visitedchildren[node.index()]) {
if (item.second) {
if (!dim) dim = item.second->getDimension();
else if (dim != item.second->getDimension()) {
@ -115,8 +114,28 @@ Geometry *GeometryEvaluator::applyToChildren3D(const AbstractNode &node, OpenSCA
return applyHull3D(node);
}
Geometry::ChildList children = collectChildren3D(node);
CGAL_Nef_polyhedron *N = new CGAL_Nef_polyhedron;
BOOST_FOREACH(const ChildItem &item, this->visitedchildren[node.index()]) {
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));
}
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);
}
item.first->progress_report();
}
/*
CGAL_Nef_polyhedron *N = new CGAL_Nef_polyhedron;
BOOST_FOREACH(const Geometry::ChildItem &item, this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const shared_ptr<const Geometry> &chgeom = item.second;
// FIXME: Don't use deep access to modinst members
@ -138,7 +157,7 @@ Geometry *GeometryEvaluator::applyToChildren3D(const AbstractNode &node, OpenSCA
if (chgeom->getDimension() == 3) {
// Initialize N on first iteration with first expected geometric object
if (N->isNull() && !N->isEmpty()) *N = chN->copy();
else CGAL_binary_operator(*N, *chN, op);
else CGALUtils::applyBinaryOperator(*N, *chN, op);
}
else {
// FIXME: Fix error message
@ -147,11 +166,12 @@ Geometry *GeometryEvaluator::applyToChildren3D(const AbstractNode &node, OpenSCA
}
chnode->progress_report();
}
*/
return N;
}
Geometry *GeometryEvaluator::applyHull2D(const AbstractNode &node)
Polygon2d *GeometryEvaluator::applyHull2D(const AbstractNode &node)
{
std::vector<const Polygon2d *> children = collectChildren2D(node);
Polygon2d *geometry = NULL;
@ -183,45 +203,16 @@ Geometry *GeometryEvaluator::applyHull2D(const AbstractNode &node)
Geometry *GeometryEvaluator::applyHull3D(const AbstractNode &node)
{
std::vector<const Geometry *> children = collectChildren3D(node);
Geometry::ChildList children = collectChildren3D(node);
// Collect point cloud
std::list<CGAL_Polyhedron::Vertex::Point_3> points;
CGAL_Polyhedron P;
BOOST_FOREACH(const Geometry *geometry, children) {
const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(geometry);
if (N) {
if (!N->p3->is_simple()) {
PRINT("Hull() currently requires a valid 2-manifold. Please modify your design. See http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/STL_Import_and_Export");
}
else {
N->p3->convert_to_Polyhedron(P);
std::transform(P.vertices_begin(), P.vertices_end(), std::back_inserter(points),
boost::bind(static_cast<const CGAL_Polyhedron::Vertex::Point_3&(CGAL_Polyhedron::Vertex::*)() const>(&CGAL_Polyhedron::Vertex::point), _1));
}
}
else {
const PolySet *ps = dynamic_cast<const PolySet *>(geometry);
BOOST_FOREACH(const PolySet::Polygon &p, ps->polygons) {
BOOST_FOREACH(const Vector3d &v, p) {
points.push_back(CGAL_Polyhedron::Vertex::Point_3(v[0], v[1], v[2]));
}
}
}
}
if (points.size() > 0) {
// Apply hull
CGAL_Polyhedron P;
if (points.size() > 3) {
CGAL::convex_hull_3(points.begin(), points.end(), P);
}
if (CGALUtils::applyHull(children, P)) {
return new CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron3(P));
}
return NULL;
}
Geometry *GeometryEvaluator::applyMinkowski2D(const AbstractNode &node)
Polygon2d *GeometryEvaluator::applyMinkowski2D(const AbstractNode &node)
{
std::vector<const Polygon2d *> children = collectChildren2D(node);
if (children.size() > 0) {
@ -249,10 +240,10 @@ Geometry *GeometryEvaluator::applyMinkowski2D(const AbstractNode &node)
return NULL;
}
std::vector<const Polygon2d *> GeometryEvaluator::collectChildren2D(const AbstractNode &node)
std::vector<const class Polygon2d *> GeometryEvaluator::collectChildren2D(const AbstractNode &node)
{
std::vector<const Polygon2d *> children;
BOOST_FOREACH(const ChildItem &item, this->visitedchildren[node.index()]) {
BOOST_FOREACH(const Geometry::ChildItem &item, this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const shared_ptr<const Geometry> &chgeom = item.second;
// FIXME: Don't use deep access to modinst members
@ -285,10 +276,10 @@ void GeometryEvaluator::smartCache(const AbstractNode &node,
{
// Since we can generate both Nef and non-Nef geometry, we need to insert it into
// the appropriate cache
const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(geom.get());
shared_ptr<const CGAL_Nef_polyhedron> N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(geom);
if (N) {
if (!CGALCache::instance()->contains(this->tree.getIdString(node))) {
CGALCache::instance()->insert(this->tree.getIdString(node), *N);
CGALCache::instance()->insert(this->tree.getIdString(node), N);
}
}
else {
@ -300,10 +291,10 @@ void GeometryEvaluator::smartCache(const AbstractNode &node,
}
}
std::vector<const Geometry *> GeometryEvaluator::collectChildren3D(const AbstractNode &node)
Geometry::ChildList GeometryEvaluator::collectChildren3D(const AbstractNode &node)
{
std::vector<const Geometry *> children;
BOOST_FOREACH(const ChildItem &item, this->visitedchildren[node.index()]) {
Geometry::ChildList children;
BOOST_FOREACH(const Geometry::ChildItem &item, this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const shared_ptr<const Geometry> &chgeom = item.second;
// FIXME: Don't use deep access to modinst members
@ -317,7 +308,7 @@ std::vector<const Geometry *> GeometryEvaluator::collectChildren3D(const Abstrac
if (chgeom) {
if (chgeom->getDimension() == 3) {
children.push_back(chgeom.get());
children.push_back(item);
}
else {
PRINT("ERROR: Only 3D children are supported by this operation!");
@ -330,7 +321,7 @@ std::vector<const Geometry *> GeometryEvaluator::collectChildren3D(const Abstrac
/*!
*/
Geometry *GeometryEvaluator::applyToChildren2D(const AbstractNode &node, OpenSCADOperator op)
Polygon2d *GeometryEvaluator::applyToChildren2D(const AbstractNode &node, OpenSCADOperator op)
{
if (op == OPENSCAD_MINKOWSKI) {
return applyMinkowski2D(node);
@ -341,7 +332,7 @@ Geometry *GeometryEvaluator::applyToChildren2D(const AbstractNode &node, OpenSCA
ClipperLib::Clipper sumclipper;
bool first = true;
BOOST_FOREACH(const ChildItem &item, this->visitedchildren[node.index()]) {
BOOST_FOREACH(const Geometry::ChildItem &item, this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const shared_ptr<const Geometry> &chgeom = item.second;
// FIXME: Don't use deep access to modinst members
@ -837,7 +828,7 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
if (!node.cut_mode) {
ClipperLib::Clipper sumclipper;
BOOST_FOREACH(const ChildItem &item, this->visitedchildren[node.index()]) {
BOOST_FOREACH(const Geometry::ChildItem &item, this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const shared_ptr<const Geometry> &chgeom = item.second;
// FIXME: Don't use deep access to modinst members
@ -907,7 +898,7 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
Nptr = createNefPolyhedronFromGeometry(*geometry);
}
if (!Nptr->isNull()) {
CGAL_Nef_polyhedron nef_poly = CGAL_project(*Nptr, node.cut_mode);
CGAL_Nef_polyhedron nef_poly = CGALUtils::project(*Nptr, node.cut_mode);
Polygon2d *poly = nef_poly.convertToPolygon2d();
assert(poly);
poly->setConvexity(node.convexity);

View File

@ -4,6 +4,7 @@
#include "visitor.h"
#include "enums.h"
#include "memory.h"
#include "Geometry.h"
#include <utility>
#include <list>
@ -16,8 +17,8 @@ public:
GeometryEvaluator(const class Tree &tree);
virtual ~GeometryEvaluator() {}
shared_ptr<const class Geometry> getGeometry(const AbstractNode &node, bool cache);
shared_ptr<const class Geometry> evaluateGeometry(const AbstractNode &node, bool allownef);
shared_ptr<const Geometry> getGeometry(const AbstractNode &node, bool cache);
shared_ptr<const Geometry> evaluateGeometry(const AbstractNode &node, bool allownef);
virtual Response visit(State &state, const AbstractNode &node);
virtual Response visit(State &state, const AbstractPolyNode &node);
@ -36,18 +37,16 @@ private:
bool isCached(const AbstractNode &node) const;
void smartCache(const AbstractNode &node, const shared_ptr<const Geometry> &geom);
std::vector<const class Polygon2d *> collectChildren2D(const AbstractNode &node);
std::vector<const class Geometry *> collectChildren3D(const AbstractNode &node);
Geometry *applyMinkowski2D(const AbstractNode &node);
Geometry *applyHull2D(const AbstractNode &node);
Geometry::ChildList collectChildren3D(const AbstractNode &node);
Polygon2d *applyMinkowski2D(const AbstractNode &node);
Polygon2d *applyHull2D(const AbstractNode &node);
Geometry *applyHull3D(const AbstractNode &node);
Geometry *applyToChildren2D(const AbstractNode &node, OpenSCADOperator op);
Polygon2d *applyToChildren2D(const AbstractNode &node, OpenSCADOperator op);
Geometry *applyToChildren3D(const AbstractNode &node, OpenSCADOperator op);
Geometry *applyToChildren(const AbstractNode &node, OpenSCADOperator op);
void addToParent(const State &state, const AbstractNode &node, const shared_ptr<const Geometry> &geom);
typedef std::pair<const AbstractNode *, shared_ptr<const Geometry> > ChildItem;
typedef std::list<ChildItem> ChildList;
std::map<int, ChildList> visitedchildren;
std::map<int, Geometry::ChildList> visitedchildren;
const Tree &tree;
shared_ptr<const Geometry> root;

View File

@ -12,6 +12,175 @@
#include <map>
#include <boost/foreach.hpp>
namespace CGALUtils {
bool applyHull(const Geometry::ChildList &children, CGAL_Polyhedron &result)
{
// Collect point cloud
std::list<CGAL_Polyhedron::Vertex::Point_3> points;
CGAL_Polyhedron P;
BOOST_FOREACH(const Geometry::ChildItem &item, children) {
const shared_ptr<const Geometry> &chgeom = item.second;
const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(chgeom.get());
if (N) {
if (!N->p3->is_simple()) {
PRINT("Hull() currently requires a valid 2-manifold. Please modify your design. See http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/STL_Import_and_Export");
}
else {
N->p3->convert_to_Polyhedron(P);
std::transform(P.vertices_begin(), P.vertices_end(), std::back_inserter(points),
boost::bind(static_cast<const CGAL_Polyhedron::Vertex::Point_3&(CGAL_Polyhedron::Vertex::*)() const>(&CGAL_Polyhedron::Vertex::point), _1));
}
}
else {
const PolySet *ps = dynamic_cast<const PolySet *>(chgeom.get());
BOOST_FOREACH(const PolySet::Polygon &p, ps->polygons) {
BOOST_FOREACH(const Vector3d &v, p) {
points.push_back(CGAL_Polyhedron::Vertex::Point_3(v[0], v[1], v[2]));
}
}
}
}
if (points.size() > 0) {
// Apply hull
if (points.size() > 3) {
CGAL::convex_hull_3(points.begin(), points.end(), result);
return true;
}
}
return false;
}
/*!
Modifies target by applying op to target and src:
target = target [op] src
*/
void applyBinaryOperator(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, OpenSCADOperator op)
{
if (target.getDimension() != 2 && target.getDimension() != 3) {
assert(false && "Dimension of Nef polyhedron must be 2 or 3");
}
if (src.isEmpty()) return; // Empty polyhedron. This can happen for e.g. square([0,0])
if (target.isEmpty() && op != OPENSCAD_UNION) return; // empty op <something> => empty
if (target.getDimension() != src.getDimension()) return; // If someone tries to e.g. union 2d and 3d objects
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
switch (op) {
case OPENSCAD_UNION:
if (target.isEmpty()) target = src.copy();
else target += src;
break;
case OPENSCAD_INTERSECTION:
target *= src;
break;
case OPENSCAD_DIFFERENCE:
target -= src;
break;
case OPENSCAD_MINKOWSKI:
target.minkowski(src);
break;
default:
PRINTB("ERROR: Unsupported CGAL operator: %d", op);
}
}
catch (const CGAL::Failure_exception &e) {
// union && difference assert triggered by testdata/scad/bugs/rotate-diff-nonmanifold-crash.scad and testdata/scad/bugs/issue204.scad
std::string opstr = op == OPENSCAD_UNION ? "union" : op == OPENSCAD_INTERSECTION ? "intersection" : op == OPENSCAD_DIFFERENCE ? "difference" : op == OPENSCAD_MINKOWSKI ? "minkowski" : "UNKNOWN";
PRINTB("CGAL error in CGAL_Nef_polyhedron's %s operator: %s", opstr % e.what());
// Errors can result in corrupt polyhedrons, so put back the old one
target = src;
}
CGAL::set_error_behaviour(old_behaviour);
}
CGAL_Nef_polyhedron project(const CGAL_Nef_polyhedron &N, bool cut)
{
logstream log(5);
CGAL_Nef_polyhedron nef_poly(2);
if (N.getDimension() != 3) return nef_poly;
CGAL_Nef_polyhedron newN;
if (cut) {
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
CGAL_Nef_polyhedron3::Plane_3 xy_plane = CGAL_Nef_polyhedron3::Plane_3(0,0,1,0);
newN.p3.reset(new CGAL_Nef_polyhedron3(N.p3->intersection(xy_plane, CGAL_Nef_polyhedron3::PLANE_ONLY)));
}
catch (const CGAL::Failure_exception &e) {
PRINTB("CGAL error in projection node during plane intersection: %s", e.what());
try {
PRINT("Trying alternative intersection using very large thin box: ");
std::vector<CGAL_Point_3> pts;
// dont use z of 0. there are bugs in CGAL.
double inf = 1e8;
double eps = 0.001;
CGAL_Point_3 minpt( -inf, -inf, -eps );
CGAL_Point_3 maxpt( inf, inf, eps );
CGAL_Iso_cuboid_3 bigcuboid( minpt, maxpt );
for ( int i=0;i<8;i++ ) pts.push_back( bigcuboid.vertex(i) );
CGAL_Polyhedron bigbox;
CGAL::convex_hull_3(pts.begin(), pts.end(), bigbox);
CGAL_Nef_polyhedron3 nef_bigbox( bigbox );
newN.p3.reset(new CGAL_Nef_polyhedron3(nef_bigbox.intersection(*N.p3)));
}
catch (const CGAL::Failure_exception &e) {
PRINTB("CGAL error in projection node during bigbox intersection: %s", e.what());
}
}
if (!newN.p3 || newN.p3->is_empty()) {
CGAL::set_error_behaviour(old_behaviour);
PRINT("WARNING: projection() failed.");
return nef_poly;
}
log << OpenSCAD::svg_header( 480, 100000 ) << "\n";
try {
ZRemover zremover;
CGAL_Nef_polyhedron3::Volume_const_iterator i;
CGAL_Nef_polyhedron3::Shell_entry_const_iterator j;
CGAL_Nef_polyhedron3::SFace_const_handle sface_handle;
for ( i = newN.p3->volumes_begin(); i != newN.p3->volumes_end(); ++i ) {
log << "<!-- volume. mark: " << i->mark() << " -->\n";
for ( j = i->shells_begin(); j != i->shells_end(); ++j ) {
log << "<!-- shell. mark: " << i->mark() << " -->\n";
sface_handle = CGAL_Nef_polyhedron3::SFace_const_handle( j );
newN.p3->visit_shell_objects( sface_handle , zremover );
log << "<!-- shell. end. -->\n";
}
log << "<!-- volume end. -->\n";
}
nef_poly.p2 = zremover.output_nefpoly2d;
} catch (const CGAL::Failure_exception &e) {
PRINTB("CGAL error in projection node while flattening: %s", e.what());
}
log << "</svg>\n";
CGAL::set_error_behaviour(old_behaviour);
}
// In projection mode all the triangles are projected manually into the XY plane
else {
PolySet *ps3 = N.convertToPolyset();
if (!ps3) return nef_poly;
const Polygon2d *poly = PolysetUtils::project(*ps3);
// FIXME: Convert back to Nef2 and delete poly?
/* if (nef_poly.isEmpty()) {
nef_poly.p2.reset(new CGAL_Nef_polyhedron2(plist.begin(), plist.end(), CGAL_Nef_polyhedron2::INCLUDED));
}
else {
(*nef_poly.p2) += CGAL_Nef_polyhedron2(plist.begin(), plist.end(), CGAL_Nef_polyhedron2::INCLUDED);
}
*/
delete ps3;
}
return nef_poly;
}
};
bool createPolySetFromPolyhedron(const CGAL_Polyhedron &p, PolySet &ps)
{
bool err = false;
@ -517,131 +686,5 @@ CGAL_Nef_polyhedron *createNefPolyhedronFromGeometry(const Geometry &geom)
return NULL;
}
/*!
Modifies target by applying op to target and src:
target = target [op] src
*/
void CGAL_binary_operator(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, OpenSCADOperator op)
{
if (target.getDimension() != 2 && target.getDimension() != 3) {
assert(false && "Dimension of Nef polyhedron must be 2 or 3");
}
if (src.isEmpty()) return; // Empty polyhedron. This can happen for e.g. square([0,0])
if (target.isEmpty() && op != OPENSCAD_UNION) return; // empty op <something> => empty
if (target.getDimension() != src.getDimension()) return; // If someone tries to e.g. union 2d and 3d objects
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
switch (op) {
case OPENSCAD_UNION:
if (target.isEmpty()) target = src.copy();
else target += src;
break;
case OPENSCAD_INTERSECTION:
target *= src;
break;
case OPENSCAD_DIFFERENCE:
target -= src;
break;
case OPENSCAD_MINKOWSKI:
target.minkowski(src);
break;
}
}
catch (const CGAL::Failure_exception &e) {
// union && difference assert triggered by testdata/scad/bugs/rotate-diff-nonmanifold-crash.scad and testdata/scad/bugs/issue204.scad
std::string opstr = op == OPENSCAD_UNION ? "union" : op == OPENSCAD_INTERSECTION ? "intersection" : op == OPENSCAD_DIFFERENCE ? "difference" : op == OPENSCAD_MINKOWSKI ? "minkowski" : "UNKNOWN";
PRINTB("CGAL error in CGAL_Nef_polyhedron's %s operator: %s", opstr % e.what());
// Errors can result in corrupt polyhedrons, so put back the old one
target = src;
}
CGAL::set_error_behaviour(old_behaviour);
}
CGAL_Nef_polyhedron CGAL_project(const CGAL_Nef_polyhedron &N, bool cut)
{
logstream log(5);
CGAL_Nef_polyhedron nef_poly(2);
if (N.getDimension() != 3) return nef_poly;
CGAL_Nef_polyhedron newN;
if (cut) {
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
CGAL_Nef_polyhedron3::Plane_3 xy_plane = CGAL_Nef_polyhedron3::Plane_3(0,0,1,0);
newN.p3.reset(new CGAL_Nef_polyhedron3(N.p3->intersection(xy_plane, CGAL_Nef_polyhedron3::PLANE_ONLY)));
}
catch (const CGAL::Failure_exception &e) {
PRINTB("CGAL error in projection node during plane intersection: %s", e.what());
try {
PRINT("Trying alternative intersection using very large thin box: ");
std::vector<CGAL_Point_3> pts;
// dont use z of 0. there are bugs in CGAL.
double inf = 1e8;
double eps = 0.001;
CGAL_Point_3 minpt( -inf, -inf, -eps );
CGAL_Point_3 maxpt( inf, inf, eps );
CGAL_Iso_cuboid_3 bigcuboid( minpt, maxpt );
for ( int i=0;i<8;i++ ) pts.push_back( bigcuboid.vertex(i) );
CGAL_Polyhedron bigbox;
CGAL::convex_hull_3(pts.begin(), pts.end(), bigbox);
CGAL_Nef_polyhedron3 nef_bigbox( bigbox );
newN.p3.reset(new CGAL_Nef_polyhedron3(nef_bigbox.intersection(*N.p3)));
}
catch (const CGAL::Failure_exception &e) {
PRINTB("CGAL error in projection node during bigbox intersection: %s", e.what());
}
}
if (!newN.p3 || newN.p3->is_empty()) {
CGAL::set_error_behaviour(old_behaviour);
PRINT("WARNING: projection() failed.");
return nef_poly;
}
log << OpenSCAD::svg_header( 480, 100000 ) << "\n";
try {
ZRemover zremover;
CGAL_Nef_polyhedron3::Volume_const_iterator i;
CGAL_Nef_polyhedron3::Shell_entry_const_iterator j;
CGAL_Nef_polyhedron3::SFace_const_handle sface_handle;
for ( i = newN.p3->volumes_begin(); i != newN.p3->volumes_end(); ++i ) {
log << "<!-- volume. mark: " << i->mark() << " -->\n";
for ( j = i->shells_begin(); j != i->shells_end(); ++j ) {
log << "<!-- shell. mark: " << i->mark() << " -->\n";
sface_handle = CGAL_Nef_polyhedron3::SFace_const_handle( j );
newN.p3->visit_shell_objects( sface_handle , zremover );
log << "<!-- shell. end. -->\n";
}
log << "<!-- volume end. -->\n";
}
nef_poly.p2 = zremover.output_nefpoly2d;
} catch (const CGAL::Failure_exception &e) {
PRINTB("CGAL error in projection node while flattening: %s", e.what());
}
log << "</svg>\n";
CGAL::set_error_behaviour(old_behaviour);
}
// In projection mode all the triangles are projected manually into the XY plane
else {
PolySet *ps3 = N.convertToPolyset();
if (!ps3) return nef_poly;
const Polygon2d *poly = PolysetUtils::project(*ps3);
// FIXME: Convert back to Nef2 and delete poly?
/* if (nef_poly.isEmpty()) {
nef_poly.p2.reset(new CGAL_Nef_polyhedron2(plist.begin(), plist.end(), CGAL_Nef_polyhedron2::INCLUDED));
}
else {
(*nef_poly.p2) += CGAL_Nef_polyhedron2(plist.begin(), plist.end(), CGAL_Nef_polyhedron2::INCLUDED);
}
*/
delete ps3;
}
return nef_poly;
}
#endif /* ENABLE_CGAL */

View File

@ -6,15 +6,18 @@
#include "CGAL_Nef_polyhedron.h"
#include "enums.h"
namespace CGALUtils {
bool applyHull(const Geometry::ChildList &children, CGAL_Polyhedron &P);
void applyBinaryOperator(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, OpenSCADOperator op);
CGAL_Nef_polyhedron project(const CGAL_Nef_polyhedron &N, bool cut);
};
CGAL_Nef_polyhedron *createNefPolyhedronFromGeometry(const class Geometry &geom);
bool createPolySetFromPolyhedron(const CGAL_Polyhedron &p, PolySet &ps);
bool createPolyhedronFromPolySet(const PolySet &ps, CGAL_Polyhedron &p);
CGAL_Iso_cuboid_3 bounding_box( const CGAL_Nef_polyhedron3 &N );
CGAL_Iso_rectangle_2e bounding_box( const CGAL_Nef_polyhedron2 &N );
void CGAL_binary_operator(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, OpenSCADOperator op);
CGAL_Nef_polyhedron CGAL_project(const CGAL_Nef_polyhedron &N, bool cut);
#include "svg.h"
#include "printutils.h"

View File

@ -28,10 +28,10 @@ void CGALWorker::start(const Tree &tree)
void CGALWorker::work()
{
CGAL_Nef_polyhedron *root_N = NULL;
shared_ptr<const CGAL_Nef_polyhedron> root_N;
try {
GeometryEvaluator evaluator(*this->tree);
root_N = new CGAL_Nef_polyhedron(evaluator.cgalevaluator->evaluateCGALMesh(*this->tree->root()));
root_N = evaluator.cgalevaluator->evaluateCGALMesh(*this->tree->root());
}
catch (const ProgressCancelException &e) {
PRINT("Rendering cancelled.");

View File

@ -2,6 +2,7 @@
#define CGALWORKER_H_
#include <QObject>
#include "memory.h"
class CGALWorker : public QObject
{
@ -17,7 +18,7 @@ protected slots:
void work();
signals:
void done(class CGAL_Nef_polyhedron *);
void done(shared_ptr<const class CGAL_Nef_polyhedron>);
protected:

View File

@ -37,7 +37,7 @@
Saves the current 3D CGAL Nef polyhedron as STL to the given file.
The file must be open.
*/
void export_stl(CGAL_Nef_polyhedron *root_N, std::ostream &output)
void export_stl(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
{
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
@ -125,7 +125,7 @@ void export_stl(CGAL_Nef_polyhedron *root_N, std::ostream &output)
CGAL::set_error_behaviour(old_behaviour);
}
void export_off(CGAL_Nef_polyhedron *root_N, std::ostream &output)
void export_off(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
{
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
@ -142,7 +142,7 @@ void export_off(CGAL_Nef_polyhedron *root_N, std::ostream &output)
/*!
Saves the current 2D CGAL Nef polyhedron as DXF to the given absolute filename.
*/
void export_dxf(CGAL_Nef_polyhedron *root_N, std::ostream &output)
void export_dxf(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
{
setlocale(LC_NUMERIC, "C"); // Ensure radix is . (not ,) in output
// Some importers (e.g. Inkscape) needs a BLOCKS section to be present

View File

@ -7,10 +7,10 @@
#ifdef ENABLE_CGAL
void export_stl(class CGAL_Nef_polyhedron *root_N, std::ostream &output);
void export_off(CGAL_Nef_polyhedron *root_N, std::ostream &output);
void export_dxf(CGAL_Nef_polyhedron *root_N, std::ostream &output);
void export_png_with_cgal(CGAL_Nef_polyhedron *root_N, Camera &c, std::ostream &output);
void export_stl(const class CGAL_Nef_polyhedron *root_N, 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_with_opencsg(Tree &tree, Camera &c, std::ostream &output);
void export_png_with_throwntogether(Tree &tree, Camera &c, std::ostream &output);

View File

@ -11,7 +11,7 @@
#include "CGAL_renderer.h"
#include "cgal.h"
void export_png_with_cgal(CGAL_Nef_polyhedron *root_N, Camera &cam, std::ostream &output)
void export_png_with_cgal(const CGAL_Nef_polyhedron *root_N, Camera &cam, std::ostream &output)
{
OffscreenView *glview;
try {

View File

@ -47,7 +47,6 @@
#ifdef ENABLE_CGAL
#include "CGAL_Nef_polyhedron.h"
#include "CGALEvaluator.h"
#include "PolySetCGALEvaluator.h"
#endif
#include "csgterm.h"
@ -250,7 +249,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;
CGAL_Nef_polyhedron root_N;
shared_ptr<const CGAL_Nef_polyhedron> root_N;
handle_dep(filename.c_str());
@ -359,11 +358,11 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
}
if (stl_output_file) {
if (root_N.getDimension() != 3) {
if (root_N->getDimension() != 3) {
PRINT("Current top level object is not a 3D object.\n");
return 1;
}
if (!root_N.p3->is_simple()) {
if (!root_N->p3->is_simple()) {
PRINT("Object isn't a valid 2-manifold! Modify your design.\n");
return 1;
}
@ -372,17 +371,17 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
PRINTB("Can't open file \"%s\" for export", stl_output_file);
}
else {
export_stl(&root_N, fstream);
export_stl(root_N.get(), fstream);
fstream.close();
}
}
if (off_output_file) {
if (root_N.getDimension() != 3) {
if (root_N->getDimension() != 3) {
PRINT("Current top level object is not a 3D object.\n");
return 1;
}
if (!root_N.p3->is_simple()) {
if (!root_N->p3->is_simple()) {
PRINT("Object isn't a valid 2-manifold! Modify your design.\n");
return 1;
}
@ -391,13 +390,13 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
PRINTB("Can't open file \"%s\" for export", off_output_file);
}
else {
export_off(&root_N, fstream);
export_off(root_N.get(), fstream);
fstream.close();
}
}
if (dxf_output_file) {
if (root_N.getDimension() != 2) {
if (root_N->getDimension() != 2) {
PRINT("Current top level object is not a 2D object.\n");
return 1;
}
@ -406,7 +405,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, fstream);
export_dxf(root_N.get(), fstream);
fstream.close();
}
}
@ -418,7 +417,7 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
}
else {
if (renderer==Render::CGAL) {
export_png_with_cgal(&root_N, camera, fstream);
export_png_with_cgal(root_N.get(), camera, fstream);
} else if (renderer==Render::THROWNTOGETHER) {
export_png_with_throwntogether(tree, camera, fstream);
} else {

View File

@ -581,7 +581,6 @@ set(CGAL_SOURCES
../src/cgalutils.cc
../src/CGALEvaluator.cc
../src/CGALCache.cc
../src/PolySetCGALEvaluator.cc
../src/CGAL_Nef_polyhedron_DxfData.cc
../src/cgaladv_minkowski2.cc
../src/Polygon2d-CGAL.cc
@ -591,7 +590,6 @@ set(CGAL_SOURCES
set(COMMON_SOURCES
../src/nodedumper.cc
../src/traverser.cc
../src/PolySetEvaluator.cc
../src/GeometryCache.cc
../src/clipper-utils.cc
../src/polyclipping/clipper.cpp

View File

@ -149,9 +149,9 @@ int main(int argc, char **argv)
print_messages_push();
std::cout << "First evaluation:\n";
CGAL_Nef_polyhedron N = geomevaluator.cgalevaluator->evaluateCGALMesh(*root_node);
shared_ptr<const CGAL_Nef_polyhedron> N = geomevaluator.cgalevaluator->evaluateCGALMesh(*root_node);
std::cout << "Second evaluation:\n";
CGAL_Nef_polyhedron N2 = geomevaluator.cgalevaluator->evaluateCGALMesh(*root_node);
shared_ptr<const CGAL_Nef_polyhedron> N2 = geomevaluator.cgalevaluator->evaluateCGALMesh(*root_node);
// FIXME:
// Evaluate again to make cache kick in
// Record printed output and compare it