move transform from CGALEvaluator to Nef_polyhedron - reuse in resize(). also

move ZRemover code to cgalutils, also cleanup SVG code
felipesanches-svg
don bright 2013-03-10 21:35:30 -05:00
parent 33a54b52f2
commit 5559ae9a6a
9 changed files with 200 additions and 236 deletions

View File

@ -185,13 +185,6 @@ CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node)
// Based on resize() in Giles Bathgate's RapCAD
CGAL_Nef_polyhedron N;
N = applyToChildren(node, CGE_UNION);
if (N.isNull()) {
PRINT("WARNING: resize() of null polyhedron");
return N;
}
int dim = N.dim;
if (dim==2) N.convertTo3d();
CGAL_Iso_cuboid_3 bb = bounding_box( *N.p3 );
Eigen::Matrix<NT,3,1> scale, bbox_size;
@ -200,13 +193,18 @@ CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node)
for (int i=0;i<3;i++)
if (node.newsize[i] && bbox_size[i]!=NT(0))
scale[i] = NT(node.newsize[i]) / NT(bbox_size[i]);
CGAL_Aff_transformation t( scale[0], 0, 0, 0,
0, scale[1], 0, 0,
0, 0, scale[2], 0, 1);
N.p3->transform( t );
NT autoscale = scale.maxCoeff();
if (node.autosize)
for (int i=0;i<3;i++)
scale[i] = autoscale;
if (dim==2) N.convertTo2d();
Eigen::Matrix4d t;
t << CGAL::to_double(scale[0]), 0, 0, 0,
0, CGAL::to_double(scale[1]), 0, 0,
0, 0, CGAL::to_double(scale[2]), 0,
0, 0, 0, 1;
N.transform( Transform3d( t ) );
return N;
}
@ -286,56 +284,8 @@ Response CGALEvaluator::visit(State &state, const TransformNode &node)
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
// 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!
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;
}
}
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 {
N.transform( node.matrix );
}
}
else {

View File

@ -4,6 +4,7 @@
#include "cgalfwd.h"
#include "memory.h"
#include <string>
#include "linalg.h"
class CGAL_Nef_polyhedron
{
@ -27,9 +28,7 @@ public:
int weight() const;
class PolySet *convertToPolyset();
class DxfData *convertToDxfData() const;
void convertTo2d();
void convertTo3d();
void transform( const Transform3d &matrix );
int dim;
shared_ptr<CGAL_Nef_polyhedron2> p2;
shared_ptr<CGAL_Nef_polyhedron3> p3;

View File

@ -29,6 +29,11 @@
#include "CGAL_Nef_polyhedron.h"
#include "cgal.h"
#include "cgalutils.h"
#include <boost/variant.hpp>
#include "polyset.h"
#include "dxftess.h"
#include "CGALEvaluator.h"
#include "Tree.h"
#ifdef ENABLE_CGAL
@ -88,85 +93,60 @@ std::string CGAL_Nef_polyhedron::dump() const
return std::string("Nef Polyhedron with dimension != 2 or 3");
}
// use a try/catch block around any calls to this
void CGAL_Nef_polyhedron::convertTo2d()
void CGAL_Nef_polyhedron::transform( const Transform3d &matrix )
{
logstream log(5);
if (dim!=3) return;
assert(this->p3);
ZRemover zremover;
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 = this->p3->volumes_begin(); i != this->p3->volumes_end(); ++i ) {
log << "<!-- volume begin. mark: " << i->mark() << " -->\n";
for ( j = i->shells_begin(); j != i->shells_end(); ++j ) {
log << "<!-- shell. mark: " << i->mark() << " -->\n";
sface_handle = CGAL_Nef_polyhedron3::SFace_const_handle( j );
this->p3->visit_shell_objects( sface_handle , zremover );
log << "<!-- shell. end. -->\n";
if (!this->isNull()) {
if (this->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 << matrix(0,0), matrix(0,1), matrix(1,0), matrix(1,1);
if (testmat.determinant() == 0) {
PRINT("Warning: Scaling a 2D object with 0 - removing object");
this->reset();
}
else {
CGAL_Aff_transformation2 t(
matrix(0,0), matrix(0,1), matrix(0,3),
matrix(1,0), matrix(1,1), matrix(1,3), matrix(3,3));
DxfData *dd = this->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);
Tree nulltree;
CGALEvaluator tmpeval(nulltree);
CGAL_Nef_polyhedron N = tmpeval.evaluateCGALMesh(ps);
this->p2.reset();
*(this->p2) = *(N.p2);
delete dd;
}
}
log << "<!-- volume end. -->\n";
}
this->p3.reset();
this->p2 = zremover.output_nefpoly2d;
this->dim = 2;
}
std::vector<CGAL_Point_3> face2to3(
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::vector<CGAL_Point_3> result;
CGAL_For_all(c1, c2) {
if ( explorer.is_standard( explorer.target(c1) ) ) {
//CGAL_Point_2e source = explorer.point( explorer.source( c1 ) );
CGAL_Point_2e target = explorer.point( explorer.target( c1 ) );
if (c1->mark()) {
CGAL_Point_3 tmp( target.x(), target.y(), 0 );
result.push_back( tmp );
else if (this->dim == 3) {
if (matrix.matrix().determinant() == 0) {
PRINT("Warning: Scaling a 3D object with 0 - removing object");
this->reset();
}
else {
CGAL_Aff_transformation t(
matrix(0,0), matrix(0,1), matrix(0,2), matrix(0,3),
matrix(1,0), matrix(1,1), matrix(1,2), matrix(1,3),
matrix(2,0), matrix(2,1), matrix(2,2), matrix(2,3), matrix(3,3));
this->p3->transform(t);
}
}
}
return result;
}
// use a try/catch block around any calls to this
void CGAL_Nef_polyhedron::convertTo3d()
{
if (dim!=2) return;
assert(this->p2);
CGAL_Nef_polyhedron2::Explorer explorer = this->p2->explorer();
CGAL_Nef_polyhedron2::Explorer::Face_const_iterator i;
this->p3.reset( new CGAL_Nef_polyhedron3() );
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 );
std::vector<CGAL_Point_3> body_pts = face2to3( c1, c2, explorer );
CGAL_Nef_polyhedron3 body( body_pts.begin(), body_pts.end() );
CGAL_Nef_polyhedron3 holes;
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 );
std::vector<CGAL_Point_3> hole_pts = face2to3( c3, c4, explorer );
CGAL_Nef_polyhedron3 hole( hole_pts.begin(), hole_pts.end() );
holes = holes.join( hole );
}
body = body.difference( holes );
*(this->p3) = this->p3->join( body );
}
this->p2.reset();
this->dim = 3;
}
#endif // ENABLE_CGAL

