diff options
author | Don Bright <hugh.m.bright@gmail.com> | 2013-12-15 03:12:01 (GMT) |
---|---|---|
committer | Don Bright <hugh.m.bright@gmail.com> | 2013-12-15 03:12:01 (GMT) |
commit | 804ec858d9bd832629a2b00ebe689f2d11e4cbe5 (patch) | |
tree | 72ba912a89a66345025aa1ff7540b7d482a742d9 /src | |
parent | 09d60fd5afd54f1537ff6f5349f6466be8401d01 (diff) |
triangulation of near-planar PolySet faces
Diffstat (limited to 'src')
-rw-r--r-- | src/CGAL_Nef_polyhedron.cc | 2 | ||||
-rw-r--r-- | src/cgalutils.cc | 27 | ||||
-rw-r--r-- | src/cgalutils.h | 5 | ||||
-rw-r--r-- | src/dxftess-cgal.cc | 119 |
4 files changed, 127 insertions, 26 deletions
diff --git a/src/CGAL_Nef_polyhedron.cc b/src/CGAL_Nef_polyhedron.cc index 2d5bba5..8b54eba 100644 --- a/src/CGAL_Nef_polyhedron.cc +++ b/src/CGAL_Nef_polyhedron.cc @@ -100,7 +100,7 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() ps = new PolySet(); CGAL_Polyhedron P; this->p3->convert_to_Polyhedron(P); - bool err = createPolySetFromPolyhedron(P, ps); + bool err = createPolySetFromPolyhedron(P, *ps); if (err) delete ps; } catch (const CGAL::Precondition_exception &e) { diff --git a/src/cgalutils.cc b/src/cgalutils.cc index bb46f1c..12e743d 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -8,10 +8,9 @@ #include <map> -PolySet *createPolySetFromPolyhedron(const CGAL_Polyhedron &p) +bool createPolySetFromPolyhedron(const CGAL_Polyhedron &p, PolySet &ps) { - PolySet *ps = new PolySet(); - + bool err = false; typedef CGAL_Polyhedron::Vertex Vertex; typedef CGAL_Polyhedron::Vertex_const_iterator VCI; typedef CGAL_Polyhedron::Facet_const_iterator FCI; @@ -35,13 +34,13 @@ PolySet *createPolySetFromPolyhedron(const CGAL_Polyhedron &p) double x3 = CGAL::to_double(v3.point().x()); double y3 = CGAL::to_double(v3.point().y()); double z3 = CGAL::to_double(v3.point().z()); - ps->append_poly(); - ps->append_vertex(x1, y1, z1); - ps->append_vertex(x2, y2, z2); - ps->append_vertex(x3, y3, z3); + ps.append_poly(); + ps.append_vertex(x1, y1, z1); + ps.append_vertex(x2, y2, z2); + ps.append_vertex(x3, y3, z3); } while (hc != hc_end); } - return ps; + return err; } #undef GEN_SURFACE_DEBUG @@ -127,22 +126,20 @@ public: } }; -CGAL_Polyhedron *createPolyhedronFromPolySet(const PolySet &ps) +bool createPolyhedronFromPolySet(const PolySet &ps, CGAL_Polyhedron &p) { - CGAL_Polyhedron *P = NULL; + bool err = false; CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION); try { - P = new CGAL_Polyhedron; CGAL_Build_PolySet builder(ps); - P->delegate(builder); + p.delegate(builder); } catch (const CGAL::Assertion_exception &e) { PRINTB("CGAL error in CGAL_Build_PolySet: %s", e.what()); - delete P; - P = NULL; + err = true; } CGAL::set_error_behaviour(old_behaviour); - return P; + return err; } CGAL_Iso_cuboid_3 bounding_box( const CGAL_Nef_polyhedron3 &N ) diff --git a/src/cgalutils.h b/src/cgalutils.h index 0e7fbb5..8f7e4dd 100644 --- a/src/cgalutils.h +++ b/src/cgalutils.h @@ -2,8 +2,9 @@ #define CGALUTILS_H_ #include <cgal.h> -bool createPolySetFromPolyhedron(const CGAL_Polyhedron &p, class PolySet &ps); -bool createPolyhedronFromPolySet(const class PolySet &ps, CGAL_Polyhedron &p); +#include "polyset.h" +bool createPolySetFromPolyhedron(const CGAL_Polyhedron &p, PolySet &ps); +bool createPolyhedronFromPolySet(const PolySet &ps, CGAL_Polyhedron &p); CGAL_Iso_cuboid_3 bounding_box( const CGAL_Nef_polyhedron3 &N ); CGAL_Iso_rectangle_2e bounding_box( const CGAL_Nef_polyhedron2 &N ); diff --git a/src/dxftess-cgal.cc b/src/dxftess-cgal.cc index d6f592f..6899598 100644 --- a/src/dxftess-cgal.cc +++ b/src/dxftess-cgal.cc @@ -336,19 +336,122 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, Vector2d scale, bool u } } -void triangulate_polygon( const PolySet::Polygon &pgon, std::vector<PolySet::Polygon> &triangles ) -{ +typedef enum { XYPLANE, YZPLANE, XZPLANE, NONE } projection_t; + +Vector2d get_projected_point( Vector3d v, projection_t projection ) { + Vector2d v2(0,0); + if (projection==XYPLANE) { v2.x() = v.x(); v2.y() = v.y(); } + else if (projection==XZPLANE) { v2.x() = v.x(); v2.y() = v.z(); } + else if (projection==YZPLANE) { v2.x() = v.y(); v2.y() = v.z(); } + return v2; +} +CGAL_Point_3 cgp( Vector3d v ) { return CGAL_Point_3( v.x(), v.y(), v.z() ); } +/* near-planar polygons in 3d can be projected into 2d, but you have to +be careful. if you project, say, 0,0,0 0,1,0 0,1,1 0,0,1 onto the XY plane +you will not get a polygon, you will get a skinny line thing. */ +projection_t find_good_projection( PolySet::Polygon pgon ) { + // step 1 - find 3 non-collinear points in the input + if (pgon.size()<3) return NONE; + Vector3d v1,v2,v3; + v1 = v2 = v3 = pgon[0]; + for (size_t i=0;i<pgon.size();i++) { + if (pgon[i]!=v1) { v2=pgon[i]; break; } + } + if (v1==v2) return NONE; + for (size_t i=0;i<pgon.size();i++) { + if (!CGAL::collinear( cgp(v1), cgp(v2), cgp(pgon[i]) )) { + v3=pgon[i]; break; + } + } + if (CGAL::collinear( cgp(v1), cgp(v2), cgp(v3) ) ) return NONE; + // step 2 - find which direction is best for projection. planes use + // the equation ax+by+cz+d = 0. a,b, and c determine the direction the + // plane is in. we want to find which projection of the 'normal vector' + // would make the smallest shadow if projected onto the given plane. + // 'quadrance' (distance squared) can tell this w/o using sqrt. + CGAL::Plane_3<CGAL_Kernel3> pl( cgp(v1), cgp(v2), cgp(v3) ); + NT3 qxy = pl.a()*pl.a()+pl.b()*pl.b(); + NT3 qyz = pl.b()*pl.b()+pl.c()*pl.c(); + NT3 qxz = pl.c()*pl.c()+pl.a()*pl.a(); + NT3 min = std::min(qxy,std::min(qyz,qxz)); + if (min==qxy) return XYPLANE; + else if (min==qyz) return YZPLANE; + return XZPLANE; } -/* given a 3d PolySet with 'near planar' faces, triangulate the faces -so CGAL Nef Polyhedron will accept them. */ +void triangulate_polygon( const PolySet::Polygon &pgon, std::vector<PolySet::Polygon> &triangles, projection_t projection ) +{ + CDT cdt; + std::vector<Vertex_handle> vhandles; + std::map<CDTPoint,Vector3d> vertmap; + CGAL::Orientation original_orientation; + std::vector<CDTPoint> orpgon; + for (size_t i = 0; i < pgon.size(); i++) { + Vector3d v3 = pgon.at(i); + Vector2d v2 = get_projected_point( v3, projection ); + CDTPoint cdtpoint = CDTPoint(v2.x(),v2.y()); + vertmap[ cdtpoint ] = v3; + Vertex_handle vh = cdt.insert( cdtpoint ); + vhandles.push_back(vh); + orpgon.push_back( cdtpoint ); + } + original_orientation = CGAL::orientation_2( orpgon.begin(),orpgon.end() ); + for (size_t i = 0; i < vhandles.size(); i++ ) { + int vindex1 = (i+0); + int vindex2 = (i+1)%vhandles.size(); + cdt.insert_constraint( vhandles[vindex1], vhandles[vindex2] ); + } + std::list<CDTPoint> list_of_seeds; + CGAL::refine_Delaunay_mesh_2_without_edge_refinement(cdt, + list_of_seeds.begin(), list_of_seeds.end(), DummyCriteria<CDT>()); + + CDT::Finite_faces_iterator fit; + for( fit=cdt.finite_faces_begin(); fit!=cdt.finite_faces_end(); fit++ ) + { + if(fit->is_in_domain()) { + CDTPoint p1 = cdt.triangle( fit )[0]; + CDTPoint p2 = cdt.triangle( fit )[1]; + CDTPoint p3 = cdt.triangle( fit )[2]; + Vector3d v1 = vertmap[p1]; + Vector3d v2 = vertmap[p2]; + Vector3d v3 = vertmap[p3]; + PolySet::Polygon pgon; + if (CGAL::orientation(p1,p2,p3)==original_orientation) { + pgon.push_back(v1); + pgon.push_back(v2); + pgon.push_back(v3); + } else { + pgon.push_back(v3); + pgon.push_back(v2); + pgon.push_back(v1); + } + triangles.push_back( pgon ); + } + } +} + +/* given a 3d PolySet with 'near planar' faces, triangulate the faces. +See Issue 340... this is so CGAL Nef Polyhedron will accept them. +This code assumes the input polyset has simple polygon faces with no holes. */ void tessellate_3d_faces( const PolySet &inps, PolySet &outps ) { + PRINTB("tess 3d %i",inps.polygons.size()); + PRINTB("%s < input ps",inps.dump()); for (size_t i = 0; i < inps.polygons.size(); i++) { - const PolySet::Polygon *pgon = &inps.polygons[i]; - for (size_t j = 0; j < pgon->size(); j++) { - Vector3d v = pgon->at(j); - } + const PolySet::Polygon pgon = inps.polygons[i]; + if (pgon.size()<3) continue; + std::vector<PolySet::Polygon> triangles; + projection_t projection = find_good_projection( pgon ); + triangulate_polygon( pgon, triangles, projection ); + for (size_t j=0;j<triangles.size();j++) { + PolySet::Polygon t = triangles[j]; + outps.append_poly(); + outps.append_vertex(t[0].x(),t[0].y(),t[0].z()); + outps.append_vertex(t[1].x(),t[1].y(),t[1].z()); + outps.append_vertex(t[2].x(),t[2].y(),t[2].z()); + } } + PRINTB("tess 3d done %i",outps.polygons.size()); + PRINTB("%s < output ps",outps.dump()); } |