#ifndef CGAL_MESH_H #define CGAL_MESH_H #include #include #include #include #include #include #include #include #include #include #include //CGAL_BEGIN_NAMESPACE using namespace CGAL; #define INVALID_EDGE Edge(NULL, -1); #define UPDATE {viewer->repaint(); qApp->processEvents(); float ff; for(float f=0.0; f<1.2e6; f++) ff += sin(f);} //#define UPDATE template class Triangulation_finite_vertex_circulator : public Triangulation_vertex_circulator_2 { }; template class Mesh: public Constrained_Delaunay_triangulation_2 { public: QWidget *viewer; typedef Gt Triangulation_geom_traits; typedef Tds Triangulation_data_structure; typedef typename Gt::FT FT; typedef FT Length; typedef FT Square_length; typedef CGAL::Triangulation_2 Tr; typedef CGAL::Constrained_triangulation_2 Ct; typedef CGAL::Constrained_Delaunay_triangulation_2 CDt; // typedef typename CDt::Constraint Constraint; typedef typename CDt::Vertex Vertex; typedef typename CDt::Edge Edge; typedef typename CDt::Face_handle Face_handle; typedef typename CDt::Vertex_handle Vertex_handle; typedef typename CDt::Finite_faces_iterator Finite_faces_iterator; typedef std::pair Constrained_edge; typedef typename Gt::Point_2 Point; typedef std::pair Constraint; typedef std::list List_constraints; typedef Mtraits Mesh_traits; enum Cluster_status {REDUCED,NON_REDUCED}; struct Cluster { Cluster_status status; Length length; FT alpha_min; std::map vertices; }; void write(ostream &f); void read(istream &f); void reset() { cluster_map.clear(); clear(); } private: int current_time; std::multimap Bad_faces; std::list c_edge_queue; std::map insertion_time; std::map insertion_radius_map; std::multimap cluster_map; public: //INSERTION-REMOVAL void refine_mesh(QWidget *v); void bounds(FT &xmin, FT &ymin, FT &xmax, FT &ymax, FT &xcenter, FT &ycenter); void bounding_box(); Mesh(const Geom_traits& gt=Geom_traits()):CDt(gt){}; Mesh(List_constraints& lc, const Geom_traits& gt=Geom_traits()):CDt(gt) { typename List_constraints::iterator lcit=lc.begin(); for( ; lcit != lc.end(); ++lcit) { insert( (*lcit).first, (*lcit).second); } CGAL_triangulation_postcondition(is_valid()); } template Mesh(InputIterator first, InputIterator last, const Geom_traits& gt=Gt()):CDt(gt) { while(first != last){ insert((*first).first, (*first).second); ++first; } CGAL_triangulation_postcondition(is_valid()); } private: void refine_face(Face_handle f); void refine_edge(Vertex_handle va, Vertex_handle vb); void create_clusters(); void create_clusters_of_vertex(Vertex_handle v); void show_clusters(); Vertex_handle insert_middle(Vertex_handle va, Vertex_handle vb); void cut_cluster(Vertex_handle va, Vertex_handle vb); void cut_reduced_cluster(Vertex_handle va, Vertex_handle vb); void cut_cluster_edge(Vertex_handle va, Vertex_handle vb); Vertex_handle insert_in_c_edge(Vertex_handle va, Vertex_handle vb, Point p); void fill_edge_queue(); void fill_facette_map(); void process_edge_queue(); void process_facette_map(); void update_c_edge_queue(Vertex_handle va, Vertex_handle vb, Vertex_handle vm); void update_facette_map(Vertex_handle v); void update_cluster(Vertex_handle va, Vertex_handle vb, Vertex_handle vm); inline Edge edge_between(Vertex_handle va, Vertex_handle vb); //CHECK bool is_encroached(Vertex_handle va, Vertex_handle vb, Point p); bool is_encroached(Vertex_handle va, Vertex_handle vb); bool min_insertion_radius(Vertex_handle v, Cluster &c); bool is_bad(Face_handle f); bool is_small_angle(Vertex_handle vleft, Vertex_handle vmiddle, Vertex_handle vright); bool is_cluster_reduced(const Cluster&); //look cluster status bool is_cluster(Vertex_handle va, Vertex_handle vb); FT shortest_edge_of_cluster(Vertex_handle v, Cluster &cluster); void check_cluster_status( Cluster&); // HELPING functions Square_length shortest_edge(Face_handle f); FT angle(Vertex_handle vleft, Vertex_handle vmiddle, Vertex_handle vright); FT circumradius_to_shortest_edge_ratio(Face_handle f); FT insertion_radius(Vertex_handle v); Vertex_handle nearest_incident_vertex(Vertex_handle v); bool find_cluster(Vertex_handle va, Vertex_handle vb, Cluster &c); inline Vertex_circulator incr(Vertex_circulator &c) { c++; if(Vertex_handle(c) == infinite_vertex()) { c++; } return c; } inline Vertex_circulator incr_constraint(Vertex_handle v, Vertex_circulator &c) { Vertex_circulator cbegin = c; incr(c); while(!edge_between(v, c).first->is_constrained(edge_between(v, c).second) && c != cbegin ) { incr(c); } return c; } inline Vertex_circulator succ(Vertex_circulator c) { return incr(c); } inline Vertex_circulator succ_constraint(Vertex_handle v, Vertex_circulator c) { return incr_constraint(v, c); } inline bool get_conflicting_edges(const Point &p, list &cel) { //cel = constrained edges list Face_handle start; int li; Locate_type lt; Face_handle fh = locate(p,lt,li, start); switch(lt) { case OUTSIDE_AFFINE_HULL: case VERTEX: return false; case FACE: case EDGE: case OUTSIDE_CONVEX_HULL: propagate_conflicting_edges(p,fh,0,cel); propagate_conflicting_edges(p,fh,1,cel); propagate_conflicting_edges(p,fh,2,cel); return true; } CGAL_triangulation_assertion(false); return false; } //private: inline void propagate_conflicting_edges (const Point &p, Face_handle fh, int i, list &cel) { if(is_infinite(make_pair(fh,i))) return; Face_handle fn = fh->neighbor(i); Edge e(fh,i); if(!is_encroached(e.first->vertex(cw(e.second)), e.first->vertex(ccw(e.second)), p)) { return; } if ( fh->is_constrained(i)) {// || ! test_conflict(p,fn)) { cel.push_back(Constrained_edge(e.first->vertex(cw(e.second)), e.first->vertex(ccw(e.second))));//Edge(fn, fn->index(fh)); return; } int j = fn->index(fh); propagate_conflicting_edges(p,fn,ccw(j),cel); propagate_conflicting_edges(p,fn,cw(j),cel); return; } bool is_infinite(Face_handle fh) { Vertex_handle va, vb, vc; va=fh->vertex(0); vb=fh->vertex(1); vc=fh->vertex(2); if(va==infinite_vertex() || vb==infinite_vertex() || vc==infinite_vertex()) return true; //check whether the face still exists... if(!is_face(va, vb, vc)) return true; return false; } bool is_infinite(Edge e) { Vertex_handle va, vb; va=e.first->vertex(cw(e.second)); vb=e.first->vertex(ccw(e.second)); if(va==infinite_vertex() || vb==infinite_vertex()) return true; //check whether the face still exists... if(!is_edge(va, vb)) return true; return false; } }; template bool Mesh:: find_cluster(Vertex_handle va, Vertex_handle vb, Cluster &c) { // check if vb is in any cluster of va pair::iterator, multimap::iterator> range = cluster_map.equal_range(va); for(multimap::iterator it = range.first; it != range.second; it++) { Cluster &cl = it->second; if(cl.vertices.find(vb)!=cl.vertices.end()) { c = it->second; return true; } } return false; } //the function that writes a file template void Mesh:: write(ostream &f) { int nedges = 0; Edge_iterator eit = edges_begin(); while(eit != edges_end()) { if((*eit).first->is_constrained((*eit).second)) nedges++; eit++; } f<is_constrained((*eit).second)) { f<<(*eit).first->vertex(cw((*eit).second))->point().x()<<" "; f<<(*eit).first->vertex(cw((*eit).second))->point().y()<<" "; f<<(*eit).first->vertex(ccw((*eit).second))->point().x()<<" "; f<<(*eit).first->vertex(ccw((*eit).second))->point().y()< void Mesh:: read(istream &f) { int nedges = 0; clear(); f>>nedges; for(int n=0; n>x1>>y1>>x2>>y2; insert(Point(x1, y1), Point(x2, y2)); } } template void Mesh:: fill_edge_queue() { Edge_iterator ei = edges_begin(); while(ei != edges_end()) { Vertex_handle va = (*ei).first->vertex(cw((*ei).second)); Vertex_handle vb = (*ei).first->vertex(ccw((*ei).second)); if((*ei).first->is_constrained((*ei).second) && is_encroached(va, vb)&& va!=infinite_vertex()&& vb!=infinite_vertex()) { c_edge_queue.push_back(make_pair(va, vb)); } ei++; } } //it is necessarry for process_facette_map template void Mesh:: fill_facette_map() { Face_iterator fit = faces_begin(); while(fit != faces_end()) { if(!is_infinite(fit)) { if( is_bad(fit)) { Bad_faces.insert(make_pair( circumradius_to_shortest_edge_ratio(fit), fit)); } } fit++; } } //is used by process_edge_queue template void Mesh:: process_edge_queue() { while(! c_edge_queue.empty() ) { Constrained_edge ce; ce=c_edge_queue.front(); c_edge_queue.pop_front(); // if ce is not an edge, choose another. should be more robust while(!is_edge(ce.first, ce.second) && !c_edge_queue.empty()) { ce=c_edge_queue.front(); c_edge_queue.pop_front(); } Face_handle fh; int i; if ( is_edge( ce.first, ce.second, fh,i)) { if(fh->is_constrained(i) && is_encroached(ce.first, ce.second)) { //Vertex_handle va = ce.first; //Vertex_handle vb = ce.second; refine_edge(ce.first, ce.second); //c_edge_queue.pop_front(); } } } } template void Mesh:: process_facette_map() { if(Bad_faces.empty()) { } while( !Bad_faces.empty()) { Face_handle Bf = (*(Bad_faces.begin())).second; while(is_infinite(Bf)) { Bad_faces.erase(Bad_faces.begin()); if(Bad_faces.empty()) return; Bf = (*(Bad_faces.begin())).second; } Bad_faces.erase(Bad_faces.begin()); Vertex_handle va, vb, vc; va = Bf->vertex(0); vb = Bf->vertex(1); vc = Bf->vertex(2); if( is_face(va,vb,vc )&&is_bad(Bf)) { refine_face(Bf); } } } //this function split all the segments that are encroached template void Mesh:: refine_edge(Vertex_handle va, Vertex_handle vb) { UPDATE; Face_handle f; int i; is_edge(va, vb, f, i); if( !is_cluster(va,vb) && !is_cluster(vb,va) && f->is_constrained(i)) { Vertex_handle vm = insert_middle(va,vb); update_c_edge_queue(va, vb, vm); update_facette_map(vm); return; } else if (is_cluster(va,vb) && is_cluster(vb,va)) { Vertex_handle vm = insert_middle(va,vb); update_c_edge_queue(va, vb, vm); update_facette_map(vm); if(vm.is_null()) { exit(-1); } update_cluster(va,vb,vm); update_cluster(vb,va,vm); return; } Vertex_handle vaa = is_cluster(va,vb) ? va : vb; Vertex_handle vbb = is_cluster(va,vb) ? vb : va; cut_cluster_edge(vaa,vbb); } //split all the bad faces template void Mesh:: refine_face(Face_handle f) { Point pc; Vertex_handle v; //check if the face still exists pc = circumcenter(f); list conflicts; list::iterator out_conflicts=c_edge_queue.begin(); if(get_conflicting_edges(pc, c_edge_queue)) { if(!c_edge_queue.empty()){ while(! c_edge_queue.empty() ) { Constrained_edge ce; ce=c_edge_queue.front(); c_edge_queue.pop_front(); while(!is_edge(ce.first, ce.second) && !c_edge_queue.empty()) { ce=c_edge_queue.front(); c_edge_queue.pop_front(); } Face_handle fh; int i; if ( is_edge( ce.first, ce.second, fh,i)) { if( fh->is_constrained(i) && is_encroached(ce.first, ce.second)) { Vertex_handle va = ce.first; Vertex_handle vb = ce.second; Square_length rg = shortest_edge(f); Cluster cluster; Vertex_handle vaa = is_cluster(va,vb) ? va : vb; Vertex_handle vbb = is_cluster(va,vb) ? vb : va; find_cluster(vaa, vbb, cluster); Length rmin = shortest_edge_of_cluster(vaa, cluster); if(rmin >rg) { refine_edge(ce.first, ce.second); } else { exit(-1); } //c_edge_queue.pop_front(); } } } } else { Face_handle start; int li; Locate_type lt; Face_handle fh = locate(pc,lt,li, start); if(lt!=OUTSIDE_CONVEX_HULL) { v = insert(pc); update_facette_map(v); } } } UPDATE; current_time++; insertion_time[v] = current_time; //flip_around(v); } template void Mesh:: create_clusters() { Vertex_iterator vit = vertices_begin(); while(vit != vertices_end()) { create_clusters_of_vertex(vit); vit++; } } template void Mesh:: create_clusters_of_vertex(Vertex_handle v) { // prerequisite: at least too vertices must exist in the triangulation Vertex_circulator vcirc = incident_vertices(v); incr_constraint(v, vcirc); Vertex_circulator vbegin = vcirc; incr_constraint(v, vcirc); do { if(!is_small_angle(vcirc, v, succ_constraint(v, vcirc))) { break; } incr_constraint(v, vcirc); } while(vcirc!=vbegin); // now vcirc points to: // * either the point JUST BEFORE the first large angle // * or vbegin if such an angle has not been encountered // begin with the second case: a single cluster exists if(vcirc==vbegin) { FT min_angle = 1000.0; // a BIG value for an angle Cluster cl; do{ if(is_small_angle(vcirc, v, succ_constraint(v, vcirc))) { cl.vertices.insert(make_pair(vcirc, squared_distance(v->point(), vcirc->point()))); min_angle = min(min_angle, angle(vcirc, v, succ_constraint(v, vcirc))); } incr_constraint(v, vcirc); }while(vcirc!=vbegin); cl.alpha_min = min_angle; cluster_map.insert(make_pair(v, cl)); } else { // the first case vbegin = vcirc; do{ Cluster cl; cl.alpha_min = 1000; do { cl.vertices.insert(make_pair(vcirc, squared_distance(v->point(), vcirc->point()))); cl.alpha_min = min(cl.alpha_min, angle(vcirc, v, succ_constraint(v, vcirc))); incr_constraint(v, vcirc); } while(is_small_angle(vcirc, v, succ_constraint(v, vcirc))); cluster_map.insert(make_pair(v, cl)); } while(vcirc != vbegin); } } template void Mesh:: show_clusters() { multimap::iterator cmit = cluster_map.begin(); while(cmit != cluster_map.end()) { Vertex_handle v = (*cmit).first; map::iterator cit = (*cmit).second.vertices.begin(); while(cit != (*cmit).second.vertices.end()) { Vertex_handle v1 = (*cit).first; cit++; } cmit++; } } //refine the cluster template void Mesh:: cut_cluster(Vertex_handle va, Vertex_handle vb) { Cluster c; find_cluster(va, vb, c); check_cluster_status(c); if( !is_cluster_reduced(c)) { cut_cluster_edge(va, vb); } else { cut_reduced_cluster(va, vb); } } //refine the reduced_cluster template void Mesh:: cut_reduced_cluster(Vertex_handle va, Vertex_handle vb) { Cluster c; find_cluster(va, vb, c); Vertex_handle vm; if(is_cluster_reduced(c)) { // vm = insert_in_c_edge(va, vb, va->point() + (vb->point() - va->point())/2.0); } update_c_edge_queue(va, vb, vm); update_facette_map(vm); } //refine the cluster edges template void Mesh:: cut_cluster_edge(Vertex_handle va, Vertex_handle vb) { //seulement les constraints Cluster c; find_cluster(va, vb, c); Square_length l2 = 2.0; //shortest_edge_of_cluster(va, c)/1.001; Square_length L2 = squared_distance(va->point(), vb->point()); if(L2 > l2) { FT rapport = pow(2.0, rint(0.5*log(L2/l2)/log(2.0)))*::sqrt(l2/(L2*4)); Point pc=va->point()+(vb->point()-va->point())*rapport; Vertex_handle vc = insert_in_c_edge(va,vb,pc); flip_around(vc); update_c_edge_queue(va, vb, vc); update_facette_map(vc); update_cluster(va, vb, vc); } } template Mesh::Vertex_handle Mesh:: insert_middle(Vertex_handle va, Vertex_handle vb) { Point midpoint; midpoint = va->point() + (vb->point() - va->point())/2.0 ; return insert_in_c_edge(va,vb, midpoint); } //insert in constraint edge the middle template Mesh::Vertex_handle Mesh:: insert_in_c_edge(Vertex_handle va, Vertex_handle vb, Point p) { Face_handle f; int i; is_edge(va, vb, f, i); Vertex_handle v = Ct::special_insert_in_edge(p, f, i); flip_around(v) ; update_c_edge_queue(va, vb, v); return v; } //update the encroached segments list template void Mesh:: update_c_edge_queue(Vertex_handle va, Vertex_handle vb, Vertex_handle vm) { //c_edge_queue.pop_back(); Face_circulator fc = incident_faces(vm); Face_circulator fcbegin = fc; if(fc.is_empty()) return; do { int i; for(i=0; i<3; i++) { Edge e=Edge(fc, i); Vertex_handle v1=e.first->vertex(cw(i)); Vertex_handle v2=e.first->vertex(ccw(i)); if(is_encroached(v1, v2)&& e.first->is_constrained(i)&& v1!=infinite_vertex()&&v2!=infinite_vertex()) { c_edge_queue.push_back(Constrained_edge(v1, v2)); } } fc++; } while(fc != fcbegin); if(is_encroached(va, vm)) { c_edge_queue.push_back(Constrained_edge(va, vm)); } if(is_encroached(vb, vm)) { c_edge_queue.push_back(Constrained_edge(vb, vm)); } } template void Mesh:: update_facette_map(Vertex_handle v) { Face_circulator fc = v->incident_faces(); Face_circulator fcbegin = fc; do { if(!is_infinite(fc)) { if(is_bad(fc)) { Bad_faces.insert(make_pair( circumradius_to_shortest_edge_ratio(fc), fc)); } } fc++; } while(fc!=fcbegin); } //ok template void Mesh:: update_cluster(Vertex_handle va, Vertex_handle vb, Vertex_handle vm) { multimap::iterator it_va_cluster = cluster_map.find(va); int n_va_cluster = cluster_map.count(va); for(int i=0; i &vertices = (*it_va_cluster).second.vertices; map::iterator it_vertices = vertices.find(vb); if(it_vertices != vertices.end()) { vertices.erase(vb); if(va.is_null()) {} if(vm.is_null()) {} vertices[vm] = (squared_distance(va->point(), vm->point())); break; } it_va_cluster++; } multimap::iterator it_vb_cluster = cluster_map.find(vb); int n_vb_cluster = cluster_map.count(vb); for(int i=0; i &vertices = (*it_vb_cluster).second.vertices; map::iterator it_vertices = vertices.find(va); if(it_vertices != vertices.end()) { vertices.erase(va); vertices[vm] = (squared_distance(vb->point(), vm->point())); break; } it_vb_cluster++; } } template inline Mesh::Edge Mesh::edge_between(Vertex_handle va, Vertex_handle vb) { Edge_circulator ec = va->incident_edges(); Edge_circulator ecbegin = ec; do { Edge e = (*ec); Face_handle f = e.first; int iedge = e.second; Vertex_handle v1 = f->vertex(cw(iedge)); Vertex_handle v2 = f->vertex(ccw(iedge)); if((v1 == va && v2 == vb) || (v2 == va && v1 == vb)) { return e; } ec++; } while(ec != ecbegin); cerr<<"invalid edge"< bool Mesh:: is_encroached(Vertex_handle va, Vertex_handle vb, Point p) { Point pm=midpoint(va->point(), vb->point()); if(2.0*::sqrt(squared_distance(pm, p)) < ::sqrt(squared_distance(va->point(), vb->point()))) { return true; } return false; } template bool Mesh:: is_encroached(Vertex_handle va, Vertex_handle vb) { Vertex_iterator vi=vertices_begin(); while(vi!=vertices_end()) { if(is_encroached(va, vb, vi->point())&& va!=Vertex_handle(vi)&& vb!=Vertex_handle(vi)) { return true; } vi++; } return false; } template bool Mesh:: min_insertion_radius(Vertex_handle v, Cluster &c) { } //the measure of faces quality template bool Mesh:: is_bad(Face_handle f) { FT quality = circumradius_to_shortest_edge_ratio(f); if((quality >1) || (quality < 0.5)) //set_a:(>1.0 || <0.4) //set_b:(>1.0 || <0.5) //set_c:(>1.1 || <0.5) //set_d:(>1.1 || <0.4) //set_e:(>0.9 || <0.5) //set_f:(>0.9 || <0.4)//~NOK //set_g:(>0.8 || <0.4)//NOK //set_h:(>0.8 || <0.5) { return TRUE; } else { return FALSE; } // } } // template bool Mesh:: is_small_angle(Vertex_handle vleft, Vertex_handle vmiddle, Vertex_handle vright) { FT cos_alpha; cos_alpha = angle(vleft, vmiddle, vright); if(cos_alpha > 1/2) { return TRUE; //the same cluster } else { return FALSE; //another cluster } } // template bool Mesh:: is_cluster_reduced(const Cluster& c) { return c.status == REDUCED; } template bool Mesh:: is_cluster(Vertex_handle va, Vertex_handle vb) { // check if vb is in any cluster of va pair::iterator, multimap::iterator> range = cluster_map.equal_range(va); for(multimap::iterator it = range.first; it != range.second; it++) { Cluster &cl = it->second; if(cl.vertices.find(vb)!=cl.vertices.end()) { return true; } } return false; } template typename Gt::FT Mesh:: shortest_edge_of_cluster(Vertex_handle v, Cluster &cluster) { map::iterator vit = cluster.vertices.begin(); FT min_edge = squared_distance(((*vit).first)->point(), (*v).point()); vit++; while(vit != cluster.vertices.end()) { FT temp = squared_distance(((*vit).first)->point(), (*v).point()); if(temp < min_edge) { min_edge = temp; } vit++; } return min_edge; } // look if all edges have the same lenght template void Mesh:: check_cluster_status( Cluster& cluster) { Length initl; map::iterator vi = cluster.vertices.begin(); initl = (*(cluster.vertices.find((*vi).first))).second; vi++; for(;vi != cluster.vertices.end(); vi++) { if(( (*(cluster.vertices.find((*vi).first))).second) != initl) { cluster.status = NON_REDUCED; return; } vi++; } cluster.status = REDUCED; } template void Mesh:: bounds(FT &xmin, FT &ymin, FT &xmax, FT &ymax, FT &xcenter, FT &ycenter) { Vertex_iterator vi=vertices_begin(); xmin=xmax=xcenter=vi->point().x(); ymin=ymax=ycenter=vi->point().y(); vi++; while(vi != vertices_end()) { xcenter+=vi->point().x(); ycenter+=vi->point().y(); if(vi->point().x() < xmin) xmin=vi->point().x(); if(vi->point().x() > xmax) xmax=vi->point().x(); if(vi->point().y() < ymin) ymin=vi->point().y(); if(vi->point().y() > ymax) ymax=vi->point().y(); vi++; } xcenter /= number_of_vertices(); ycenter /= number_of_vertices(); } //bounding box template void Mesh:: bounding_box() { FT span; FT xmin, xmax, ymin, ymax, xcenter, ycenter; bounds(xmin, ymin, xmax, ymax, xcenter, ycenter); span = max((xmax-xmin), (ymax-ymin)); Point bb1(xcenter - 1.5*span, ycenter - 1.5*span); Point bb2(xcenter + 1.5*span, ycenter - 1.5*span); Point bb3(xcenter + 1.5*span, ycenter + 1.5*span); Point bb4(xcenter - 1.5*span, ycenter + 1.5*span); insert(bb1); insert(bb2); insert(bb3); insert(bb4); insert(bb1, bb2); insert(bb2, bb3); insert(bb3, bb4); insert(bb4, bb1); } //the angle that are between 2 edges from the triangulation template typename Gt::FT Mesh:: angle(Vertex_handle vleft, Vertex_handle vmiddle, Vertex_handle vright) { Point pa = vleft->point(), pb = vmiddle->point(), pc = vright->point(); FT a, b, c; a = ::sqrt(squared_distance(pb, pc)); b = ::sqrt(squared_distance(pc, pa)); c = ::sqrt(squared_distance(pa, pb)); FT cos_alpha = ((a*a+c*c-b*b)/(2*a*c)); return cos_alpha; } //the shortest edge that are in a triangle template typename Gt::FT Mesh:: shortest_edge(Face_handle f) { Point pa = (f->vertex(0))->point(), pb = (f->vertex(1))->point(), pc = (f->vertex(2))->point(); FT a, b, c; a =(squared_distance(pb, pc)); b =(squared_distance(pc, pa)); c =(squared_distance(pa, pb)); return (min(a, min(b, c))); // regarder la documentation du CGAL sur // MIN (Developer Manual) } //the triangle quality is represented by the //circumradius_to_shortest_edge_ratio value template typename Gt::FT Mesh:: circumradius_to_shortest_edge_ratio(Face_handle f) { Point p; p = circumcenter(f); Point A = (f->vertex(0))->point(); FT radius =::sqrt(squared_distance(p, A)); FT sh_edge =::sqrt(shortest_edge(f)); return (radius/sh_edge); } //insertion radius: the definition template typename Gt::FT Mesh:: insertion_radius(Vertex_handle v) { Vertex_handle v1 = nearest_incident_vertex(v); return (squared_distance(v->point(), v1->point())); } //this function must compute the vertex that are so close to our vertex. template Mesh::Vertex_handle Mesh:: nearest_incident_vertex(Vertex_handle v) { Vertex_handle vbegin, vcurrent, vnearest; Vertex_circulator circ = v->incident_vertices(); vbegin = circ; vnearest = vbegin; circ++; FT dist = (squared_distance(v->point(), vbegin->point())); while((vcurrent = circ) != vbegin) { FT d1 = (squared_distance(v->point(), vcurrent->point())); if(d1 < dist) { vnearest = vcurrent; } circ++; } return vnearest; } //the mesh refine function template void Mesh:: refine_mesh( QWidget *w) { viewer = w; // bounding_box(); create_clusters(); show_clusters(); fill_edge_queue(); fill_facette_map(); process_edge_queue(); process_facette_map(); } //CGAL_END_NAMESPACE #endif