View File

@ -90,8 +90,21 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node)
log << OpenSCAD::svg_header( 480, 100000 ) << "\n";
try {
sum.convertTo2d();
nef_poly.p2 = sum.p2;
ZRemover zremover;
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 ) {
log << "<!-- volume. mark: " << i->mark() << " -->\n";
for ( j = i->shells_begin(); j != i->shells_end(); ++j ) {
log << "<!-- shell. mark: " << i->mark() << " -->\n";
sface_handle = CGAL_Nef_polyhedron3::SFace_const_handle( j );
sum.p3->visit_shell_objects( sface_handle , zremover );
log << "<!-- shell. end. -->\n";
}
log << "<!-- volume end. -->\n";
}
nef_poly.p2 = zremover.output_nefpoly2d;
} catch (const CGAL::Failure_exception &e) {
PRINTB("CGAL error in projection node while flattening: %s", e.what());
}

View File

@ -59,7 +59,7 @@ AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiat
argnames += "type", "level", "convexity";
if (type == RESIZE)
argnames += "newsize";
argnames += "newsize", "auto";
Context c(ctx);
c.args(argnames, argexpr, inst->argnames, inst->argvalues);
@ -90,6 +90,8 @@ AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiat
if ( v.size() >= 2 ) node->newsize[1] = v[1].toDouble();
if ( v.size() >= 3 ) node->newsize[2] = v[2].toDouble();
}
Value autosize = c.lookup_variable("auto");
node->autosize = autosize.toBool();
}
node->convexity = (int)convexity.toDouble();

View File

@ -32,6 +32,7 @@ public:
std::string subdiv_type;
int convexity, level;
Vector3d newsize;
bool autosize;
cgaladv_type_e type;
};

View File

