summaryrefslogtreecommitdiff
path: root/src/CGALRenderer.cc
diff options
context:
space:
mode:
authorMarius Kintel <marius@kintel.net>2010-03-29 01:31:47 (GMT)
committerMarius Kintel <marius@kintel.net>2010-10-31 00:42:35 (GMT)
commit184d0e041f6279dba5d1f6348f973478ae133a3a (patch)
treedccc0d26fd5b14e4f5ca834290e7f588febfcbe4 /src/CGALRenderer.cc
parent34a8206410f049f566535b1d795b4e89950c6a6f (diff)
Initial implementation of CGALRenderer
Diffstat (limited to 'src/CGALRenderer.cc')
-rw-r--r--src/CGALRenderer.cc597
1 files changed, 487 insertions, 110 deletions
diff --git a/src/CGALRenderer.cc b/src/CGALRenderer.cc
index 2926023..d9f4c69 100644
--- a/src/CGALRenderer.cc
+++ b/src/CGALRenderer.cc
@@ -9,27 +9,28 @@
#include "csgnode.h"
#include "transformnode.h"
+#include "polyset.h"
+#include "dxfdata.h"
+#include "dxftess.h"
#include <sstream>
#include <iostream>
#include <assert.h>
#include <QRegExp>
-string CGALRenderer::getCGALMesh() const
+CGALRenderer *CGALRenderer::global_renderer = NULL;
+
+CGAL_Nef_polyhedron CGALRenderer::renderCGALMesh(const AbstractNode &node)
{
- assert(this->root);
- // FIXME: assert that cache contains root
- return this->cache[mk_cache_id(*this->root)];
+ if (!isCached(node)) {
+ Traverser render(*this, node, Traverser::PRE_AND_POSTFIX);
+ render.execute();
+ assert(isCached(node));
+ }
+ return this->cache[mk_cache_id(node)];
}
-// CGAL_Nef_polyhedron CGALRenderer::getCGALMesh() const
-// {
-// assert(this->root);
-// // FIXME: assert that cache contains root
-// return this->cache[*this->root];
-// }
-
-bool CGALRenderer::isCached(const AbstractNode &node)
+bool CGALRenderer::isCached(const AbstractNode &node) const
{
return this->cache.contains(mk_cache_id(node));
}
@@ -38,82 +39,55 @@ bool CGALRenderer::isCached(const AbstractNode &node)
Modifies target by applying op to target and src:
target = target [op] src
*/
-void
-CGALRenderer::process(string &target, const string &src, CGALRenderer::CsgOp op)
+void CGALRenderer::process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, CsgOp op)
{
-// if (target.dim != 2 && target.dim != 3) {
-// assert(false && "Dimension of Nef polyhedron must be 2 or 3");
-// }
-
- switch (op) {
- case UNION:
- target += "+" + src;
- break;
- case INTERSECTION:
- target += "*" + src;
- break;
- case DIFFERENCE:
- target += "-" + src;
- break;
- case MINKOWSKI:
- target += "M" + src;
- break;
+ if (target.dim != 2 && target.dim != 3) {
+ assert(false && "Dimension of Nef polyhedron must be 2 or 3");
+ }
+
+ if (target.dim == 2) {
+ switch (op) {
+ case UNION:
+ target.p2 += src.p2;
+ break;
+ case INTERSECTION:
+ target.p2 *= src.p2;
+ break;
+ case DIFFERENCE:
+ target.p2 -= src.p2;
+ break;
+ case MINKOWSKI:
+ target.p2 = minkowski2(target.p2, src.p2);
+ break;
+ }
+ }
+ else if (target.dim == 3) {
+ switch (op) {
+ case UNION:
+ target.p3 += src.p3;
+ break;
+ case INTERSECTION:
+ target.p3 *= src.p3;
+ break;
+ case DIFFERENCE:
+ target.p3 -= src.p3;
+ break;
+ case MINKOWSKI:
+ target.p3 = minkowski3(target.p3, src.p3);
+ break;
+ }
}
}
-// /*!
-// Modifies target by applying op to target and src:
-// target = target [op] src
-// */
-// void process(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, CsgOp op)
-// {
-// if (target.dim == 2) {
-// switch (op) {
-// case UNION:
-// target.p2 += src.p2;
-// break;
-// case INTERSECTION:
-// target.p2 *= src.p2;
-// break;
-// case DIFFERENCE:
-// target.p2 -= src.p2;
-// break;
-// case MINKOWSKI:
-// target.p2 = minkowski2(target.p2, src.p2);
-// break;
-// }
-// }
-// else if (target.dim == 3) {
-// switch (op) {
-// case UNION:
-// target.p3 += src.p3;
-// break;
-// case INTERSECTION:
-// target.p3 *= src.p3;
-// break;
-// case DIFFERENCE:
-// target.p3 -= src.p3;
-// break;
-// case MINKOWSKI:
-// target.p3 = minkowski3(target.p3, src.p3);
-// break;
-// }
-// }
-// else {
-// assert(false && "Dimention of Nef polyhedron must be 2 or 3");
-// }
-// }
-
+/*!
+ FIXME: Let caller insert into the cache since caller might modify the result
+ (e.g. transform)
+*/
void CGALRenderer::applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp op)
{
- std::stringstream stream;
- stream << typeid(node).name();
- stream << "<" << node.index() << ">";
- string N = stream.str();
+ CGAL_Nef_polyhedron N;
if (this->visitedchildren[node.index()].size() > 0) {
- // FIXME: assert that cache contains nodes in code below
bool first = true;
-// CGAL_Nef_polyhedron N;
for (ChildList::const_iterator iter = this->visitedchildren[node.index()].begin();
iter != this->visitedchildren[node.index()].end();
iter++) {
@@ -121,16 +95,17 @@ void CGALRenderer::applyToChildren(const AbstractNode &node, CGALRenderer::CsgOp
const QString &chcacheid = iter->second;
// FIXME: Don't use deep access to modinst members
if (chnode->modinst->tag_background) continue;
+ assert(isCached(*chnode));
if (first) {
- N += "(" + this->cache[chcacheid];
-// if (N.dim != 0) first = false; // FIXME: when can this happen?
- first = false;
+ N = this->cache[chcacheid];
+ // If the first child(ren) are empty (e.g. echo) nodes,
+ // ignore them (reset first flag)
+ if (N.dim != 0) first = false;
} else {
process(N, this->cache[chcacheid], op);
}
chnode->progress_report();
}
- N += ")";
}
QString cacheid = mk_cache_id(node);
this->cache.insert(cacheid, N);
@@ -153,6 +128,7 @@ Response CGALRenderer::visit(const State &state, const AbstractNode &node)
return ContinueTraversal;
}
+#if 0
Response CGALRenderer::visit(const State &state, const AbstractIntersectionNode &node)
{
if (state.isPrefix() && isCached(node)) return PruneTraversal;
@@ -186,6 +162,7 @@ Response CGALRenderer::visit(const State &state, const CsgNode &node)
}
return ContinueTraversal;
}
+#endif
Response CGALRenderer::visit(const State &state, const TransformNode &node)
{
@@ -194,7 +171,43 @@ Response CGALRenderer::visit(const State &state, const TransformNode &node)
if (!isCached(node)) {
// First union all children
applyToChildren(node, UNION);
- // FIXME: Then apply transform
+
+ // Then apply transform
+ QString cacheid = mk_cache_id(node);
+ CGAL_Nef_polyhedron N = this->cache[cacheid];
+ assert(N.dim >= 2 && N.dim <= 3);
+ 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!
+
+ CGAL_Aff_transformation2 t(
+ node.m[0], node.m[4], node.m[12],
+ node.m[1], node.m[5], node.m[13], node.m[15]);
+
+ DxfData dd(N);
+ for (int i=0; i < dd.points.size(); i++) {
+ CGAL_Kernel2::Point_2 p = CGAL_Kernel2::Point_2(dd.points[i].x, dd.points[i].y);
+ p = t.transform(p);
+ dd.points[i].x = to_double(p.x());
+ dd.points[i].y = to_double(p.y());
+ }
+
+ PolySet ps;
+ ps.is2d = true;
+ dxf_tesselate(&ps, &dd, 0, true, false, 0);
+
+ N = renderCGALMesh(ps);
+ ps.refcount = 0;
+ }
+ else if (N.dim == 3) {
+ CGAL_Aff_transformation t(
+ node.m[0], node.m[4], node.m[ 8], node.m[12],
+ node.m[1], node.m[5], node.m[ 9], node.m[13],
+ node.m[2], node.m[6], node.m[10], node.m[14], node.m[15]);
+ N.p3.transform(t);
+ }
+ this->cache.insert(cacheid, N);
}
addToParent(state, node);
}
@@ -215,35 +228,27 @@ Response CGALRenderer::visit(const State &state, const AbstractPolyNode &node)
if (state.isPrefix() && isCached(node)) return PruneTraversal;
if (state.isPostfix()) {
if (!isCached(node)) {
+ // First union all children
+ applyToChildren(node, UNION);
- // FIXME: Manage caching
- // FIXME: Will generate one single Nef polyhedron (no csg ops necessary)
-
-// PolySet *ps = render_polyset(RENDER_CGAL);
-// try {
-// CGAL_Nef_polyhedron N = ps->renderCSGMesh();
-// cgal_nef_cache.insert(cache_id, new cgal_nef_cache_entry(N), N.weight());
-// print_messages_pop();
-// progress_report();
-
-// ps->unlink();
-// return N;
-// }
-// catch (...) { // Don't leak the PolySet on ProgressCancelException
-// ps->unlink();
-// throw;
-// }
-
- string N = typeid(node).name();
- QString cacheid = mk_cache_id(node);
- this->cache.insert(cacheid, N);
-
-// std::cout << "Insert: " << N << "\n";
-// std::cout << "Node: " << cacheid.toStdString() << "\n\n";
+ // Then apply polyset operation
+ PolySet *ps = node.render_polyset(AbstractPolyNode::RENDER_CGAL);
+ try {
+ CGAL_Nef_polyhedron N = renderCGALMesh(*ps);
+// print_messages_pop();
+ node.progress_report();
+
+ ps->unlink();
+ QString cacheid = mk_cache_id(node);
+ this->cache.insert(cacheid, N);
+ }
+ catch (...) { // Don't leak the PolySet on ProgressCancelException
+ ps->unlink();
+ throw;
+ }
}
addToParent(state, node);
}
-
return ContinueTraversal;
}
@@ -284,3 +289,375 @@ QString CGALRenderer::mk_cache_id(const AbstractNode &node) const
cache_id.remove('\n');
return cache_id;
}
+
+#if 0
+/*!
+ Static function to render CGAL meshes.
+ NB! This is just a support function used for development and debugging
+*/
+CGAL_Nef_polyhedron CGALRenderer::renderCGALMesh(const AbstractPolyNode &node)
+{
+ // FIXME: Lookup Nef polyhedron in cache.
+
+ // print_messages_push();
+
+ PolySet *ps = node.render_polyset(AbstractPolyNode::RENDER_CGAL);
+ try {
+ CGAL_Nef_polyhedron N = ps->renderCSGMesh();
+ // FIXME: Insert into cache
+ // print_messages_pop();
+ node.progress_report();
+
+ ps->unlink();
+ return N;
+ }
+ catch (...) { // Don't leak the PolySet on ProgressCancelException
+ ps->unlink();
+ throw;
+ }
+}
+#endif
+
+#ifdef ENABLE_CGAL
+
+#undef GEN_SURFACE_DEBUG
+
+class CGAL_Build_PolySet : public CGAL::Modifier_base<CGAL_HDS>
+{
+public:
+ typedef CGAL_HDS::Vertex::Point Point;
+
+ const PolySet &ps;
+ CGAL_Build_PolySet(const PolySet &ps) : ps(ps) { }
+
+ void operator()(CGAL_HDS& hds)
+ {
+ CGAL_Polybuilder B(hds, true);
+
+ QList<PolySet::Point> vertices;
+ Grid3d<int> vertices_idx(GRID_FINE);
+
+ for (int i = 0; i < ps.polygons.size(); i++) {
+ const PolySet::Polygon *poly = &ps.polygons[i];
+ for (int j = 0; j < poly->size(); j++) {
+ const PolySet::Point *p = &poly->at(j);
+ if (!vertices_idx.has(p->x, p->y, p->z)) {
+ vertices_idx.data(p->x, p->y, p->z) = vertices.size();
+ vertices.append(*p);
+ }
+ }
+ }
+
+ B.begin_surface(vertices.size(), ps.polygons.size());
+#ifdef GEN_SURFACE_DEBUG
+ printf("=== CGAL Surface ===\n");
+#endif
+
+ for (int i = 0; i < vertices.size(); i++) {
+ const PolySet::Point *p = &vertices[i];
+ B.add_vertex(Point(p->x, p->y, p->z));
+#ifdef GEN_SURFACE_DEBUG
+ printf("%d: %f %f %f\n", i, p->x, p->y, p->z);
+#endif
+ }
+
+ for (int i = 0; i < ps.polygons.size(); i++) {
+ const PolySet::Polygon *poly = &ps.polygons[i];
+ QHash<int,int> fc;
+ bool facet_is_degenerated = false;
+ for (int j = 0; j < poly->size(); j++) {
+ const PolySet::Point *p = &poly->at(j);
+ int v = vertices_idx.data(p->x, p->y, p->z);
+ if (fc[v]++ > 0)
+ facet_is_degenerated = true;
+ }
+
+ if (!facet_is_degenerated)
+ B.begin_facet();
+#ifdef GEN_SURFACE_DEBUG
+ printf("F:");
+#endif
+ for (int j = 0; j < poly->size(); j++) {
+ const PolySet::Point *p = &poly->at(j);
+#ifdef GEN_SURFACE_DEBUG
+ printf(" %d (%f,%f,%f)", vertices_idx.data(p->x, p->y, p->z), p->x, p->y, p->z);
+#endif
+ if (!facet_is_degenerated)
+ B.add_vertex_to_facet(vertices_idx.data(p->x, p->y, p->z));
+ }
+#ifdef GEN_SURFACE_DEBUG
+ if (facet_is_degenerated)
+ printf(" (degenerated)");
+ printf("\n");
+#endif
+ if (!facet_is_degenerated)
+ B.end_facet();
+ }
+
+#ifdef GEN_SURFACE_DEBUG
+ printf("====================\n");
+#endif
+ B.end_surface();
+
+ #undef PointKey
+ }
+};
+
+#endif /* ENABLE_CGAL */
+
+CGAL_Nef_polyhedron CGALRenderer::renderCGALMesh(const PolySet &ps)
+{
+ if (ps.is2d)
+ {
+#if 0
+ // This version of the code causes problems in some cases.
+ // Example testcase: import_dxf("testdata/polygon8.dxf");
+ //
+ typedef std::list<CGAL_Nef_polyhedron2::Point> point_list_t;
+ typedef point_list_t::iterator point_list_it;
+ std::list< point_list_t > pdata_point_lists;
+ std::list < std::pair < point_list_it, point_list_it > > pdata;
+ Grid2d<CGAL_Nef_polyhedron2::Point> grid(GRID_COARSE);
+
+ for (int i = 0; i < ps.polygons.size(); i++) {
+ pdata_point_lists.push_back(point_list_t());
+ for (int j = 0; j < ps.polygons[i].size(); j++) {
+ double x = ps.polygons[i][j].x;
+ double y = ps.polygons[i][j].y;
+ CGAL_Nef_polyhedron2::Point p;
+ if (grid.has(x, y)) {
+ p = grid.data(x, y);
+ } else {
+ p = CGAL_Nef_polyhedron2::Point(x, y);
+ grid.data(x, y) = p;
+ }
+ pdata_point_lists.back().push_back(p);
+ }
+ pdata.push_back(std::make_pair(pdata_point_lists.back().begin(),
+ pdata_point_lists.back().end()));
+ }
+
+ CGAL_Nef_polyhedron2 N(pdata.begin(), pdata.end(), CGAL_Nef_polyhedron2::POLYGONS);
+ return CGAL_Nef_polyhedron(N);
+#endif
+#if 0
+ // This version of the code works fine but is pretty slow.
+ //
+ CGAL_Nef_polyhedron2 N;
+ Grid2d<CGAL_Nef_polyhedron2::Point> grid(GRID_COARSE);
+
+ for (int i = 0; i < ps.polygons.size(); i++) {
+ std::list<CGAL_Nef_polyhedron2::Point> plist;
+ for (int j = 0; j < ps.polygons[i].size(); j++) {
+ double x = ps.polygons[i][j].x;
+ double y = ps.polygons[i][j].y;
+ CGAL_Nef_polyhedron2::Point p;
+ if (grid.has(x, y)) {
+ p = grid.data(x, y);
+ } else {
+ p = CGAL_Nef_polyhedron2::Point(x, y);
+ grid.data(x, y) = p;
+ }
+ plist.push_back(p);
+ }
+ N += CGAL_Nef_polyhedron2(plist.begin(), plist.end(), CGAL_Nef_polyhedron2::INCLUDED);
+ }
+
+ return CGAL_Nef_polyhedron(N);
+#endif
+#if 1
+ // This version of the code does essentially the same thing as the 2nd
+ // version but merges some triangles before sending them to CGAL. This adds
+ // complexity but speeds up things..
+ //
+ struct PolyReducer
+ {
+ Grid2d<int> grid;
+ QHash< QPair<int,int>, QPair<int,int> > egde_to_poly;
+ QHash< int, CGAL_Nef_polyhedron2::Point > points;
+ QHash< int, QList<int> > polygons;
+ int poly_n;
+
+ void add_edges(int pn)
+ {
+ for (int j = 1; j <= this->polygons[pn].size(); j++) {
+ int a = this->polygons[pn][j-1];
+ int b = this->polygons[pn][j % this->polygons[pn].size()];
+ if (a > b) { a = a^b; b = a^b; a = a^b; }
+ if (this->egde_to_poly[QPair<int,int>(a, b)].first == 0)
+ this->egde_to_poly[QPair<int,int>(a, b)].first = pn;
+ else if (this->egde_to_poly[QPair<int,int>(a, b)].second == 0)
+ this->egde_to_poly[QPair<int,int>(a, b)].second = pn;
+ else
+ abort();
+ }
+ }
+
+ void del_poly(int pn)
+ {
+ for (int j = 1; j <= this->polygons[pn].size(); j++) {
+ int a = this->polygons[pn][j-1];
+ int b = this->polygons[pn][j % this->polygons[pn].size()];
+ if (a > b) { a = a^b; b = a^b; a = a^b; }
+ if (this->egde_to_poly[QPair<int,int>(a, b)].first == pn)
+ this->egde_to_poly[QPair<int,int>(a, b)].first = 0;
+ if (this->egde_to_poly[QPair<int,int>(a, b)].second == pn)
+ this->egde_to_poly[QPair<int,int>(a, b)].second = 0;
+ }
+ this->polygons.remove(pn);
+ }
+
+ PolyReducer(const PolySet &ps) : grid(GRID_COARSE), poly_n(1)
+ {
+ int point_n = 1;
+ for (int i = 0; i < ps.polygons.size(); i++) {
+ for (int j = 0; j < ps.polygons[i].size(); j++) {
+ double x = ps.polygons[i][j].x;
+ double y = ps.polygons[i][j].y;
+ if (this->grid.has(x, y)) {
+ this->polygons[this->poly_n].append(this->grid.data(x, y));
+ } else {
+ this->grid.align(x, y) = point_n;
+ this->polygons[this->poly_n].append(point_n);
+ this->points[point_n] = CGAL_Nef_polyhedron2::Point(x, y);
+ point_n++;
+ }
+ }
+ add_edges(this->poly_n);
+ this->poly_n++;
+ }
+ }
+
+ int merge(int p1, int p1e, int p2, int p2e)
+ {
+ for (int i = 1; i < this->polygons[p1].size(); i++) {
+ int j = (p1e + i) % this->polygons[p1].size();
+ this->polygons[this->poly_n].append(this->polygons[p1][j]);
+ }
+ for (int i = 1; i < this->polygons[p2].size(); i++) {
+ int j = (p2e + i) % this->polygons[p2].size();
+ this->polygons[this->poly_n].append(this->polygons[p2][j]);
+ }
+ del_poly(p1);
+ del_poly(p2);
+ add_edges(this->poly_n);
+ return this->poly_n++;
+ }
+
+ void reduce()
+ {
+ QList<int> work_queue;
+ QHashIterator< int, QList<int> > it(polygons);
+ while (it.hasNext()) {
+ it.next();
+ work_queue.append(it.key());
+ }
+ while (!work_queue.isEmpty()) {
+ int poly1_n = work_queue.first();
+ work_queue.removeFirst();
+ if (!this->polygons.contains(poly1_n))
+ continue;
+ for (int j = 1; j <= this->polygons[poly1_n].size(); j++) {
+ int a = this->polygons[poly1_n][j-1];
+ int b = this->polygons[poly1_n][j % this->polygons[poly1_n].size()];
+ if (a > b) { a = a^b; b = a^b; a = a^b; }
+ if (this->egde_to_poly[QPair<int,int>(a, b)].first != 0 &&
+ this->egde_to_poly[QPair<int,int>(a, b)].second != 0) {
+ int poly2_n = this->egde_to_poly[QPair<int,int>(a, b)].first +
+ this->egde_to_poly[QPair<int,int>(a, b)].second - poly1_n;
+ int poly2_edge = -1;
+ for (int k = 1; k <= this->polygons[poly2_n].size(); k++) {
+ int c = this->polygons[poly2_n][k-1];
+ int d = this->polygons[poly2_n][k % this->polygons[poly2_n].size()];
+ if (c > d) { c = c^d; d = c^d; c = c^d; }
+ if (a == c && b == d) {
+ poly2_edge = k-1;
+ continue;
+ }
+ int poly3_n = this->egde_to_poly[QPair<int,int>(c, d)].first +
+ this->egde_to_poly[QPair<int,int>(c, d)].second - poly2_n;
+ if (poly3_n < 0)
+ continue;
+ if (poly3_n == poly1_n)
+ goto next_poly1_edge;
+ }
+ work_queue.append(merge(poly1_n, j-1, poly2_n, poly2_edge));
+ goto next_poly1;
+ }
+ next_poly1_edge:;
+ }
+ next_poly1:;
+ }
+ }
+
+ CGAL_Nef_polyhedron2 toNef()
+ {
+ CGAL_Nef_polyhedron2 N;
+
+ QHashIterator< int, QList<int> > it(polygons);
+ while (it.hasNext()) {
+ it.next();
+ std::list<CGAL_Nef_polyhedron2::Point> plist;
+ for (int j = 0; j < it.value().size(); j++) {
+ int p = it.value()[j];
+ plist.push_back(points[p]);
+ }
+ N += CGAL_Nef_polyhedron2(plist.begin(), plist.end(), CGAL_Nef_polyhedron2::INCLUDED);
+ }
+
+ return N;
+ }
+ };
+
+ PolyReducer pr(ps);
+ // printf("Number of polygons before reduction: %d\n", pr.polygons.size());
+ pr.reduce();
+ // printf("Number of polygons after reduction: %d\n", pr.polygons.size());
+ return CGAL_Nef_polyhedron(pr.toNef());
+#endif
+#if 0
+ // This is another experimental version. I should run faster than the above,
+ // is a lot simpler and has only one known weakness: Degenerate polygons, which
+ // get repaired by GLUTess, might trigger a CGAL crash here. The only
+ // known case for this is triangle-with-duplicate-vertex.dxf
+ // FIXME: If we just did a projection, we need to recreate the border!
+ if (ps.polygons.size() > 0) assert(ps.borders.size() > 0);
+ CGAL_Nef_polyhedron2 N;
+ Grid2d<CGAL_Nef_polyhedron2::Point> grid(GRID_COARSE);
+
+ for (int i = 0; i < ps.borders.size(); i++) {
+ std::list<CGAL_Nef_polyhedron2::Point> plist;
+ for (int j = 0; j < ps.borders[i].size(); j++) {
+ double x = ps.borders[i][j].x;
+ double y = ps.borders[i][j].y;
+ CGAL_Nef_polyhedron2::Point p;
+ if (grid.has(x, y)) {
+ p = grid.data(x, y);
+ } else {
+ p = CGAL_Nef_polyhedron2::Point(x, y);
+ grid.data(x, y) = p;
+ }
+ plist.push_back(p);
+ }
+ // FIXME: If a border (path) has a duplicate vertex in dxf,
+ // the CGAL_Nef_polyhedron2 constructor will crash.
+ N ^= CGAL_Nef_polyhedron2(plist.begin(), plist.end(), CGAL_Nef_polyhedron2::INCLUDED);
+ }
+
+ return CGAL_Nef_polyhedron(N);
+
+#endif
+ }
+ else
+ {
+ CGAL_Polyhedron P;
+ CGAL_Build_PolySet builder(ps);
+ P.delegate(builder);
+#if 0
+ std::cout << P;
+#endif
+ CGAL_Nef_polyhedron3 N(P);
+ return CGAL_Nef_polyhedron(N);
+ }
+ return CGAL_Nef_polyhedron();
+}
contact: Jan Huwald // Impressum