projection: fallback to 'large thin box' if intersection with plane fails.

also implement SVG debugging output for 2d + 3d Nef Polyhedrons.
felipesanches-svg
don bright 2012-10-15 20:17:12 -05:00
parent 65fc1d6b01
commit 56def4aef2
6 changed files with 396 additions and 70 deletions

View File

@ -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;

View File

@ -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

View File

@ -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>
typedef CGAL_Nef_polyhedron3::Point_3 Point_3;
/*
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.
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

View File

@ -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

View File

@ -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 */

View File

@ -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