@ -173,5 +173,56 @@ CGAL_Iso_rectangle_2e bounding_box( const CGAL_Nef_polyhedron2 &N )
return result;
}
void ZRemover::visit( CGAL_Nef_polyhedron3::Halffacet_const_handle hfacet )
{
log << " <!-- ZRemover Halffacet visit. Mark: " << hfacet->mark() << " -->\n";
if ( hfacet->plane().orthogonal_direction() != this->up ) {
log << " <!-- ZRemover down-facing half-facet. skipping -->\n";
log << " <!-- ZRemover Halffacet visit end-->\n";
return;
}
// possible optimization - throw out facets that are vertically oriented
CGAL_Nef_polyhedron3::Halffacet_cycle_const_iterator fci;
int contour_counter = 0;
CGAL_forall_facet_cycles_of( fci, hfacet ) {
if ( fci.is_shalfedge() ) {
log << " <!-- ZRemover Halffacet cycle begin -->\n";
CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c1(fci), cend(c1);
std::vector<CGAL_Nef_polyhedron2::Explorer::Point> contour;
CGAL_For_all( c1, cend ) {
CGAL_Nef_polyhedron3::Point_3 point3d = c1->source()->target()->point();
CGAL_Nef_polyhedron2::Explorer::Point point2d( point3d.x(), point3d.y() );
contour.push_back( point2d );
}
if (contour.size()==0) continue;
log << " <!-- is_simple_2:" << CGAL::is_simple_2( contour.begin(), contour.end() ) << " --> \n";
tmpnef2d.reset( new CGAL_Nef_polyhedron2( contour.begin(), contour.end(), boundary ) );
if ( contour_counter == 0 ) {
log << " <!-- contour is a body. make union(). " << contour.size() << " points. -->\n" ;
*(output_nefpoly2d) += *(tmpnef2d);
} else {
log << " <!-- contour is a hole. make intersection(). " << contour.size() << " points. -->\n";
*(output_nefpoly2d) *= *(tmpnef2d);
}
/*log << "\n<!-- ======== output tmp nef: ==== -->\n"
<< OpenSCAD::dump_svg( *tmpnef2d ) << "\n"
<< "\n<!-- ======== output accumulator: ==== -->\n"
<< OpenSCAD::dump_svg( *output_nefpoly2d ) << "\n";*/
contour_counter++;
} else {
log << " <!-- ZRemover trivial facet cycle skipped -->\n";
}
log << " <!-- ZRemover Halffacet cycle end -->\n";
}
log << " <!-- ZRemover Halffacet visit end -->\n";
}
#endif /* ENABLE_CGAL */

View File

@ -57,55 +57,7 @@ public:
void visit( CGAL_Nef_polyhedron3::SHalfedge_const_handle ) {}
void visit( CGAL_Nef_polyhedron3::SHalfloop_const_handle ) {}
void visit( CGAL_Nef_polyhedron3::SFace_const_handle ) {}
void visit( CGAL_Nef_polyhedron3::Halffacet_const_handle hfacet ) {
log << " <!-- Halffacet visit. Mark: " << hfacet->mark() << " -->\n";
if ( hfacet->plane().orthogonal_direction() != this->up ) {
log << " <!-- down-facing half-facet. skipping -->\n";
log << " <!-- Halffacet visit end-->\n";
return;
}
// possible optimization - throw out facets that are 'side facets' between
// the top & bottom of the big thin box. (i.e. mixture of z=-eps and z=eps)
CGAL_Nef_polyhedron3::Halffacet_cycle_const_iterator fci;
int contour_counter = 0;
CGAL_forall_facet_cycles_of( fci, hfacet ) {
if ( fci.is_shalfedge() ) {
CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c1(fci), cend(c1);
std::vector<CGAL_Nef_polyhedron2::Explorer::Point> contour;
CGAL_For_all( c1, cend ) {
CGAL_Nef_polyhedron3::Point_3 point3d = c1->source()->target()->point();
CGAL_Nef_polyhedron2::Explorer::Point point2d( point3d.x(), point3d.y() );
contour.push_back( point2d );
}
if (contour.size()==0) continue;
log << " <!-- is_simple_2:" << CGAL::is_simple_2( contour.begin(), contour.end() ) << " --> \n";
tmpnef2d.reset( new CGAL_Nef_polyhedron2( contour.begin(), contour.end(), boundary ) );
if ( contour_counter == 0 ) {
log << " <!-- contour is a body. make union(). " << contour.size() << " points. -->\n" ;
*(output_nefpoly2d) += *(tmpnef2d);
} else {
log << " <!-- contour is a hole. make intersection(). " << contour.size() << " points. -->\n";
*(output_nefpoly2d) *= *(tmpnef2d);
}
log << "\n<!-- ======== output tmp nef: ==== -->\n"
<< OpenSCAD::dump_svg( *tmpnef2d ) << "\n"
<< "\n<!-- ======== output accumulator: ==== -->\n"
<< OpenSCAD::dump_svg( *output_nefpoly2d ) << "\n";
contour_counter++;
} else {
log << " <!-- trivial facet cycle skipped -->\n";
}
} // next facet cycle (i.e. next contour)
log << " <!-- Halffacet visit end -->\n";
} // visit()
void visit( CGAL_Nef_polyhedron3::Halffacet_const_handle hfacet );
};

