summaryrefslogtreecommitdiff
path: root/src/CGALEvaluator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/CGALEvaluator.cc')
-rw-r--r--src/CGALEvaluator.cc129
1 files changed, 72 insertions, 57 deletions
diff --git a/src/CGALEvaluator.cc b/src/CGALEvaluator.cc
index ee04e05..4deb3b3 100644
--- a/src/CGALEvaluator.cc
+++ b/src/CGALEvaluator.cc
@@ -61,14 +61,16 @@ void CGALEvaluator::process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedr
if (target.dim != 2 && target.dim != 3) {
assert(false && "Dimension of Nef polyhedron must be 2 or 3");
}
- if (src.empty()) return; // Empty polyhedron. This can happen for e.g. square([0,0])
+ if (src.isEmpty()) return; // Empty polyhedron. This can happen for e.g. square([0,0])
+ if (target.isEmpty() && op != CGE_UNION) return; // empty op <something> => empty
if (target.dim != src.dim) 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 CGE_UNION:
- target += src;
+ if (target.isEmpty()) target = src.copy();
+ else target += src;
break;
case CGE_INTERSECTION:
target *= src;
@@ -81,15 +83,13 @@ void CGALEvaluator::process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedr
break;
}
}
- catch (CGAL::Failure_exception e) {
- // union && difference assert triggered by testdata/scad/bugs/rotate-diff-nonmanifold-crash.scad
+ 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 == CGE_UNION ? "union" : op == CGE_INTERSECTION ? "intersection" : op == CGE_DIFFERENCE ? "difference" : op == CGE_MINKOWSKI ? "minkowski" : "UNKNOWN";
PRINTB("CGAL error in CGAL_Nef_polyhedron's %s operator: %s", opstr % e.what());
- // Minkowski errors can result in corrupt polyhedrons
- if (op == CGE_MINKOWSKI) {
- target = src;
- }
+ // Errors can result in corrupt polyhedrons, so put back the old one
+ target = src;
}
CGAL::set_error_behaviour(old_behaviour);
}
@@ -112,7 +112,8 @@ CGAL_Nef_polyhedron CGALEvaluator::applyToChildren(const AbstractNode &node, CGA
if (!isCached(*chnode)) {
CGALCache::instance()->insert(this->tree.getIdString(*chnode), chN);
}
- if (N.empty()) N = chN.copy();
+ // Initialize N on first iteration with first expected geometric object
+ if (N.isNull() && !N.isEmpty()) N = chN.copy();
else process(N, chN, op);
chnode->progress_report();
@@ -132,6 +133,7 @@ CGAL_Nef_polyhedron CGALEvaluator::applyHull(const CgaladvNode &node)
const CGAL_Nef_polyhedron &chN = item.second;
// FIXME: Don't use deep access to modinst members
if (chnode->modinst->isBackground()) continue;
+ if (chN.dim == 0) continue; // Ignore object with dimension 0 (e.g. echo)
if (dim == 0) {
dim = chN.dim;
}
@@ -150,9 +152,14 @@ CGAL_Nef_polyhedron CGALEvaluator::applyHull(const CgaladvNode &node)
}
else if (dim == 3) {
CGAL_Polyhedron P;
- chN.p3->convert_to_Polyhedron(P);
- 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));
+ 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 {
+ chN.p3->convert_to_Polyhedron(P);
+ 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();
}
@@ -165,7 +172,8 @@ CGAL_Nef_polyhedron CGALEvaluator::applyHull(const CgaladvNode &node)
}
else if (dim == 3) {
CGAL_Polyhedron P;
- CGAL::convex_hull_3(points3d.begin(), points3d.end(), P);
+ if (points3d.size()>3)
+ CGAL::convex_hull_3(points3d.begin(), points3d.end(), P);
N = CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron3(P));
}
return N;
@@ -240,53 +248,60 @@ Response CGALEvaluator::visit(State &state, const TransformNode &node)
if (!isCached(node)) {
// First union all children
N = applyToChildren(node, CGE_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();
+ }
// Then apply transform
- // If there is no geometry under the transform, N will be empty and of dim 0,
- // just just silently ignore such nodes
- if (N.dim == 2) {
- // Unfortunately CGAL provides no transform method for CGAL_Nef_polyhedron2
- // objects. So we convert in to our internal 2d data format, transform it,
- // tesselate it and create a new CGAL_Nef_polyhedron2 from it.. What a hack!
-
- Eigen::Matrix2f testmat;
- testmat << node.matrix(0,0), node.matrix(0,1), node.matrix(1,0), node.matrix(1,1);
- if (testmat.determinant() == 0) {
- PRINT("Warning: Scaling a 2D object with 0 - removing object");
- N.reset();
- }
- else {
- CGAL_Aff_transformation2 t(
- 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,3));
+ // If there is no geometry under the transform, N will be empty
+ // just silently ignore such nodes
+ if (!N.isNull()) {
+ if (N.dim == 2) {
+ // Unfortunately CGAL provides no transform method for CGAL_Nef_polyhedron2
+ // objects. So we convert in to our internal 2d data format, transform it,
+ // tesselate it and create a new CGAL_Nef_polyhedron2 from it.. What a hack!
- DxfData *dd = N.convertToDxfData();
- for (size_t i=0; i < dd->points.size(); i++) {
- CGAL_Kernel2::Point_2 p = CGAL_Kernel2::Point_2(dd->points[i][0], dd->points[i][1]);
- p = t.transform(p);
- dd->points[i][0] = to_double(p.x());
- dd->points[i][1] = to_double(p.y());
+ Eigen::Matrix2f testmat;
+ testmat << node.matrix(0,0), node.matrix(0,1), node.matrix(1,0), node.matrix(1,1);
+ if (testmat.determinant() == 0) {
+ PRINT("Warning: Scaling a 2D object with 0 - removing object");
+ N.reset();
+ }
+ else {
+ CGAL_Aff_transformation2 t(
+ 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,3));
+
+ DxfData *dd = N.convertToDxfData();
+ for (size_t i=0; i < dd->points.size(); i++) {
+ CGAL_Kernel2::Point_2 p = CGAL_Kernel2::Point_2(dd->points[i][0], dd->points[i][1]);
+ p = t.transform(p);
+ dd->points[i][0] = to_double(p.x());
+ dd->points[i][1] = to_double(p.y());
+ }
+
+ PolySet ps;
+ ps.is2d = true;
+ dxf_tesselate(&ps, *dd, 0, true, false, 0);
+
+ N = evaluateCGALMesh(ps);
+ delete dd;
}
-
- PolySet ps;
- ps.is2d = true;
- dxf_tesselate(&ps, *dd, 0, true, false, 0);
-
- N = evaluateCGALMesh(ps);
- delete dd;
- }
- }
- else if (N.dim == 3) {
- if (node.matrix.matrix().determinant() == 0) {
- PRINT("Warning: Scaling a 3D object with 0 - removing object");
- N.reset();
}
- else {
- CGAL_Aff_transformation t(
- node.matrix(0,0), node.matrix(0,1), node.matrix(0,2), node.matrix(0,3),
- node.matrix(1,0), node.matrix(1,1), node.matrix(1,2), node.matrix(1,3),
- node.matrix(2,0), node.matrix(2,1), node.matrix(2,2), node.matrix(2,3), node.matrix(3,3));
- N.p3->transform(t);
+ else if (N.dim == 3) {
+ if (node.matrix.matrix().determinant() == 0) {
+ PRINT("Warning: Scaling a 3D object with 0 - removing object");
+ N.reset();
+ }
+ else {
+ CGAL_Aff_transformation t(
+ node.matrix(0,0), node.matrix(0,1), node.matrix(0,2), node.matrix(0,3),
+ node.matrix(1,0), node.matrix(1,1), node.matrix(1,2), node.matrix(1,3),
+ node.matrix(2,0), node.matrix(2,1), node.matrix(2,2), node.matrix(2,3), node.matrix(3,3));
+ N.p3->transform(t);
+ }
}
}
}
@@ -377,7 +392,7 @@ void CGALEvaluator::addToParent(const State &state, const AbstractNode &node, co
CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
{
- if (ps.empty()) return CGAL_Nef_polyhedron();
+ if (ps.empty()) return CGAL_Nef_polyhedron(ps.is2d ? 2 : 3);
if (ps.is2d)
{
@@ -637,7 +652,7 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
N = new CGAL_Nef_polyhedron3(*P);
}
}
- catch (CGAL::Assertion_exception e) {
+ catch (const CGAL::Assertion_exception &e) {
PRINTB("CGAL error in CGAL_Nef_polyhedron3(): %s", e.what());
}
CGAL::set_error_behaviour(old_behaviour);
contact: Jan Huwald // Impressum