diff --git a/src/PolySetCGALEvaluator.cc b/src/PolySetCGALEvaluator.cc index 22567f21..c1bdea47 100644 --- a/src/PolySetCGALEvaluator.cc +++ b/src/PolySetCGALEvaluator.cc @@ -39,6 +39,8 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node) ps->convexity = node.convexity; ps->is2d = true; + // In cut mode, the model is intersected by a large but very thin box living on the + // XY plane. if (node.cut_mode) { PolySet cube; @@ -82,8 +84,17 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node) cube.append_vertex(x1, y2, z2); CGAL_Nef_polyhedron Ncube = this->cgalevaluator.evaluateCGALMesh(cube); - // N.p3 *= CGAL_Nef_polyhedron3(CGAL_Plane(0, 0, 1, 0), CGAL_Nef_polyhedron3::INCLUDED); sum *= Ncube; + + // FIXME: Instead of intersecting with a thin volume, we could intersect + // with a plane. This feels like a better solution. However, as the result + // of such an intersection isn't simple, we cannot convert the resulting + // Nef polyhedron to a Polyhedron using convertToPolyset() and we need + // another way of extracting the result. kintel 20120203. +// *sum.p3 = sum.p3->intersection(CGAL_Nef_polyhedron3::Plane_3(0, 0, 1, 0), +// CGAL_Nef_polyhedron3::PLANE_ONLY); + + if (!sum.p3->is_simple()) { PRINT("WARNING: Body of projection(cut = true) isn't valid 2-manifold! Modify your design.."); goto cant_project_non_simple_polyhedron; @@ -91,6 +102,12 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node) PolySet *ps3 = sum.convertToPolyset(); if (!ps3) return NULL; + + // Extract polygons in the XY plane, ignoring all other polygons + // FIXME: If the polyhedron is really thin, there might be unwanted polygons + // in the XY plane, causing the resulting 2D polygon to be self-intersection + // and cause a crash in CGALEvaluator::PolyReducer. The right solution is to + // filter these polygons here. kintel 20120203. Grid2d conversion_grid(GRID_COARSE); for (size_t i = 0; i < ps3->polygons.size(); i++) { for (size_t j = 0; j < ps3->polygons[i].size(); j++) { @@ -114,6 +131,7 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node) } delete ps3; } + // In projection mode all the triangles are projected manually into the XY plane else { if (!sum.p3->is_simple()) { diff --git a/src/export.cc b/src/export.cc index 6dce6990..40ce6cbf 100644 --- a/src/export.cc +++ b/src/export.cc @@ -53,7 +53,6 @@ void export_stl(CGAL_Nef_polyhedron *root_N, std::ostream &output) output << "solid OpenSCAD_Model\n"; - int facet_count = 0; for (FCI fi = P.facets_begin(); fi != P.facets_end(); ++fi) { HFCC hc = fi->facet_begin(); HFCC hc_end = hc; @@ -198,3 +197,20 @@ void export_dxf(CGAL_Nef_polyhedron *root_N, std::ostream &output) #endif +#ifdef DEBUG +#include +void export_stl(const PolySet &ps, std::ostream &output) +{ + output << "solid OpenSCAD_PolySet\n"; + BOOST_FOREACH(const PolySet::Polygon &p, ps.polygons) { + output << "facet\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_PolySet\n"; +} +#endif diff --git a/src/export.h b/src/export.h index 9750c300..3897be04 100644 --- a/src/export.h +++ b/src/export.h @@ -1,13 +1,18 @@ #ifndef EXPORT_H_ #define EXPORT_H_ -#ifdef ENABLE_CGAL - #include +#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); + +#endif + +#ifdef DEBUG +void export_stl(const class PolySet &ps, std::ostream &output); #endif #endif diff --git a/testdata/scad/bugs/projectioncrash.scad b/testdata/scad/bugs/projectioncrash.scad new file mode 100644 index 00000000..532ef8d2 --- /dev/null +++ b/testdata/scad/bugs/projectioncrash.scad @@ -0,0 +1,5 @@ +// This causes OpenSCAD to crash. See source code comments: +// PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node) +// Se also https://github.com/openscad/openscad/issues/80 + +projection(cut=true) translate([0,0,-4.999999]) cube(10, center=true); diff --git a/testdata/scad/features/projection-tests.scad b/testdata/scad/features/projection-tests.scad index e1b05c7a..edb65ba1 100644 --- a/testdata/scad/features/projection-tests.scad +++ b/testdata/scad/features/projection-tests.scad @@ -8,3 +8,6 @@ projection(cut=true) { square(); } linear_extrude(height=20) projection(cut=false) sphere(r=10); translate([22,0,0]) linear_extrude(height=20) projection(cut=true) translate([0,0,9]) sphere(r=10); translate([44,0,0]) linear_extrude(height=20) projection(cut=true) translate([0,0,7]) sphere(r=10); + +// Boundary case: clipping the top of a cube +translate([0,-22,0]) linear_extrude(height=5) projection(cut=true) translate([0,0,-4.999999]) cube(10, center=true);