View File

@ -2,13 +2,13 @@
#include "cgalutils.h"
#include "svg.h"
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <map>
namespace OpenSCAD {
// SVG code
// currently for debugging, not necessarily pretty or useful for users. (yet)
int svg_cursor_py = 0;
int svg_px_width = SVG_PXW;
int svg_px_height = SVG_PXH;
@ -27,6 +27,26 @@ std::string svg_label(std::string s)
return out.str();
}
std::string svg_styleblock(std::string strokewidth)
{
std::stringstream out;
// halfedge: f1/f0 = face mark, b1/b0 = body or hole, m1/m0 = halfedge mark
out << "\
<style type='text/css'>\n\
.halfedge_f0_b1_m0 { stroke: gold; stroke-width: __STROKEW__px } \n\
.halfedge_f0_b1_m1 { stroke: gold; stroke-width: __STROKEW__px } \n\
.halfedge_f0_b0_m0 { stroke: green; stroke-width: __STROKEW__px } \n\
.halfedge_f0_b0_m1 { stroke: green; stroke-width: __STROKEW__px } \n\
.halfedge_f1_b1_m0 { stroke: gold; stroke-width: __STROKEW__px } \n\
.halfedge_f1_b1_m1 { stroke: gold; stroke-width: __STROKEW__px } \n\
.halfedge_f1_b0_m0 { stroke: green; stroke-width: __STROKEW__px } \n\
.halfedge_f1_b0_m1 { stroke: green; stroke-width: __STROKEW__px } \n\
</style>";
std::string tmp = out.str();
boost::replace_all( tmp, "__STROKEW__", strokewidth );
return tmp;
}
std::string svg_border()
{
std::stringstream out;
@ -93,36 +113,27 @@ 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::string color,
bool mark,
CGAL_Iso_rectangle_2e bbox )
bool facemark, bool body )
{
std::stringstream style;
style << "halfedge_f" << facemark << "_b" << body << "_m";
std::string styleclass = style.str();
std::stringstream out;
CGAL_For_all(c1, c2) {
if ( explorer.is_standard( explorer.target(c1) ) ) {
CGAL_Point_2e source = explorer.point( explorer.source( c1 ) );
CGAL_Point_2e target = explorer.point( explorer.target( c1 ) );
CGAL_Point_2e tp1 = project_svg_2to2( source, bbox );
CGAL_Point_2e tp2 = project_svg_2to2( target, bbox );
double mod=0;
if (color=="green") mod=10;
out << " <!-- Halfedge. Mark: " << c1->mark() << " -->\n";
out << " <line"
<< " x1='" << CGAL::to_double(tp1.x()) + mod << "'"
<< " y1='" << CGAL::to_double(tp1.y()) - mod << "'"
<< " x2='" << CGAL::to_double(tp2.x()) + mod << "'"
<< " y2='" << CGAL::to_double(tp2.y()) - mod << "'"
<< " stroke='" << color << "'";
if (!mark) out << " stroke-dasharray='4 4' />\n";
else out << " />\n";
// crude "arrowhead" to indicate directionality
out << " <circle"
<< " cx='" << CGAL::to_double(tp1.x()+ (tp2.x()-tp1.x())* 7/8) + mod << "'"
<< " cy='" << CGAL::to_double(tp1.y()+ (tp2.y()-tp1.y())* 7/8) - mod << "'"
<< " r='2'"
<< " fill='" << color << "' stroke='" << color << "' />\n";
out << " <!-- Halfedge. Mark: " << c1->mark() << " -->\n";
std::string he_mark = boost::lexical_cast<std::string>(c1->mark());
out << " <line"
<< " x1='" << CGAL::to_double(source.x()) << "'"
<< " y1='" << CGAL::to_double(source.y()) << "'"
<< " x2='" << CGAL::to_double(target.x()) << "'"
<< " y2='" << CGAL::to_double(target.y()) << "'"
<< " class='" << styleclass + he_mark << "' />\n";
} else {
out << " <!-- 2d Nef Rays - not implemented -->\n";
out << " <!-- 2d Nef Rays - not implemented -->\n";
}
}
return out.str();
@ -132,27 +143,27 @@ std::string dump_svg( const CGAL_Nef_polyhedron2 &N )
{
std::stringstream out;
CGAL_Nef_polyhedron2::Explorer explorer = N.explorer();
CGAL_Iso_rectangle_2e bbox = bounding_box( N );
CGAL_Nef_polyhedron2::Explorer::Face_const_iterator i;
out << " <svg y='" << svg_cursor_py << "' width='" << svg_px_width
<< "' height='" << svg_px_height
<< "' xmlns='http://www.w3.org/2000/svg' version='1.1'>\n";
out << svg_border() << "\n" << svg_axes() << "\n";
svg_cursor_py += svg_px_height;
std::string linewidth = "0.05";
out << "<!--CGAL_Nef_polyhedron2 dump begin-->\n";
out << svg_header() << "\n" << svg_styleblock( linewidth ) << "\n";
for ( i = explorer.faces_begin(); i!= explorer.faces_end(); ++i ) {
out << " <!-- face begin. mark: " << i->mark() << " -->\n";
out << " <!-- body begin -->\n";
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, "red", i->mark(), bbox );
out << dump_cgal_nef_polyhedron2_face_svg( c1, c2, explorer, i->mark(), true );
out << " <!-- body end -->\n";
CGAL_Nef_polyhedron2::Explorer::Hole_const_iterator j;
for ( j = explorer.holes_begin( i ); j!= explorer.holes_end( i ); ++j ) {
out << " <!-- hole begin. mark: " << j->mark() << " -->\n";
CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator c3( j ), c4 ( c3 );
out << dump_cgal_nef_polyhedron2_face_svg( c3, c4, explorer, "green", j->mark(), bbox );
out << dump_cgal_nef_polyhedron2_face_svg( c3, c4, explorer, "green", j->mark() );
out << " <!-- hole end -->\n";
}
out << " <!-- face end -->\n";
@ -182,13 +193,13 @@ public:
void visit( CGAL_Nef_polyhedron3::Halffacet_const_handle hfacet )
{
int contour_count = 0;
out << " <!-- Halffacet. Mark: " << (*hfacet).mark() << " -->\n";
out << " <!-- Halffacet visit. Mark: " << (*hfacet).mark() << " -->\n";
std::string color = "gold";
if (!(*hfacet).mark()) color = "green";
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";
out << " <!-- Halffacet cycle begin: -->\n";
if ( contour_count == 0 ) {
out << " <!-- Body contour:--> \n";
} else {
@ -196,13 +207,15 @@ public:
}
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();
CGAL_Point_2e tp1 = project_svg_3to2 ( source, bbox );
CGAL_Point_2e tp2 = project_svg_3to2 ( target, bbox );
out << " "
out << " <!-- " << CGAL::to_double(source.x()) << ","
<< CGAL::to_double(source.y()) << ","
<< CGAL::to_double(source.z()) << " -->\n";
out << " <line "
<< "x1='" << CGAL::to_double(tp1.x()) << "' "
<< "y1='" << CGAL::to_double(tp1.y()) << "' "
<< "x2='" << CGAL::to_double(tp2.x()) << "' "
@ -212,31 +225,34 @@ public:
else out << " />\n";
}
contour_count++;
} // next facet cycle (i.e. next contour)
} // visit()
out << " <!-- Halffacet cycle end -->\n";
}
out << " <!-- Halffacet visit end -->\n";
}
};
std::string dump_svg( const CGAL_Nef_polyhedron3 &N )
{
std::stringstream out;
out << svg_header() << "\n" << svg_border() << "\n" << svg_axes() << "\n";
std::string linewidth = "0.05";
out << "<!--CGAL_Nef_polyhedron3 dump begin-->\n";
out << svg_header() << "\n" << svg_border() << "\n";
out << svg_styleblock( linewidth ) << "\n" << svg_axes() << "\n";
CGAL_Nef_polyhedron3::Volume_const_iterator c;
CGAL_forall_volumes(c,N) {
out << " <!--Processing volume...-->\n";
out << " <!--Volume begin-->\n";
out << " <!--Mark: " << (*c).mark() << "-->\n";
CGAL_Nef_polyhedron3::Shell_entry_const_iterator it;
CGAL_forall_shells_of(it,c) {
out << " <!--Processing shell...-->\n";
out << " <!--Shell begin-->\n";
NefPoly3_dumper_svg dumper_svg(N);
N.visit_shell_objects(CGAL_Nef_polyhedron3::SFace_const_handle(it), dumper_svg );
out << dumper_svg.out.str();
out << " <!--Processing shell end-->\n";
out << " <!--Shell end-->\n";
}
out << " <!--Processing volume end-->\n";
out << " <!--Volume end-->\n";
}
out << "<!--CGAL_Nef_polyhedron3 dump end-->\n";
out << "</svg>";