diff options
author | don bright <hugh.m.bright@gmail.com> | 2012-10-16 01:17:12 (GMT) |
---|---|---|
committer | don bright <hugh.m.bright@gmail.com> | 2012-10-16 01:17:12 (GMT) |
commit | 56def4aef228564ea4abcc06d4873c961921cf7d (patch) | |
tree | 5374210ab104604af37eae51af1341b5d7792b02 | |
parent | 65fc1d6b01ade5e76fe712f93e2e108194c3291b (diff) |
projection: fallback to 'large thin box' if intersection with plane fails.
also implement SVG debugging output for 2d + 3d Nef Polyhedrons.
-rw-r--r-- | src/CGAL_Nef_polyhedron.h | 3 | ||||
-rw-r--r-- | src/CGAL_Nef_polyhedron_DxfData.cc | 40 | ||||
-rw-r--r-- | src/PolySetCGALEvaluator.cc | 120 | ||||
-rw-r--r-- | src/cgal.h | 2 | ||||
-rw-r--r-- | src/cgalutils.cc | 297 | ||||
-rw-r--r-- | src/cgalutils.h | 4 |
6 files changed, 396 insertions, 70 deletions
diff --git a/src/CGAL_Nef_polyhedron.h b/src/CGAL_Nef_polyhedron.h index 694b420..3157ff2 100644 --- a/src/CGAL_Nef_polyhedron.h +++ b/src/CGAL_Nef_polyhedron.h @@ -20,7 +20,8 @@ public: CGAL_Nef_polyhedron &operator-=(const CGAL_Nef_polyhedron &other); CGAL_Nef_polyhedron &minkowski(const CGAL_Nef_polyhedron &other); CGAL_Nef_polyhedron copy() const; - std::string dump_p2() const; + std::string dump_svg() const; + std::string dump() const; int weight() const; class PolySet *convertToPolyset(); class DxfData *convertToDxfData() const; diff --git a/src/CGAL_Nef_polyhedron_DxfData.cc b/src/CGAL_Nef_polyhedron_DxfData.cc index 411a340..922a7ec 100644 --- a/src/CGAL_Nef_polyhedron_DxfData.cc +++ b/src/CGAL_Nef_polyhedron_DxfData.cc @@ -28,6 +28,7 @@ #include "grid.h" #include "CGAL_Nef_polyhedron.h" #include "cgal.h" +#include "cgalutils.h" #ifdef ENABLE_CGAL @@ -77,29 +78,24 @@ DxfData *CGAL_Nef_polyhedron::convertToDxfData() const return dxfdata; } -// dump the 2 dimensional nef_poly. -std::string CGAL_Nef_polyhedron::dump_p2() const +std::string CGAL_Nef_polyhedron::dump() const { - std::stringstream out; - CGAL_Nef_polyhedron2::Explorer explorer = this->p2->explorer(); - CGAL_Nef_polyhedron2::Explorer::Vertex_const_iterator i; - out << "CGAL_Nef_polyhedron::p2 Vertices"; - for (i = explorer.vertices_begin(); i != explorer.vertices_end(); ++i) { - if ( explorer.is_standard( i ) ) { - CGAL_Nef_polyhedron2::Explorer::Point point = explorer.point( i ); - out << "\n Point x y: " - << CGAL::to_double(point.x()) << " " - << CGAL::to_double(point.y()); - } else { - CGAL_Nef_polyhedron2::Explorer::Ray ray = explorer.ray( i ); - CGAL_Nef_polyhedron2::Explorer::Point point = ray.point( 0 ); - out << "\n Ray x y dx dy: " - << CGAL::to_double(point.x()) << " " << CGAL::to_double(point.y()) << " " - << CGAL::to_double(ray.direction().dx()) << " " << CGAL::to_double(ray.direction().dy()); - } - } - out << "\nCGAL_Nef_polyhedron::p2 Vertices end"; - return out.str(); + if (this->dim==2) + return dump_cgal_nef_polyhedron2( *this->p2 ); + else if (this->dim==3) + return dump_cgal_nef_polyhedron3( *this->p3 ); + else + return std::string("Nef Polyhedron with dimension != 2 or 3"); +} + +std::string CGAL_Nef_polyhedron::dump_svg() const +{ + if (this->dim==2) + return dump_cgal_nef_polyhedron2_svg( *this->p2 ); + else if (this->dim==3) + return dump_cgal_nef_polyhedron3_svg( *this->p3 ); + else + return std::string("<svg><!--Nef Polyhedron with dimension != 2 or 3--></svg>"); } #endif // ENABLE_CGAL diff --git a/src/PolySetCGALEvaluator.cc b/src/PolySetCGALEvaluator.cc index bca9902..19f5325 100644 --- a/src/PolySetCGALEvaluator.cc +++ b/src/PolySetCGALEvaluator.cc @@ -1,6 +1,7 @@ #include "PolySetCGALEvaluator.h" #include "cgal.h" #include "cgalutils.h" +#include <CGAL/convex_hull_3.h> #include "polyset.h" #include "CGALEvaluator.h" #include "projectionnode.h" @@ -15,33 +16,23 @@ #include "printutils.h" #include "openscad.h" // get_fragments_from_r() #include <boost/foreach.hpp> +#include <vector> -/* - -This Visitor is used in the 'cut' process. Essentially, one or more of -our 3d nef polyhedrons have been 'cut' by the xy-plane, forming a number -of polygons that are essentially 'flat'. This Visitor object, when -called repeatedly, collects those flat polygons together and forms a new -2d nef polyhedron out of them. It keeps track of the 'holes' so that -in the final resulting polygon, they are preserved properly. +typedef CGAL_Nef_polyhedron3::Point_3 Point_3; -The output polygon is stored in the output_nefpoly2d variable. +/* -For more information on 3d + 2d nef polyhedrons, facets, halffacets, -facet cycles, etc, please see these websites: +This class converts multiple 3d-CGAL Nef polyhedrons into a single 2d by +stripping off the z coordinate of each face vertex and doing unions and +intersections. It uses the 'visitor' pattern from the CGAL manual. +Output is in the 'output_nefpoly2d' variable. +See also http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Nef_3/Chapter_main.html -http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Nef_3_ref/Class_Nef_polyhedron_3-Traits---Halffacet.html - -The halffacet iteration 'circulator' code is based on OGL_helper.h - -Why do we throw out all 'down' half-facets? Imagine a triangle in 3d -space - it has one 'half face' for one 'side' and another 'half face' for the -other 'side'. If we iterated over both half-faces we would get the same vertex -coordinates twice. Instead, we only need one side, in our case, we -chose the 'up' side. +http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Nef_3_ref/Class_Nef_polyhedron3.html +OGL_helper.h */ -class NefShellVisitor_for_cut { +class Flattener { public: std::stringstream out; CGAL_Nef_polyhedron2::Boundary boundary; @@ -49,7 +40,7 @@ public: shared_ptr<CGAL_Nef_polyhedron2> output_nefpoly2d; CGAL::Direction_3<CGAL_Kernel3> up; bool debug; - NefShellVisitor_for_cut(bool debug=false) + Flattener(bool debug=false) { output_nefpoly2d.reset( new CGAL_Nef_polyhedron2() ); boundary = CGAL_Nef_polyhedron2::INCLUDED; @@ -67,11 +58,11 @@ public: void visit( CGAL_Nef_polyhedron3::SFace_const_handle ) {} void visit( CGAL_Nef_polyhedron3::Halffacet_const_handle hfacet ) { if ( hfacet->plane().orthogonal_direction() != this->up ) { - if (debug) out << "down facing half-facet. skipping\n"; + out << "\ndown facing half-facet. skipping\n"; return; } - int numcontours = 0; + int contour_counter = 0; CGAL_Nef_polyhedron3::Halffacet_cycle_const_iterator i; CGAL_forall_facet_cycles_of( i, hfacet ) { CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c1(i), c2(c1); @@ -82,14 +73,18 @@ public: contour.push_back( point2d ); } tmpnef2d.reset( new CGAL_Nef_polyhedron2( contour.begin(), contour.end(), boundary ) ); - if ( numcontours == 0 ) { - if (debug) out << " contour is a body. make union(). " << contour.size() << " points.\n" ; - *output_nefpoly2d += *tmpnef2d; + if ( contour_counter == 0 ) { + if (debug) out << "\ncontour is a body. make union(). " << contour.size() << " points.\n" ; + *(output_nefpoly2d) += *(tmpnef2d); } else { - if (debug) out << " contour is a hole. make intersection(). " << contour.size() << " points.\n"; - *output_nefpoly2d *= *tmpnef2d; + *(output_nefpoly2d) *= *(tmpnef2d); + if (debug) out << "\ncontour is a hole. make intersection(). " << contour.size() << " points.\n"; } - numcontours++; + out << "\n------- tmp: -------\n"; + if (debug) out << dump_cgal_nef_polyhedron2( *tmpnef2d ); + out << "\n------- output accumulator: -------\n"; + if (debug) out << dump_cgal_nef_polyhedron2( *output_nefpoly2d ); + contour_counter++; } // next facet cycle (i.e. next contour) } // visit() }; @@ -120,39 +115,74 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node) } } + // std::cout << "----- input dump \n" << sum.dump_svg() << "\n"; + CGAL_Nef_polyhedron nef_poly; if (node.cut_mode) { CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION); + bool plane_intersect_fail = false; try { - // intersect 'sum' with the x-y plane CGAL_Nef_polyhedron3::Plane_3 xy_plane = CGAL_Nef_polyhedron3::Plane_3( 0,0,1,0 ); *sum.p3 = sum.p3->intersection( xy_plane, CGAL_Nef_polyhedron3::PLANE_ONLY); - - // Visit each polygon in sum.p3 and union/intersect into a 2d polygon (with holes) - // For info on Volumes, Shells, Facets, and the 'visitor' pattern, please see - // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Nef_3/Chapter_main.html - NefShellVisitor_for_cut shell_visitor; + } + catch (const CGAL::Failure_exception &e) { + PRINTB("CGAL error in projection node during plane intersection: %s", e.what()); + plane_intersect_fail = true; + } + if (plane_intersect_fail) { + try { + PRINT("Trying alternative intersection using very large thin box: "); + double inf = 1e8, eps = 0.1; + double x1 = -inf, x2 = +inf, y1 = -inf, y2 = +inf, z1 = 0, z2 = eps; + + std::vector<Point_3> pts; + pts.push_back( Point_3( x1, y1, z1 ) ); + pts.push_back( Point_3( x1, y2, z1 ) ); + pts.push_back( Point_3( x2, y2, z1 ) ); + pts.push_back( Point_3( x2, y1, z1 ) ); + pts.push_back( Point_3( x1, y1, z2 ) ); + pts.push_back( Point_3( x1, y2, z2 ) ); + pts.push_back( Point_3( x2, y2, z2 ) ); + pts.push_back( Point_3( x2, y1, z2 ) ); + + CGAL_Polyhedron bigbox; + CGAL::convex_hull_3( pts.begin(), pts.end(), bigbox ); + CGAL_Nef_polyhedron3 nef_bigbox( bigbox ); + *sum.p3 = nef_bigbox.intersection( *sum.p3 ); + } + catch (const CGAL::Failure_exception &e) { + PRINTB("CGAL error in projection node during bigbox intersection: %s", e.what()); + // fixme , can we just return empty polyset? + CGAL::set_error_behaviour(old_behaviour); + return NULL; + } + } + + // remove z coordinates to make CGAL_Nef_polyhedron2 + try { + Flattener flattener(true); 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 = sum.p3->volumes_begin(); i != sum.p3->volumes_end(); ++i ) { for ( j = i->shells_begin(); j != i->shells_end(); ++j ) { sface_handle = CGAL_Nef_polyhedron3::SFace_const_handle( j ); - sum.p3->visit_shell_objects( sface_handle , shell_visitor ); + sum.p3->visit_shell_objects( sface_handle , flattener ); } } - if (debug) std::cout << "shell visitor\n" << shell_visitor.dump() << "\nshell visitor end\n"; - - nef_poly.p2 = shell_visitor.output_nefpoly2d; + + std::cout << "------- flattener dump \n" << flattener.dump() << "\n"; + nef_poly.p2 = flattener.output_nefpoly2d; nef_poly.dim = 2; - if (debug) std::cout << "--\n" << nef_poly.dump_p2() << "\n"; - } - catch (const CGAL::Failure_exception &e) { - PRINTB("CGAL error in projection node: %s", e.what()); - return NULL; + } catch (const CGAL::Failure_exception &e) { + PRINTB("CGAL error in projection node while flattening: %s", e.what()); } + CGAL::set_error_behaviour(old_behaviour); + + std::cout << "------- 3d cut dump \n" << sum.dump_svg() << "\n"; + std::cout << "------- 2d output dump \n" << nef_poly.dump_svg() << "\n"; // 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 @@ -54,6 +54,8 @@ typedef CGAL::Polyhedron_3<CGAL_Kernel3> CGAL_Polyhedron; typedef CGAL_Polyhedron::HalfedgeDS CGAL_HDS; typedef CGAL::Polyhedron_incremental_builder_3<CGAL_HDS> CGAL_Polybuilder; +typedef CGAL::Cartesian<NT>::Iso_cuboid_3 CGAL_Iso_cuboid_3; + #ifdef PREV_NDEBUG #define NDEBUG PREV_NDEBUG #endif diff --git a/src/cgalutils.cc b/src/cgalutils.cc index e402139..7ae6d7b 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -3,9 +3,11 @@ #include "cgalutils.h" #include "polyset.h" #include "printutils.h" - #include "cgal.h" - +#include <CGAL/bounding_box.h> +typedef CGAL::Point_3<CGAL_Kernel3> CGAL_Point_3; +typedef CGAL::Point_2<CGAL_Kernel2> CGAL_Point_2; +#include <boost/algorithm/string.hpp> #include <map> PolySet *createPolySetFromPolyhedron(const CGAL_Polyhedron &p) @@ -145,5 +147,296 @@ CGAL_Polyhedron *createPolyhedronFromPolySet(const PolySet &ps) return P; } + + + +CGAL::Point project_svg3( CGAL_Point_3 p, CGAL_Iso_cuboid_3 bbox ) +{ + // do extremely simple fake isometric projection, based on bounding box + double x = CGAL::to_double( p.x() ); + double y = CGAL::to_double( p.y() ); + double z = CGAL::to_double( p.z() ); + double screenw = 480; + double screenh = 480; + double xcenter = screenw / 2; + double ycenter = screenh / 2; + double xdist = ( 2 * CGAL::to_double( bbox.xmax() - bbox.xmin() ) ); + double ydist = ( 2 * CGAL::to_double( bbox.ymax() - bbox.ymin() ) ); + double zdist = ( 2 * CGAL::to_double( bbox.zmax() - bbox.zmin() ) ); + double xscale = (xdist==0) ? 1 : screenw / (xdist * 1.618); + double yscale = (ydist==0) ? 1 : screenh / (ydist * 1.618 * 3); + double zscale = (zdist==0) ? 1 : screenh / (zdist * 1.618); + double tx = xcenter + x * xscale + y * yscale; + double ty = ycenter - z * zscale - y * yscale; + return CGAL::Point( tx, ty, 0 ); +} + +CGAL::Point project_svg2( CGAL::Point p, CGAL_Iso_cuboid_3 bbox ) +{ + CGAL_Point_3 pnew( p.x(), 0, p.y() ); + return project_svg3( pnew, bbox ); +} + +// for debugging, not necessarily pretty or useful for users. +std::string dump_cgal_nef_polyhedron2_face_svg( + CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c1, + CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c2, + CGAL_Nef_polyhedron2::Explorer explorer ) +{ + std::stringstream out; + CGAL_For_all(c1, c2) { + if ( explorer.is_standard( explorer.target(c1) ) ) { + CGAL_Nef_polyhedron2::Explorer::Point source = explorer.point( explorer.source( c1 ) ); + CGAL_Nef_polyhedron2::Explorer::Point target = explorer.point( explorer.target( c1 ) ); + CGAL::Point tp1 = project_svg2( source ); + CGAL::Point tp2 = project_svg2( target ); + out << " <line" + << " x1='" << CGAL::to_double(tp1.x()) << "'" + << " x2='" << CGAL::to_double(tp1.y()) << "'" + << " y1='" << CGAL::to_double(tp2.x()) << "'" + << " y2='" << CGAL::to_double(tp2.y()) << "'" + << " stroke='red' />\n"; + } + } + return out.str(); +} + +std::string dump_cgal_nef_polyhedron2_svg( const CGAL_Nef_polyhedron2 &N ) +{ + std::stringstream out; + CGAL_Nef_polyhedron2::Explorer explorer = N.explorer(); + CGAL_Nef_polyhedron2::Explorer::Face_const_iterator i; + out << "<svg width='480px' height='480px' xmlns='http://www.w3.org/2000/svg' version='1.1'>\n"; + out << "<polyline points='0,0 480,0 480,480 0,480' style='fill:none;stroke:black' />\n"; + out << "<polyline points='10,455 10,475 10,465 18,465 2,465 10,465 14,461 6,469 10,465' style='fill:none;stroke:black;' />"; + for ( i = explorer.faces_begin(); i!= explorer.faces_end(); ++i ) { + CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c1 + = explorer.face_cycle( i ), c2 ( c1 ); + out << dump_cgal_nef_polyhedron2_face_svg( c1, c2, explorer ); + +/* + holes not implemented + CGAL_Nef_polyhedron2::Explorer::Hole_const_iterator j; + for ( j = explorer.holes_begin( i ); j!= explorer.holes_end( i ); ++j ) { + CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c3( j ), c4 ( c3 ); + out << dump_cgal_nef_polyhedron2_face_svg( c3, c4, explorer ); + } +*/ + } + out << "</svg>"; + std::string tmp = out.str(); + boost::replace_all( tmp, "'", "\"" ); + return tmp; +} + + +std::string dump_cgal_nef_polyhedron2_face( + CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c1, + CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c2, + CGAL_Nef_polyhedron2::Explorer explorer ) +{ + std::stringstream out; + CGAL_For_all(c1, c2) { + out << " On frame edge:" << explorer.is_frame_edge( c1 ); + out << " Mark: " << explorer.mark( c1 ); + if ( explorer.is_standard( explorer.target(c1) ) ) { + CGAL_Nef_polyhedron2::Explorer::Point source = explorer.point( explorer.source( c1 ) ); + CGAL_Nef_polyhedron2::Explorer::Point target = explorer.point( explorer.target( c1 ) ); + out << " Halfedge x y x2 y2: " + << CGAL::to_double(source.x()) << " " + << CGAL::to_double(source.y()) << " " + << CGAL::to_double(target.x()) << " " + << CGAL::to_double(target.y()) << "\n"; + } else { + CGAL_Nef_polyhedron2::Explorer::Ray ray = explorer.ray( explorer.target( c1 ) ); + out << " Ray x y dx dy: " + << CGAL::to_double(ray.point(0).x()) << " " + << CGAL::to_double(ray.point(0).y()) << " " + << CGAL::to_double(ray.point(1).x()) << " " + << CGAL::to_double(ray.point(1).y()) << "\n"; + } + } + return out.str(); +} + +std::string dump_cgal_nef_polyhedron2( const CGAL_Nef_polyhedron2 &N ) +{ + std::stringstream out; + CGAL_Nef_polyhedron2::Explorer explorer = N.explorer(); + CGAL_Nef_polyhedron2::Explorer::Face_const_iterator i; + out << "CGAL_Nef_polyhedron2 dump begin\n"; + for ( i = explorer.faces_begin(); i!= explorer.faces_end(); ++i ) { + out << " Face body:\n"; + CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c1 + = explorer.face_cycle( i ), c2 ( c1 ); + out << dump_cgal_nef_polyhedron2_face( c1, c2, explorer ); + + CGAL_Nef_polyhedron2::Explorer::Hole_const_iterator j; + for ( j = explorer.holes_begin( i ); j!= explorer.holes_end( i ); ++j ) { + out << " Face hole:\n"; + CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c3( j ), c4 ( c3 ); + out << dump_cgal_nef_polyhedron2_face( c3, c4, explorer ); + } + } + out << "CGAL_Nef_polyhedron2 dump end"; + return out.str(); +} + +// This uses the Shell Explorer pattern from the CGAL Manual to dump the 3d Nef Polyhedron information +// http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Nef_3/Chapter_main.html#Subsection_29.7.2 +class NefPoly3_dumper_svg { +public: + std::stringstream out; + CGAL_Iso_cuboid_3 bbox; + NefPoly3_dumper_svg(const CGAL_Nef_polyhedron3& N) {} + void setbbox( CGAL_Iso_cuboid_3 bbox ) { this->bbox = bbox; } + void visit(CGAL_Nef_polyhedron3::Vertex_const_handle v) {} + void visit(CGAL_Nef_polyhedron3::Halfedge_const_handle ) {} + void visit(CGAL_Nef_polyhedron3::SHalfedge_const_handle ) {} + void visit(CGAL_Nef_polyhedron3::SHalfloop_const_handle shh ){} + void visit(CGAL_Nef_polyhedron3::SFace_const_handle ) {} + void visit( CGAL_Nef_polyhedron3::Halffacet_const_handle hfacet ) + { + int contour_count = 0; + out << " <!-- Halffacet. Mark: " << (*hfacet).mark() << " -->\n"; + CGAL_Nef_polyhedron3::Halffacet_cycle_const_iterator i; + CGAL_forall_facet_cycles_of( i, hfacet ) { + CGAL_Nef_polyhedron3::SHalfloop_const_handle shl_handle; + out << " <!-- Halffacet cycle: -->\n"; + if ( contour_count == 0 ) { + out << " <!-- Body contour:--> \n"; + } else { + out << " <!-- Hole contour:--> \n" ; + } + CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c1(i), c2(c1); + CGAL_For_all( c1, c2 ) { + out << " <line"; + // don't know why we use source()->source(), except thats what CGAL does internally + CGAL_Point_3 source = c1->source()->source()->point(); + CGAL_Point_3 target = c1->source()->target()->point(); + tp1 = project_svg ( source ); + tp2 = project_svg ( target ); + out << " " + << "x1='" << CGAL::to_double(tp1.x()) << "' " + << "y1='" << CGAL::to_double(tp1.y()) << "' " + << "x2='" << CGAL::to_double(tp2.x()) << "' " + << "y2='" << CGAL::to_double(tp2.y()) << "' " + << "stroke='red' />\n"; + } + contour_count++; + } // next facet cycle (i.e. next contour) + } // visit() + +}; + + +std::string dump_cgal_nef_polyhedron3_svg( const CGAL_Nef_polyhedron3 &N ) +{ + std::stringstream out; + out << "<svg width='480px' height='480px' xmlns='http://www.w3.org/2000/svg' version='1.1'>\n"; + out << "<polyline points='0,0 480,0 480,480 0,480' style='fill:none;stroke:black' />\n"; + out << "<polyline points='10,455 10,475 10,465 18,465 2,465 10,465 14,461 6,469 10,465' style='fill:none;stroke:black;' />"; + out << "<!--CGAL_Nef_polyhedron3 dump begin-->\n"; + + std::vector<CGAL_Point_3> points; + CGAL_Nef_polyhedron3::Vertex_const_iterator vi; + for (vi = N.vertices_begin(); vi!=N.vertices_end(); ++vi) + points.push_back( vi->point() ); + CGAL_Iso_cuboid_3 bbox = CGAL::bounding_box( points.begin(), points.end() ); + + CGAL_Nef_polyhedron3::Volume_const_iterator c; + CGAL_forall_volumes(c,N) { + out << " <!--Processing volume...-->\n"; + out << " <!--Mark: " << (*c).mark() << "-->\n"; + CGAL_Nef_polyhedron3::Shell_entry_const_iterator it; + CGAL_forall_shells_of(it,c) { + out << " <!--Processing shell...-->\n"; + NefPoly3_dumper_svg dumper_svg(N); + dumper_svg.setbbox( bbox ); + N.visit_shell_objects(CGAL_Nef_polyhedron3::SFace_const_handle(it), dumper_svg ); + out << dumper_svg.out.str(); + out << " <!--Processing shell end-->\n"; + } + out << " <!--Processing volume end-->\n"; + } + out << "<!--CGAL_Nef_polyhedron3 dump end-->\n"; + out << "</svg>"; + std::string tmp = out.str(); + boost::replace_all( tmp, "'", "\"" ); + return tmp; +} + +// This uses the Shell Explorer pattern from the CGAL Manual to dump the 3d Nef Polyhedron information +// http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Nef_3/Chapter_main.html#Subsection_29.7.2 +class NefPoly3_dumper { +public: + std::stringstream out; + NefPoly3_dumper(const CGAL_Nef_polyhedron3& N) {} + void visit(CGAL_Nef_polyhedron3::Vertex_const_handle v) {} + void visit(CGAL_Nef_polyhedron3::Halfedge_const_handle ) {} + void visit(CGAL_Nef_polyhedron3::SHalfedge_const_handle ) {} + void visit(CGAL_Nef_polyhedron3::SHalfloop_const_handle shh ) + { + out << " SHalfloop visit\n"; + out << " Mark: " << (*shh).mark() << "\n"; + } + void visit(CGAL_Nef_polyhedron3::SFace_const_handle ) {} + void visit( CGAL_Nef_polyhedron3::Halffacet_const_handle hfacet ) + { + int contour_count = 0; + out << " Halffacet visit\n"; + out << " Mark: " << (*hfacet).mark() << "\n"; + CGAL_Nef_polyhedron3::Halffacet_cycle_const_iterator i; + CGAL_forall_facet_cycles_of( i, hfacet ) { + CGAL_Nef_polyhedron3::SHalfloop_const_handle shl_handle; + out << " Halffacet cycle:\n"; + if ( contour_count == 0 ) { + out << " Body contour:\n"; + } else { + out << " Hole contour:\n" ; + } + CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c1(i), c2(c1); + int count=0; + CGAL_For_all( c1, c2 ) { + out << " Halfedge vertex:"; + out << " Mark: " << (*c1).mark(); + count++; + CGAL_Point_3 point3d = c1->source()->source()->point(); + double x = CGAL::to_double( point3d.x() ); + double y = CGAL::to_double( point3d.y() ); + double z = CGAL::to_double( point3d.z() ); + out << " x:" << x << " y:" << y << " z:" << z <<"\n"; + } + out << " point count: " << count << "\n"; + contour_count++; + } // next facet cycle (i.e. next contour) + } // visit() + +}; + +std::string dump_cgal_nef_polyhedron3( const CGAL_Nef_polyhedron3 &N ) +{ + std::stringstream out; + out << "CGAL_Nef_polyhedron3 dump begin\n"; + CGAL_Nef_polyhedron3::Volume_const_iterator c; + CGAL_forall_volumes(c,N) { + out << " Processing volume...\n"; + out << " Mark: " << (*c).mark() << "\n"; + CGAL_Nef_polyhedron3::Shell_entry_const_iterator it; + CGAL_forall_shells_of(it,c) { + out << " Processing shell...\n"; + NefPoly3_dumper dumper(N); + N.visit_shell_objects(CGAL_Nef_polyhedron3::SFace_const_handle(it), dumper ); + out << dumper.out.str(); + out << " Processing shell end\n"; + } + out << " Processing volume end\n"; + } + out << "CGAL_Nef_polyhedron3 dump end\n"; + return out.str(); +} + + + #endif /* ENABLE_CGAL */ diff --git a/src/cgalutils.h b/src/cgalutils.h index a249697..2bf6566 100644 --- a/src/cgalutils.h +++ b/src/cgalutils.h @@ -5,5 +5,9 @@ class PolySet *createPolySetFromPolyhedron(const CGAL_Polyhedron &p); CGAL_Polyhedron *createPolyhedronFromPolySet(const class PolySet &ps); +std::string dump_cgal_nef_polyhedron2( const CGAL_Nef_polyhedron2 &N ); +std::string dump_cgal_nef_polyhedron3( const CGAL_Nef_polyhedron3 &N ); +std::string dump_cgal_nef_polyhedron2_svg( const CGAL_Nef_polyhedron2 &N ); +std::string dump_cgal_nef_polyhedron3_svg( const CGAL_Nef_polyhedron3 &N ); #endif |