void DT::save_triangulation_eps(const char *fname, bool debug) const { std::ofstream os; os.open(fname, std::ofstream::out | std::ofstream::trunc); double scale = 512.0; double radius = 3.0 / scale; Point_2 BB[2]; if (debug) { BB[0] = Point_2( -scale, -scale); BB[1] = Point_2(2*scale, 2*scale); } else { BB[0] = Point_2(0, 0); BB[1] = Point_2(scale, scale); } os << "%!PS-Adobe-3.1 EPSF-3.0\n"; os << "%%HiResBoundingBox: " << BB[0] << " " << BB[1] << "\n"; os << "%%BoundingBox: " << BB[0] << " " << BB[1] << "\n"; os << "%%CropBox: " << BB[0] << " " << BB[1] << "\n"; os << "/radius { " << radius << " } def\n"; os << "/p { radius 0 360 arc closepath fill stroke } def\n"; os << "gsave " << scale << " " << scale << " scale\n"; os << (1.0 / scale) << " setlinewidth\n"; // Faces os << "0.75 0.75 0.75 setrgbcolor\n"; CDT::Face_iterator fi; for (fi = dt.faces_begin(); fi != dt.faces_end(); ++fi) { if (!fi->info().main_face) continue; Point_2 p0 = fi->vertex(0)->point(), p1 = fi->vertex(1)->point(), p2 = fi->vertex(2)->point(); os << p0 << " moveto " << p1 << " lineto " << p2 << " lineto closepath " << (debug ? "fill" : "stroke") << "\n"; } // Edges os << "0.25 0.25 0.25 setrgbcolor\n"; CDT::Edge_iterator ei; for (ei = dt.edges_begin(); ei != dt.edges_end(); ++ei) { const FH fh = ei->first; const int i = ei->second; Point_2 p0 = fh->vertex(CDT::cw(i))->point(), p1 = fh->vertex(CDT::ccw(i))->point(); os << p0 << " moveto " << p1 << " lineto stroke\n"; } // Vertices os << "0 0 0 setrgbcolor\n"; for (unsigned i = 0; i < sites.size(); ++i) os << sites[i].vertex->point() << " p\n"; os << "grestore\n"; // Bounding Box if (debug) { os << "0 0 0 setrgbcolor\n"; os << "1.0 setlinewidth\n"; os << "0 0 moveto 0 " << scale << " rlineto " << scale << " 0 rlineto 0 " << -scale << " rlineto closepath stroke\n"; } os.close(); }
bool Delaunay2dMesh::buildMesh( const std::vector<CCVector2>& points2D, const std::vector<int>& segments2D, char* outputErrorStr/*=0*/) { #if defined(USE_CGAL_LIB) //CGAL boilerplate typedef CGAL::Exact_predicates_inexact_constructions_kernel K; //We define a vertex_base with info. The "info" (size_t) allow us to keep track of the original point index. typedef CGAL::Triangulation_vertex_base_with_info_2<size_t, K> Vb; typedef CGAL::Constrained_triangulation_face_base_2<K> Fb; typedef CGAL::No_intersection_tag Itag; //This tag could ben changed if we decide to handle intersection typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds; typedef CGAL::Constrained_Delaunay_triangulation_2<K, Tds, Itag> CDT; typedef CDT::Point cgalPoint; std::vector< std::pair<cgalPoint, size_t > > constraints; size_t constrCount = segments2D.size(); try { constraints.reserve(constrCount); } catch (const std::bad_alloc&) { if (outputErrorStr) strcpy(outputErrorStr, "Not enough memory"); return false; }; //We create the Constrained Delaunay Triangulation (CDT) CDT cdt; //We build the constraints for(size_t i = 0; i < constrCount; ++i) { const CCVector2 * pt = &points2D[segments2D[i]]; constraints.push_back(std::make_pair(cgalPoint(pt->x, pt->y), segments2D[i])); } //The CDT is built according to the constraints cdt.insert(constraints.begin(), constraints.end()); m_numberOfTriangles = static_cast<unsigned >(cdt.number_of_faces()); m_triIndexes = new int[cdt.number_of_faces()*3]; //The cgal data structure is converted into CC one if (m_numberOfTriangles > 0) { int faceCount = 0; for (CDT::Face_iterator face = cdt.faces_begin(); face != cdt.faces_end(); ++face, faceCount+=3) { m_triIndexes[0+faceCount] = static_cast<int>(face->vertex(0)->info()); m_triIndexes[1+faceCount] = static_cast<int>(face->vertex(1)->info()); m_triIndexes[2+faceCount] = static_cast<int>(face->vertex(2)->info()); }; } m_globalIterator = m_triIndexes; m_globalIteratorEnd = m_triIndexes + 3*m_numberOfTriangles; return true; #else if (outputErrorStr) strcpy(outputErrorStr, "CGAL library not supported"); return false; #endif }
bool Delaunay2dMesh::buildMesh( const std::vector<CCVector2>& points2D, const std::vector<int>& segments2D, char* outputErrorStr/*=0*/) { #if defined(USE_TRIANGLE_LIB) //we use the external library 'Triangle' triangulateio in; memset(&in,0,sizeof(triangulateio)); in.numberofpoints = static_cast<int>(points2D.size()); in.pointlist = (REAL*)(&points2D[0]); in.segmentlist = (int*)(&segments2D[0]); assert((segments2D.size() & 1) == 0); in.numberofsegments = static_cast<int>(segments2D.size()/2); triangulateio out; memset(&out,0,sizeof(triangulateio)); try { triangulate ( "pczBPNIOQY", &in, &out, 0 ); } catch (std::exception& e) { if (outputErrorStr) strcpy(outputErrorStr,e.what()); return false; } catch (...) { if (outputErrorStr) strcpy(outputErrorStr,"Unknown error"); return false; } m_numberOfTriangles = out.numberoftriangles; if (m_numberOfTriangles > 0) { m_triIndexes = out.trianglelist; //remove non existing points int* _tri = out.trianglelist; for (int i=0; i<out.numberoftriangles; ) { if ( _tri[0] >= in.numberofpoints || _tri[1] >= in.numberofpoints || _tri[2] >= in.numberofpoints) { int lasTriIndex = (out.numberoftriangles-1) * 3; _tri[0] = out.trianglelist[lasTriIndex + 0]; _tri[1] = out.trianglelist[lasTriIndex + 1]; _tri[2] = out.trianglelist[lasTriIndex + 2]; --out.numberoftriangles; } else { _tri += 3; ++i; } } //Reduce memory size if (out.numberoftriangles < static_cast<int>(m_numberOfTriangles)) { assert(out.numberoftriangles > 0); realloc(m_triIndexes, sizeof(int)*out.numberoftriangles*3); m_numberOfTriangles = out.numberoftriangles; } } trifree(out.segmentmarkerlist); trifree(out.segmentlist); m_globalIterator = m_triIndexes; m_globalIteratorEnd = m_triIndexes + 3*m_numberOfTriangles; return true; #elif defined(USE_CGAL_LIB) //CGAL boilerplate typedef CGAL::Exact_predicates_inexact_constructions_kernel K; //We define a vertex_base with info. The "info" (size_t) allow us to keep track of the original point index. typedef CGAL::Triangulation_vertex_base_with_info_2<size_t, K> Vb; typedef CGAL::Constrained_triangulation_face_base_2<K> Fb; typedef CGAL::No_intersection_tag Itag; //This tag could ben changed if we decide to handle intersection typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds; typedef CGAL::Constrained_Delaunay_triangulation_2<K, Tds, Itag> CDT; typedef CDT::Point cgalPoint; std::vector< std::pair<cgalPoint, size_t > > constraints; size_t constrCount = segments2D.size(); try { constraints.reserve(constrCount); } catch (const std::bad_alloc&) { if (outputErrorStr) strcpy(outputErrorStr, "Not enough memory"); return false; }; //We create the Constrained Delaunay Triangulation (CDT) CDT cdt; //We build the constraints for(size_t i = 0; i < constrCount; ++i) { const CCVector2 * pt = &points2D[segments2D[i]]; constraints.push_back(std::make_pair(cgalPoint(pt->x, pt->y), segments2D[i])); } //The CDT is built according to the constraints cdt.insert(constraints.begin(), constraints.end()); m_numberOfTriangles = static_cast<unsigned >(cdt.number_of_faces()); m_triIndexes = new int[cdt.number_of_faces()*3]; //The cgal data structure is converted into CC one if (m_numberOfTriangles > 0) { int faceCount = 0; for (CDT::Face_iterator face = cdt.faces_begin(); face != cdt.faces_end(); ++face, faceCount+=3) { m_triIndexes[0+faceCount] = static_cast<int>(face->vertex(0)->info()); m_triIndexes[1+faceCount] = static_cast<int>(face->vertex(1)->info()); m_triIndexes[2+faceCount] = static_cast<int>(face->vertex(2)->info()); }; } m_globalIterator = m_triIndexes; m_globalIteratorEnd = m_triIndexes + 3*m_numberOfTriangles; return true; #else if (outputErrorStr) strcpy(outputErrorStr, "Triangle library not supported"); return false; #endif }