mirror of https://github.com/vitalif/openscad
projection: fallback to 'large thin box' if intersection with plane fails.
also implement SVG debugging output for 2d + 3d Nef Polyhedrons.felipesanches-svg
parent
65fc1d6b01
commit
56def4aef2
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
297
src/cgalutils.cc
297
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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue