diff options
Diffstat (limited to 'src/polyset.cc')
-rw-r--r-- | src/polyset.cc | 706 |
1 files changed, 706 insertions, 0 deletions
diff --git a/src/polyset.cc b/src/polyset.cc new file mode 100644 index 0000000..5f22fde --- /dev/null +++ b/src/polyset.cc @@ -0,0 +1,706 @@ +/* + * OpenSCAD (www.openscad.at) + * Copyright (C) 2009 Clifford Wolf <clifford@clifford.at> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#define INCLUDE_ABSTRACT_NODE_DETAILS + +#include "openscad.h" +#include "printutils.h" +#include "Preferences.h" + +QCache<QString,PolySet::ps_cache_entry> PolySet::ps_cache(100); + +PolySet::ps_cache_entry::ps_cache_entry(PolySet *ps) : + ps(ps), msg(print_messages_stack.last()) { } + +PolySet::ps_cache_entry::~ps_cache_entry() { + ps->unlink(); +} + +PolySet::PolySet() : grid(GRID_FINE) +{ + is2d = false; + convexity = 1; + refcount = 1; +} + +PolySet::~PolySet() +{ + assert(refcount == 0); +} + +PolySet* PolySet::link() +{ + refcount++; + return this; +} + +void PolySet::unlink() +{ + if (--refcount == 0) + delete this; +} + +void PolySet::append_poly() +{ + polygons.append(Polygon()); +} + +void PolySet::append_vertex(double x, double y, double z) +{ + grid.align(x, y, z); + polygons.last().append(Point(x, y, z)); +} + +void PolySet::insert_vertex(double x, double y, double z) +{ + grid.align(x, y, z); + polygons.last().insert(0, Point(x, y, z)); +} + +static void gl_draw_triangle(GLint *shaderinfo, const PolySet::Point *p0, const PolySet::Point *p1, const PolySet::Point *p2, bool e0, bool e1, bool e2, double z, bool mirrored) +{ + double ax = p1->x - p0->x, bx = p1->x - p2->x; + double ay = p1->y - p0->y, by = p1->y - p2->y; + double az = p1->z - p0->z, bz = p1->z - p2->z; + double nx = ay*bz - az*by; + double ny = az*bx - ax*bz; + double nz = ax*by - ay*bx; + double nl = sqrt(nx*nx + ny*ny + nz*nz); + glNormal3d(nx / nl, ny / nl, nz / nl); +#ifdef ENABLE_OPENCSG + if (shaderinfo) { + double e0f = e0 ? 2.0 : -1.0; + double e1f = e1 ? 2.0 : -1.0; + double e2f = e2 ? 2.0 : -1.0; + glVertexAttrib3d(shaderinfo[3], e0f, e1f, e2f); + glVertexAttrib3d(shaderinfo[4], p1->x, p1->y, p1->z + z); + glVertexAttrib3d(shaderinfo[5], p2->x, p2->y, p2->z + z); + glVertexAttrib3d(shaderinfo[6], 0.0, 1.0, 0.0); + glVertex3d(p0->x, p0->y, p0->z + z); + if (!mirrored) { + glVertexAttrib3d(shaderinfo[3], e0f, e1f, e2f); + glVertexAttrib3d(shaderinfo[4], p0->x, p0->y, p0->z + z); + glVertexAttrib3d(shaderinfo[5], p2->x, p2->y, p2->z + z); + glVertexAttrib3d(shaderinfo[6], 0.0, 0.0, 1.0); + glVertex3d(p1->x, p1->y, p1->z + z); + } + glVertexAttrib3d(shaderinfo[3], e0f, e1f, e2f); + glVertexAttrib3d(shaderinfo[4], p0->x, p0->y, p0->z + z); + glVertexAttrib3d(shaderinfo[5], p1->x, p1->y, p1->z + z); + glVertexAttrib3d(shaderinfo[6], 1.0, 0.0, 0.0); + glVertex3d(p2->x, p2->y, p2->z + z); + if (mirrored) { + glVertexAttrib3d(shaderinfo[3], e0f, e1f, e2f); + glVertexAttrib3d(shaderinfo[4], p0->x, p0->y, p0->z + z); + glVertexAttrib3d(shaderinfo[5], p2->x, p2->y, p2->z + z); + glVertexAttrib3d(shaderinfo[6], 0.0, 0.0, 1.0); + glVertex3d(p1->x, p1->y, p1->z + z); + } + } + else +#endif + { + glVertex3d(p0->x, p0->y, p0->z + z); + if (!mirrored) + glVertex3d(p1->x, p1->y, p1->z + z); + glVertex3d(p2->x, p2->y, p2->z + z); + if (mirrored) + glVertex3d(p1->x, p1->y, p1->z + z); + } +} + +void PolySet::render_surface(colormode_e colormode, csgmode_e csgmode, double *m, GLint *shaderinfo) const +{ + double m_scale_rotate_det = + m[0]*m[5]*m[10] + m[4]*m[9]*m[2] + m[8]*m[1]*m[6] - + (m[8]*m[5]*m[2] + m[4]*m[1]*m[10] + m[0]*m[9]*m[6]); + bool mirrored = m_scale_rotate_det < 0; + + if (colormode == COLORMODE_MATERIAL) { + const QColor &col = Preferences::inst()->color(Preferences::OPENCSG_FACE_FRONT_COLOR); + glColor3f(col.redF(), col.greenF(), col.blueF()); +#ifdef ENABLE_OPENCSG + if (shaderinfo) { + glUniform4f(shaderinfo[1], col.redF(), col.greenF(), col.blueF(), 1.0f); + glUniform4f(shaderinfo[2], 255 / 255.0, 236 / 255.0, 94 / 255.0, 1.0); + } +#endif /* ENABLE_OPENCSG */ + } + if (colormode == COLORMODE_CUTOUT) { + const QColor &col = Preferences::inst()->color(Preferences::OPENCSG_FACE_BACK_COLOR); + glColor3f(col.redF(), col.greenF(), col.blueF()); +#ifdef ENABLE_OPENCSG + if (shaderinfo) { + glUniform4f(shaderinfo[1], 157 / 255.0, 203 / 255.0, 81 / 255.0, 1.0); + glUniform4f(shaderinfo[2], 171 / 255.0, 216 / 255.0, 86 / 255.0, 1.0); + } +#endif /* ENABLE_OPENCSG */ + } + if (colormode == COLORMODE_HIGHLIGHT) { + glColor4ub(255, 157, 81, 128); +#ifdef ENABLE_OPENCSG + if (shaderinfo) { + glUniform4f(shaderinfo[1], 255 / 255.0, 157 / 255.0, 81 / 255.0, 0.5); + glUniform4f(shaderinfo[2], 255 / 255.0, 171 / 255.0, 86 / 255.0, 0.5); + } +#endif /* ENABLE_OPENCSG */ + } + if (colormode == COLORMODE_BACKGROUND) { + glColor4ub(180, 180, 180, 128); +#ifdef ENABLE_OPENCSG + if (shaderinfo) { + glUniform4f(shaderinfo[1], 180 / 255.0, 180 / 255.0, 180 / 255.0, 0.5); + glUniform4f(shaderinfo[2], 150 / 255.0, 150 / 255.0, 150 / 255.0, 0.5); + } +#endif /* ENABLE_OPENCSG */ + } +#ifdef ENABLE_OPENCSG + if (shaderinfo) { + glUniform1f(shaderinfo[7], shaderinfo[9]); + glUniform1f(shaderinfo[8], shaderinfo[10]); + } +#endif /* ENABLE_OPENCSG */ + if (this->is2d) { + double zbase = csgmode; + glBegin(GL_TRIANGLES); + for (double z = -zbase/2; z < zbase; z += zbase) + { + for (int i = 0; i < polygons.size(); i++) { + const Polygon *poly = &polygons[i]; + if (poly->size() == 3) { + if (z < 0) { + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(2), &poly->at(1), true, true, true, z, mirrored); + } else { + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(2), true, true, true, z, mirrored); + } + } + else if (poly->size() == 4) { + if (z < 0) { + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(3), &poly->at(1), true, false, true, z, mirrored); + gl_draw_triangle(shaderinfo, &poly->at(2), &poly->at(1), &poly->at(3), true, false, true, z, mirrored); + } else { + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(3), true, false, true, z, mirrored); + gl_draw_triangle(shaderinfo, &poly->at(2), &poly->at(3), &poly->at(1), true, false, true, z, mirrored); + } + } + else { + Point center; + for (int j = 0; j < poly->size(); j++) { + center.x += poly->at(j).x; + center.y += poly->at(j).y; + } + center.x /= poly->size(); + center.y /= poly->size(); + for (int j = 1; j <= poly->size(); j++) { + if (z < 0) { + gl_draw_triangle(shaderinfo, ¢er, &poly->at(j % poly->size()), &poly->at(j - 1), + false, true, false, z, mirrored); + } else { + gl_draw_triangle(shaderinfo, ¢er, &poly->at(j - 1), &poly->at(j % poly->size()), + false, true, false, z, mirrored); + } + } + } + } + } + const QVector<Polygon> *borders_p = &borders; + if (borders_p->size() == 0) + borders_p = &polygons; + for (int i = 0; i < borders_p->size(); i++) { + const Polygon *poly = &borders_p->at(i); + for (int j = 1; j <= poly->size(); j++) { + Point p1 = poly->at(j - 1), p2 = poly->at(j - 1); + Point p3 = poly->at(j % poly->size()), p4 = poly->at(j % poly->size()); + p1.z -= zbase/2, p2.z += zbase/2; + p3.z -= zbase/2, p4.z += zbase/2; + gl_draw_triangle(shaderinfo, &p2, &p1, &p3, true, true, false, 0, mirrored); + gl_draw_triangle(shaderinfo, &p2, &p3, &p4, false, true, true, 0, mirrored); + } + } + glEnd(); + } else { + for (int i = 0; i < polygons.size(); i++) { + const Polygon *poly = &polygons[i]; + glBegin(GL_TRIANGLES); + if (poly->size() == 3) { + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(2), true, true, true, 0, mirrored); + } + else if (poly->size() == 4) { + gl_draw_triangle(shaderinfo, &poly->at(0), &poly->at(1), &poly->at(3), true, false, true, 0, mirrored); + gl_draw_triangle(shaderinfo, &poly->at(2), &poly->at(3), &poly->at(1), true, false, true, 0, mirrored); + } + else { + Point center; + for (int j = 0; j < poly->size(); j++) { + center.x += poly->at(j).x; + center.y += poly->at(j).y; + center.z += poly->at(j).z; + } + center.x /= poly->size(); + center.y /= poly->size(); + center.z /= poly->size(); + for (int j = 1; j <= poly->size(); j++) { + gl_draw_triangle(shaderinfo, ¢er, &poly->at(j - 1), &poly->at(j % poly->size()), false, true, false, 0, mirrored); + } + } + glEnd(); + } + } +} + +void PolySet::render_edges(colormode_e colormode, csgmode_e csgmode) const +{ + if (colormode == COLORMODE_MATERIAL) + glColor3ub(255, 236, 94); + if (colormode == COLORMODE_CUTOUT) + glColor3ub(171, 216, 86); + if (colormode == COLORMODE_HIGHLIGHT) + glColor4ub(255, 171, 86, 128); + if (colormode == COLORMODE_BACKGROUND) + glColor4ub(150, 150, 150, 128); + if (this->is2d) { + double zbase = csgmode; + for (double z = -zbase/2; z < zbase; z += zbase) + { + for (int i = 0; i < borders.size(); i++) { + const Polygon *poly = &borders[i]; + glBegin(GL_LINE_LOOP); + for (int j = 0; j < poly->size(); j++) { + const Point *p = &poly->at(j); + glVertex3d(p->x, p->y, z); + } + glEnd(); + } + } + for (int i = 0; i < borders.size(); i++) { + const Polygon *poly = &borders[i]; + glBegin(GL_LINES); + for (int j = 0; j < poly->size(); j++) { + const Point *p = &poly->at(j); + glVertex3d(p->x, p->y, -zbase/2); + glVertex3d(p->x, p->y, +zbase/2); + } + glEnd(); + } + } else { + for (int i = 0; i < polygons.size(); i++) { + const Polygon *poly = &polygons[i]; + glBegin(GL_LINE_LOOP); + for (int j = 0; j < poly->size(); j++) { + const Point *p = &poly->at(j); + glVertex3d(p->x, p->y, p->z); + } + glEnd(); + } + } +} + +#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 + } +}; + +CGAL_Nef_polyhedron PolySet::render_cgal_nef_polyhedron() const +{ + if (this->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 < this->polygons.size(); i++) { + pdata_point_lists.push_back(point_list_t()); + for (int j = 0; j < this->polygons[i].size(); j++) { + double x = this->polygons[i][j].x; + double y = this->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 < this->polygons.size(); i++) { + std::list<CGAL_Nef_polyhedron2::Point> plist; + for (int j = 0; j < this->polygons[i].size(); j++) { + double x = this->polygons[i][j].x; + double y = this->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(this); + // 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 + if (this->polygons.size() > 0) assert(this->borders.size() > 0); + CGAL_Nef_polyhedron2 N; + Grid2d<CGAL_Nef_polyhedron2::Point> grid(GRID_COARSE); + + for (int i = 0; i < this->borders.size(); i++) { + std::list<CGAL_Nef_polyhedron2::Point> plist; + for (int j = 0; j < this->borders[i].size(); j++) { + double x = this->borders[i][j].x; + double y = this->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(this); + P.delegate(builder); +#if 0 + std::cout << P; +#endif + CGAL_Nef_polyhedron3 N(P); + return CGAL_Nef_polyhedron(N); + } + return CGAL_Nef_polyhedron(); +} + +#endif /* ENABLE_CGAL */ + +PolySet *AbstractPolyNode::render_polyset(render_mode_e) const +{ + return NULL; +} + +#ifdef ENABLE_CGAL + +CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const +{ + QString cache_id = mk_cache_id(); + if (cgal_nef_cache.contains(cache_id)) { + progress_report(); + PRINT(cgal_nef_cache[cache_id]->msg); + return cgal_nef_cache[cache_id]->N; + } + + print_messages_push(); + + PolySet *ps = render_polyset(RENDER_CGAL); + CGAL_Nef_polyhedron N = ps->render_cgal_nef_polyhedron(); + + cgal_nef_cache.insert(cache_id, new cgal_nef_cache_entry(N), N.weight()); + print_messages_pop(); + progress_report(); + + ps->unlink(); + return N; +} + +#endif /* ENABLE_CGAL */ + +CSGTerm *AbstractPolyNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const +{ + PolySet *ps = render_polyset(RENDER_OPENCSG); + return render_csg_term_from_ps(m, highlights, background, ps, modinst, idx); +} + +CSGTerm *AbstractPolyNode::render_csg_term_from_ps(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, PolySet *ps, const ModuleInstantiation *modinst, int idx) +{ + CSGTerm *t = new CSGTerm(ps, m, QString("n%1").arg(idx)); + if (modinst->tag_highlight && highlights) + highlights->append(t->link()); + if (modinst->tag_background && background) { + background->append(t); + return NULL; + } + return t; +} + |