// Copyright (c) 1997-2010 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.1/TDS_2/include/CGAL/Triangulation_data_structure_2.h $ // $Id: Triangulation_data_structure_2.h 871c972 2020-06-03T16:23:22+02:00 Laurent Rineau // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Mariette Yvinec #ifndef CGAL_TRIANGULATION_DATA_STRUCTURE_2_H #define CGAL_TRIANGULATION_DATA_STRUCTURE_2_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace CGAL { template < class Vb = Triangulation_ds_vertex_base_2<>, class Fb = Triangulation_ds_face_base_2<> > class Triangulation_data_structure_2 :public Triangulation_cw_ccw_2 { typedef Triangulation_data_structure_2 Tds; typedef typename Vb::template Rebind_TDS::Other Vertex_base; typedef typename Fb::template Rebind_TDS::Other Face_base; friend class Triangulation_ds_edge_iterator_2; friend class Triangulation_ds_face_circulator_2; friend class Triangulation_ds_edge_circulator_2; friend class Triangulation_ds_vertex_circulator_2; public: // Tools to change the Vertex and Face types of the TDS. template < typename Vb2 > struct Rebind_vertex { typedef Triangulation_data_structure_2 Other; }; template < typename Fb2 > struct Rebind_face { typedef Triangulation_data_structure_2 Other; }; typedef Vertex_base Vertex; typedef Face_base Face; typedef Compact_container Face_range; typedef Compact_container Vertex_range; typedef typename Face_range::size_type size_type; typedef typename Face_range::difference_type difference_type; typedef typename Face_range::iterator Face_iterator; typedef typename Vertex_range::iterator Vertex_iterator; typedef Triangulation_ds_edge_iterator_2 Edge_iterator; typedef Triangulation_ds_face_circulator_2 Face_circulator; typedef Triangulation_ds_vertex_circulator_2 Vertex_circulator; typedef Triangulation_ds_edge_circulator_2 Edge_circulator; typedef Iterator_range > Vertex_handles; typedef Iterator_range > Face_handles; typedef Iterator_range Edges; typedef Vertex_iterator Vertex_handle; typedef Face_iterator Face_handle; typedef std::pair Edge; typedef std::list List_edges; protected: int _dimension; Face_range _faces; Vertex_range _vertices; //CREATORS - DESTRUCTORS public: Triangulation_data_structure_2(); Triangulation_data_structure_2(const Tds &tds); Triangulation_data_structure_2(Triangulation_data_structure_2&& tds) noexcept(noexcept(Face_range(std::move(tds._faces))) && noexcept(Vertex_range(std::move(tds._vertices)))); ~Triangulation_data_structure_2(); Tds& operator= (const Tds &tds); Tds& operator= (Tds&& tds) noexcept(noexcept(Tds(std::move(tds)))); void swap(Tds &tds); //ACCESS FUNCTIONS // We need the const_cast<>s because TDS is not const-correct. Face_range& faces() { return _faces;} Face_range& faces() const { return const_cast(this)->_faces;} Vertex_range& vertices() {return _vertices;} Vertex_range& vertices() const {return const_cast(this)->_vertices;} int dimension() const { return _dimension; } size_type number_of_vertices() const {return vertices().size();} size_type number_of_faces() const ; size_type number_of_edges() const; size_type number_of_full_dim_faces() const; //number of faces stored by tds // TEST FEATURES bool is_vertex(Vertex_handle v) const; bool is_edge(Face_handle fh, int i) const; bool is_edge(Vertex_handle va, Vertex_handle vb) const; bool is_edge(Vertex_handle va, Vertex_handle vb, Face_handle& fr, int& i) const; bool is_face(Face_handle fh) const; bool is_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) const; bool is_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3, Face_handle& fr) const; // ITERATORS AND CIRCULATORS public: // The face_iterator_base_begin gives the possibility to iterate over all // faces in the container independently of the dimension. // public for the need of file_ouput() of Constrained triangulation // should be made private later Face_iterator face_iterator_base_begin() const { return faces().begin(); } Face_iterator face_iterator_base_end() const { return faces().end(); } public: Face_iterator faces_begin() const { if (dimension() < 2) return faces_end(); return faces().begin(); } Face_iterator faces_end() const { return faces().end(); } Face_handles face_handles() const { return make_prevent_deref_range(faces_begin(),faces_end()); } Vertex_iterator vertices_begin() const { return vertices().begin(); } Vertex_iterator vertices_end() const { return vertices().end(); } Vertex_handles vertex_handles() const { return make_prevent_deref_range(vertices_begin(),vertices_end()); } Edge_iterator edges_begin() const { return Edge_iterator(this); } Edge_iterator edges_end() const { return Edge_iterator(this,1); } Edges edges() const { return Edges(edges_begin(),edges_end()); } Face_circulator incident_faces(Vertex_handle v, Face_handle f = Face_handle()) const{ return Face_circulator(v,f); } Vertex_circulator incident_vertices(Vertex_handle v, Face_handle f = Face_handle()) const { return Vertex_circulator(v,f); } Edge_circulator incident_edges(Vertex_handle v, Face_handle f = Face_handle()) const{ return Edge_circulator(v,f); } size_type degree(Vertex_handle v) const { int count = 0; Vertex_circulator vc = incident_vertices(v), done(vc); if ( ! vc.is_empty()) { do { count += 1; } while (++vc != done); } return count; } Vertex_handle mirror_vertex(Face_handle f, int i) const { CGAL_triangulation_precondition ( f->neighbor(i) != Face_handle() && f->dimension() >= 1); return f->neighbor(i)->vertex(mirror_index(f,i)); } int mirror_index(Face_handle f, int i) const { // return the index of opposite vertex in neighbor(i); CGAL_triangulation_precondition (f->neighbor(i) != Face_handle() && f->dimension() >= 1); if (f->dimension() == 1) { CGAL_assertion(i<=1); const int j = f->neighbor(i)->index(f->vertex((i==0) ? 1 : 0)); CGAL_assertion(j<=1); return (j==0) ? 1 : 0; } return ccw( f->neighbor(i)->index(f->vertex(ccw(i)))); } Edge mirror_edge(const Edge e) const { CGAL_triangulation_precondition(e.first->neighbor(e.second) != Face_handle() && e.first->dimension() >= 1); return Edge(e.first->neighbor(e.second), mirror_index(e.first, e.second)); } // MODIFY void flip(Face_handle f, int i); Vertex_handle insert_first(); Vertex_handle insert_second(); Vertex_handle insert_in_face(Face_handle f); Vertex_handle insert_in_edge(Face_handle f, int i); Vertex_handle insert_dim_up(Vertex_handle w = Vertex_handle(), bool orient=true); void remove_degree_3(Vertex_handle v, Face_handle f = Face_handle()); void remove_1D(Vertex_handle v); void remove_second(Vertex_handle v); void remove_first(Vertex_handle v); void remove_dim_down(Vertex_handle v); void dim_down(Face_handle f, int i); Vertex_handle star_hole(List_edges& hole); void star_hole(Vertex_handle v, List_edges& hole); void make_hole(Vertex_handle v, List_edges& hole); // template< class EdgeIt> // Vertex_handle star_hole(EdgeIt edge_begin,EdgeIt edge_end); // template< class EdgeIt> // void star_hole(Vertex_handle v, EdgeIt edge_begin, EdgeIt edge_end); // template< class EdgeIt, class FaceIt> // Vertex_handle star_hole(EdgeIt edge_begin, // EdgeIt edge_end, // FaceIt face_begin, // FaceIt face_end); // template< class EdgeIt, class FaceIt> // void star_hole(Vertex_handle v, // EdgeIt edge_begin, // EdgeIt edge_end, // FaceIt face_begin, // FaceIt face_end); Vertex_handle create_vertex(); Vertex_handle create_vertex(const Vertex &v); Vertex_handle create_vertex(Vertex_handle v); //calls copy constructor Face_handle create_face(); Face_handle create_face(const Face& f); Face_handle create_face(Face_handle f); //calls copy constructor Face_handle create_face(Face_handle f1, int i1, Face_handle f2, int i2, Face_handle f3, int i3); Face_handle create_face(Face_handle f1, int i1, Face_handle f2, int i2); Face_handle create_face(Face_handle f1, int i1, Vertex_handle v); Face_handle create_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3); Face_handle create_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3, Face_handle f1, Face_handle f2, Face_handle f3); void set_adjacency(Face_handle f0, int i0, Face_handle f1, int i1) const; void delete_face(Face_handle); void delete_vertex(Vertex_handle); // split and join operations protected: Vertex_handle join_vertices(Face_handle f, int i, Vertex_handle v); typedef boost::tuples::tuple Fourtuple; public: Fourtuple split_vertex(Vertex_handle v, Face_handle f1, Face_handle g1); inline Vertex_handle join_vertices(Face_handle f, int i) { return join_vertices(f, i, f->vertex( ccw(i) )); } inline Vertex_handle join_vertices(Edge e) { return join_vertices(e.first, e.second); } inline Vertex_handle join_vertices(Edge_iterator eit) { return join_vertices(*eit); } inline Vertex_handle join_vertices(Edge_circulator ec) { return join_vertices(*ec); } // insert_degree_2 and remove_degree_2 operations Vertex_handle insert_degree_2(Face_handle f, int i); void remove_degree_2(Vertex_handle v); // CHECKING bool is_valid(bool verbose = false, int level = 0) const; // HELPING private: typedef std::pair Vh_pair; public: void set_adjacency(Face_handle fh, int ih, std::map< Vh_pair, Edge>& edge_map); void reorient_faces(); private: bool dim_down_precondition(Face_handle f, int i); public: void clear(); template Vertex_handle copy_tds(const TDS_src &tds, typename TDS_src::Vertex_handle); template Vertex_handle copy_tds(const TDS_src &tds) { return copy_tds(tds, typename TDS_src::Vertex_handle()); } template Vertex_handle copy_tds(const TDS_src&, typename TDS_src::Vertex_handle,const ConvertVertex&,const ConvertFace&); Vertex_handle collapse_edge(Edge e) { std::cout << "before collapse"<vertex(cw(i)); Vertex_handle wh = fh->vertex(ccw(i)); Face_handle left = fh->neighbor(cw(i)); Face_handle right = fh->neighbor(ccw(i)); Face_handle nh = fh->neighbor(i); int li = left->index(fh); int ri = right->index(fh); int ni = nh->index(fh); left->set_neighbor(li, right); right->set_neighbor(ri,left); left->set_vertex(ccw(li), vh); vh->set_face(right); right->vertex(ccw(ri))->set_face(right); left = nh->neighbor(ccw(ni)); right = nh->neighbor(cw(ni)); li = left->index(nh); ri = right->index(nh); left->set_neighbor(li, right); right->set_neighbor(ri,left); left->set_vertex(cw(li), vh); right->vertex(cw(ri))->set_face(right); delete_face(fh); delete_face(nh); delete_vertex(wh); std::cout << "after collapse"< Vertex_handle insert_in_hole(FaceIt face_begin, FaceIt face_end) { Vertex_handle newv = create_vertex(); insert_in_hole(newv, face_begin, face_end); return newv; } template< class FaceIt > void insert_in_hole(Vertex_handle v, FaceIt face_begin, FaceIt face_end) { CGAL_triangulation_precondition(dimension() == 2); std::vector new_faces; std::vector bdry_edges; Face_handle fh = *face_begin; int ii = 0; bool found_boundary = false; do { if (std::find(face_begin, face_end, fh->neighbor(ii)) == face_end) { bdry_edges.push_back(Edge(fh, ii)); found_boundary = true; } else { int newi = fh->neighbor(ii)->index(fh->vertex(ccw(ii))); fh = fh->neighbor(ii); ii = newi; } } while(!found_boundary); // Now we have found ONE edge on the boundary. // From that one edge we must walk on the boundary // of the hole until we've covered the whole thing. bool complete_walk = false; do { Face_handle nh = fh->neighbor(ccw(ii)); if (std::find(face_begin, face_end, nh) == face_end) { ii = ccw(ii); Edge new_edge(fh, ii); if (std::find(bdry_edges.begin(), bdry_edges.end(), new_edge) == bdry_edges.end()) { bdry_edges.push_back(Edge(fh, ii)); } else { complete_walk = true; } } else { int newi = cw(nh->index(fh->vertex(ii))); fh = nh; ii = newi; } } while (!complete_walk); // At this point, bdry_edges contains the edges that define // the boundary of the hole with a specific ordering: for any // two consecutive edges in the vector e1 = (f1, i1), // e2 = (f2, i2) it holds that // f1->vertex(cw(i1)) == f2->vertex(ccw(i2)) for (unsigned int jj = 0; jj < bdry_edges.size(); jj++) { Face_handle fh = bdry_edges[jj].first; int idx = bdry_edges[jj].second; Vertex_handle v1 = fh->vertex(ccw(idx)); Vertex_handle v2 = fh->vertex(cw(idx)); Face_handle nf = fh->neighbor(idx); int jdx = mirror_index(fh, idx); Face_handle new_f = create_face(v, v1, v2); v1->set_face(new_f); set_adjacency(new_f, 0, nf, jdx); new_faces.push_back(new_f); } // At this point we have created all the new faces of the triangulation, // and we have set adjacency relationships with the faces on the border // of the hole. for (unsigned int i = 0; i < new_faces.size() - 1; i++) { set_adjacency(new_faces[i], 1, new_faces[i+1], 2); } set_adjacency(new_faces[0], 2, new_faces[new_faces.size()-1], 1); // Now we have also set adjacency relationships between the new faces. for (FaceIt it = face_begin; it != face_end; it++) { delete_face(*it); } // The old faces that were in conflict are now deleted. v->set_face(new_faces[0]); // Set the pointer of the new vertex to one of the new faces. } /************* END OF MODIFICATIONS ***************/ template< class EdgeIt> Vertex_handle star_hole(EdgeIt edge_begin, EdgeIt edge_end) // creates a new vertex // and stars from it // the hole described by the range [edge_begin,edge_end[ // the triangulation is assumed to have dim=2 // hole is supposed to be ccw oriented { Vertex_handle newv = create_vertex(); star_hole(newv, edge_begin, edge_end); return newv; } template< class EdgeIt> void star_hole(Vertex_handle v, EdgeIt edge_begin, EdgeIt edge_end) // uses vertex v // to star the hole described by the range [edge_begin,edge_end[ // the triangulation is assumed to have dim=2 // the hole is supposed to be ccw oriented { std::list empty_list; star_hole(v, edge_begin, edge_end, empty_list.begin(), empty_list.end()); return; } template< class EdgeIt, class FaceIt> Vertex_handle star_hole(EdgeIt edge_begin, EdgeIt edge_end, FaceIt face_begin, FaceIt face_end) // creates a new vertex // and stars from it // the hole described by the range [edge_begin,edge_end[ // reusing the faces in the range [face_begin,face_end[ // the triangulation is assumed to have dim=2 // the hole is supposed to be ccw oriented { Vertex_handle newv = create_vertex(); star_hole(newv, edge_begin, edge_end, face_begin, face_end); return newv; } template< class EdgeIt, class FaceIt> void star_hole(Vertex_handle newv, EdgeIt edge_begin, EdgeIt edge_end, FaceIt face_begin, FaceIt face_end) // uses vertex v // to star the hole described by the range [edge_begin,edge_end[ // reusing the faces in the range [face_begin,face_end[ // the triangulation is assumed to have dim=2 // hole is supposed to be ccw oriented { CGAL_triangulation_precondition(dimension() == 2); EdgeIt eit = edge_begin; FaceIt fit = face_begin; Face_handle fn = (*eit).first; int in = (*eit).second; fn->vertex(cw(in))->set_face(fn); Face_handle first_f = reset_or_create_face(fn, in , newv, fit, face_end); Face_handle previous_f=first_f, next_f; ++eit; for( ; eit != edge_end ; eit++) { fn = (*eit).first; in = (*eit).second; fn->vertex(cw(in))->set_face(fn); next_f = reset_or_create_face(fn, in , newv, fit, face_end); set_adjacency(next_f, 1, previous_f, 0); previous_f=next_f; } set_adjacency(next_f, 0, first_f, 1); newv->set_face(first_f); return; } private: template< class FaceIt> Face_handle reset_or_create_face(Face_handle fn, int in, Vertex_handle v, FaceIt& fit, const FaceIt& face_end) { if (fit == face_end) return create_face(fn, in, v); (*fit)->set_vertices(fn->vertex(cw(in)), fn->vertex(ccw(in)), v); (*fit)->set_neighbors(Face_handle(),Face_handle(),fn); fn->set_neighbor(in, *fit); return *fit++; } }; //for backward compatibility template < class Gt , class Vb, class Fb> class Triangulation_default_data_structure_2 : public Triangulation_data_structure_2 { public: typedef Triangulation_data_structure_2 Tds; typedef Triangulation_default_data_structure_2 Tdds; typedef Gt Geom_traits; Triangulation_default_data_structure_2(const Geom_traits& = Geom_traits()) : Tds() {} }; //for backward compatibility template class Triangulation_data_structure_using_list_2 :public Triangulation_data_structure_2 { public: typedef Triangulation_data_structure_2 Tds; typedef Triangulation_data_structure_using_list_2 Tdsul; Triangulation_data_structure_using_list_2(): Tds() {} }; template < class Vb, class Fb> Triangulation_data_structure_2 :: Triangulation_data_structure_2() : _dimension(-2) { } template < class Vb, class Fb> Triangulation_data_structure_2 :: Triangulation_data_structure_2(const Tds &tds) { copy_tds(tds); } template < class Vb, class Fb> Triangulation_data_structure_2 :: Triangulation_data_structure_2(Tds &&tds) noexcept(noexcept(Face_range(std::move(tds._faces))) && noexcept(Vertex_range(std::move(tds._vertices)))) : _dimension(std::exchange(tds._dimension, -2)) , _faces(std::move(tds._faces)) , _vertices(std::move(tds._vertices)) { } template < class Vb, class Fb> Triangulation_data_structure_2 :: ~Triangulation_data_structure_2() { clear(); } //copy-assignment template < class Vb, class Fb> Triangulation_data_structure_2& Triangulation_data_structure_2 :: operator= (const Tds &tds) { copy_tds(tds); return *this; } //move-assignment template < class Vb, class Fb> Triangulation_data_structure_2& Triangulation_data_structure_2 :: operator= (Tds &&tds) noexcept(noexcept(Tds(std::move(tds)))) { _faces = std::move(tds._faces); _vertices = std::move(tds._vertices); _dimension = std::exchange(tds._dimension, -2); return *this; } template < class Vb, class Fb> void Triangulation_data_structure_2:: clear() { faces().clear(); vertices().clear(); set_dimension(-2); return; } template < class Vb, class Fb> void Triangulation_data_structure_2:: swap(Tds &tds) { CGAL_triangulation_expensive_precondition(tds.is_valid() && is_valid()); std::swap(_dimension, tds._dimension); faces().swap(tds.faces()); vertices().swap(tds.vertices()); return; } //ACCESS FUNCTIONS template inline typename Triangulation_data_structure_2::size_type Triangulation_data_structure_2 :: number_of_faces() const { if (dimension() < 2) return 0; return faces().size(); } template inline typename Triangulation_data_structure_2::size_type Triangulation_data_structure_2:: number_of_edges() const { switch (dimension()) { case 1: return number_of_vertices(); case 2: return 3*number_of_faces()/2; default: return 0; } } template typename Triangulation_data_structure_2::size_type Triangulation_data_structure_2:: number_of_full_dim_faces() const { return faces().size(); } template inline bool Triangulation_data_structure_2:: is_vertex(Vertex_handle v) const { Vertex_iterator vit = vertices_begin(); while (vit != vertices_end() && v != vit) ++vit; return v == vit; } template inline bool Triangulation_data_structure_2:: is_edge(Face_handle fh, int i) const { if ( dimension() == 0 ) return false; if ( dimension() == 1 && i != 2) return false; if (i > 2) return false; Face_iterator fit = face_iterator_base_begin(); while (fit != face_iterator_base_end() && fh != fit ) ++fit; return fh == fit; } template bool Triangulation_data_structure_2:: is_edge(Vertex_handle va, Vertex_handle vb) const // returns true (false) if the line segment ab is (is not) an edge of t //It is assumed that va is a vertex of t { Vertex_circulator vc = incident_vertices(va), done(vc); if ( vc == 0) return false; do { if( vb == vc ) {return true;} } while (++vc != done); return false; } template bool Triangulation_data_structure_2:: is_edge(Vertex_handle va, Vertex_handle vb, Face_handle &fr, int & i) const // assume va is a vertex of t // returns true (false) if the line segment ab is (is not) an edge of t // if true is returned (fr,i) is the edge ab // with face fr on the right of a->b { Face_handle fc = va->face(); Face_handle start = fc; if (fc == nullptr) return false; int inda, indb; do { inda=fc->index(va); indb = (dimension() == 2 ? cw(inda) : 1-inda); if(fc->vertex(indb) == vb) { fr=fc; i = 3 - inda - indb; //works in dim 1 or 2 return true; } fc=fc->neighbor(indb); //turns ccw around va } while (fc != start); return false; } template inline bool Triangulation_data_structure_2:: is_face(Face_handle fh) const { if (dimension() < 2) return false; Face_iterator fit = faces_begin(); while (fit != faces_end() && fh != fit ) ++fit; return fh == fit; } template inline bool Triangulation_data_structure_2:: is_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) const { Face_handle f; return is_face(v1,v2,v3,f); } template bool Triangulation_data_structure_2:: is_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3, Face_handle &f) const { if (dimension() != 2) return false; int i; bool b = is_edge(v1,v2,f,i); if (!b) return false; else if (v3== f->vertex(i)) return true; f = f-> neighbor(i); int ind1= f->index(v1); int ind2= f->index(v2); if (v3 == f->vertex(3-ind1-ind2)) { return true;} return false; } template void Triangulation_data_structure_2:: flip(Face_handle f, int i) { CGAL_triangulation_precondition( dimension()==2); Face_handle n = f->neighbor(i); int ni = mirror_index(f,i); //ni = n->index(f); Vertex_handle v_cw = f->vertex(cw(i)); Vertex_handle v_ccw = f->vertex(ccw(i)); // bl == bottom left, tr == top right Face_handle tr = f->neighbor(ccw(i)); int tri = mirror_index(f,ccw(i)); Face_handle bl = n->neighbor(ccw(ni)); int bli = mirror_index(n,ccw(ni)); f->set_vertex(cw(i), n->vertex(ni)); n->set_vertex(cw(ni), f->vertex(i)); // update the neighborhood relations set_adjacency(f, i, bl, bli); set_adjacency(f, ccw(i), n, ccw(ni)); set_adjacency(n, ni, tr, tri); if(v_cw->face() == f) { v_cw->set_face(n); } if(v_ccw->face() == n) { v_ccw->set_face(f); } } template < class Vb, class Fb> typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: insert_first( ) { CGAL_triangulation_precondition( number_of_vertices() == 0 && dimension()==-2 ); return insert_dim_up(); } template < class Vb, class Fb> typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: insert_second() { CGAL_triangulation_precondition( number_of_vertices() == 1 && dimension()==-1 ); return insert_dim_up(); } template < class Vb, class Fb> typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: insert_in_face(Face_handle f) // New vertex will replace f->vertex(0) in face f { CGAL_triangulation_precondition( f != Face_handle() && dimension()== 2); Vertex_handle v = create_vertex(); Vertex_handle v0 = f->vertex(0); Vertex_handle v2 = f->vertex(2); Vertex_handle v1 = f->vertex(1); Face_handle n1 = f->neighbor(1); Face_handle n2 = f->neighbor(2); Face_handle f1 = create_face(v0, v, v2, f, n1, Face_handle()); Face_handle f2 = create_face(v0, v1, v, f, Face_handle(), n2); set_adjacency(f1, 2, f2, 1); if (n1 != Face_handle()) { int i1 = mirror_index(f,1); //int i1 = n1->index(f); n1->set_neighbor(i1,f1); } if (n2 != Face_handle()) { int i2 = mirror_index(f,2);//int i2 = n2->index(f); n2->set_neighbor(i2,f2);} f->set_vertex(0, v); f->set_neighbor(1, f1); f->set_neighbor(2, f2); if( v0->face() == f ) { v0->set_face(f2); } v->set_face(f); return v; } template < class Vb, class Fb> typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: insert_in_edge(Face_handle f, int i) //insert in the edge opposite to vertex i of face f { CGAL_triangulation_precondition(f != Face_handle() && dimension() >= 1); if (dimension() == 1) {CGAL_triangulation_precondition(i == 2);} if (dimension() == 2) {CGAL_triangulation_precondition(i == 0 || i == 1 || i == 2);} Vertex_handle v; if (dimension() == 1) { v = create_vertex(); Face_handle ff = f->neighbor(0); Vertex_handle vv = f->vertex(1); Face_handle g = create_face(v,vv,Vertex_handle(),ff, f, Face_handle()); f->set_vertex(1,v);f->set_neighbor(0,g); ff->set_neighbor(1,g); v->set_face(g); vv->set_face(ff); } else { //dimension() ==2 Face_handle n = f->neighbor(i); int in = mirror_index(f,i); //n->index(f); v = insert_in_face(f); flip(n,in); } return v; } template < class Vb, class Fb> typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: insert_dim_up(Vertex_handle w, bool orient) { // the following function insert // a vertex v which is outside the affine hull of Tds // The triangulation will be starred from v and w // ( geometrically w= // the infinite vertex ) // w=nullptr for first and second insertions // orient governs the orientation of the resulting triangulation Vertex_handle v = create_vertex(); set_dimension( dimension() + 1); Face_handle f1; Face_handle f2; const int dim = dimension(); //it is the resulting dimension switch (dim) { case -1: f1 = create_face(v,Vertex_handle(),Vertex_handle()); v->set_face(f1); break; case 0 : f1 = face_iterator_base_begin(); f2 = create_face(v,Vertex_handle(),Vertex_handle()); set_adjacency(f1, 0, f2, 0); v->set_face(f2); break; case 1 : case 2 : { std::list faces_list; Face_iterator ib= face_iterator_base_begin(); Face_iterator ib_end = face_iterator_base_end(); for (; ib != ib_end ; ++ib){ faces_list.push_back( ib); } std::list to_delete; typename std::list::iterator lfit = faces_list.begin(); Face_handle f, g; for ( ; lfit != faces_list.end() ; ++lfit) { f = * lfit; g = create_face(f->vertex(0),f->vertex(1),f->vertex(2), f->neighbor(0),f->neighbor(1),f->neighbor(2)); f->set_vertex(dim,v); g->set_vertex(dim,w); set_adjacency(f, dim, g, dim); if (f->has_vertex(w)) to_delete.push_back(g); // flat face to delete } lfit = faces_list.begin(); for ( ; lfit != faces_list.end() ; ++lfit) { f = * lfit; g = f->neighbor(dim); for(int j = 0; j < dim ; ++j) { g->set_neighbor(j, f->neighbor(j)->neighbor(dim)); } } // couldn't unify the code for reorientation mater lfit = faces_list.begin() ; if (dim == 1){ if (orient) { (*lfit)->reorient(); ++lfit ; (*lfit)->neighbor(1)->reorient(); } else { (*lfit)->neighbor(1)->reorient(); ++lfit ; (*lfit)->reorient(); } } else { // dimension == 2 for( ;lfit != faces_list.end(); ++lfit ) { if (orient) {(*lfit)->neighbor(2)->reorient();} else { (*lfit)->reorient();} } } lfit = to_delete.begin(); int i1, i2; for ( ;lfit != to_delete.end(); ++lfit){ f = *lfit ; int j ; if (f->vertex(0) == w) {j=0;} else {j=1;} f1= f->neighbor(dim); i1= mirror_index(f,dim); //f1->index(f); f2= f->neighbor(j); i2= mirror_index(f,j); //f2->index(f); set_adjacency(f1, i1, f2, i2); delete_face(f); } v->set_face( *(faces_list.begin())); } break; default: CGAL_triangulation_assertion(false); break; } return v; } template void Triangulation_data_structure_2:: remove_degree_3(Vertex_handle v, Face_handle f) // remove a vertex of degree 3 { CGAL_triangulation_precondition(v != Vertex_handle()); CGAL_triangulation_precondition(degree(v) == 3); if (f == Face_handle()) {f= v->face();} else { CGAL_triangulation_assertion( f->has_vertex(v));} int i = f->index(v); Face_handle left = f->neighbor(cw(i)); int li = mirror_index(f,cw(i)); Face_handle right = f->neighbor(ccw(i)); int ri = mirror_index(f,ccw(i)); Face_handle ll, rr; Vertex_handle q = left->vertex(li); CGAL_triangulation_assertion( left->vertex(li) == right->vertex(ri)); ll = left->neighbor(cw(li)); if(ll != Face_handle()) { int lli = mirror_index(left,cw(li)); ll->set_neighbor(lli, f); } f->set_neighbor(cw(i), ll); if (f->vertex(ccw(i))->face() == left) f->vertex(ccw(i))->set_face(f); rr = right->neighbor(ccw(ri)); if(rr != Face_handle()) { int rri = mirror_index(right,ccw(ri)); //rr->index(right); rr->set_neighbor(rri, f); } f->set_neighbor(ccw(i), rr); if (f->vertex(cw(i))->face() == right) f->vertex(cw(i))->set_face(f); f->set_vertex(i, q); if (q->face() == right || q->face() == left) { q->set_face(f); } delete_face(right); delete_face(left); delete_vertex(v); } template void Triangulation_data_structure_2:: dim_down(Face_handle f, int i) { CGAL_triangulation_expensive_precondition( is_valid() ); CGAL_triangulation_precondition( dimension() == 2 ); CGAL_triangulation_precondition( number_of_vertices() > 3 ); CGAL_triangulation_precondition( degree( f->vertex(i) ) == number_of_vertices()-1 ); Vertex_handle v = f->vertex(i); std::list to_delete; std::list to_downgrade; Face_iterator ib = face_iterator_base_begin(); for( ; ib != face_iterator_base_end(); ++ib ){ if ( ! ib->has_vertex(v) ) { to_delete.push_back(ib);} else { to_downgrade.push_back(ib);} } typename std::list::iterator lfit = to_downgrade.begin(); int j; for( ; lfit != to_downgrade.end() ; ++lfit) { Face_handle fs = *lfit; j = fs->index(v); if (j == 0) fs->cw_permute(); else if(j == 1) fs->ccw_permute(); fs->set_vertex(2, Vertex_handle()); fs->set_neighbor(2, Face_handle()); fs->vertex(0)->set_face(fs); } lfit = to_delete.begin(); for( ; lfit != to_delete.end() ; ++lfit) { delete_face(*lfit); } set_dimension(dimension() -1); Face_handle n0 = f->neighbor(0); //Face_handle n1 = f->neighbor(1); //Vertex_handle v0 = f->vertex(0); Vertex_handle v1 = f->vertex(1); f->set_vertex(1, v); Face_handle fl = create_face(v, v1, Vertex_handle(), n0, f, Face_handle()); f->set_neighbor(0, fl); n0->set_neighbor(1, fl); v->set_face(f); } template void Triangulation_data_structure_2:: remove_dim_down(Vertex_handle v) { Face_handle f; switch( dimension()){ case -1: delete_face(v->face()); break; case 0: f = v->face(); f->neighbor(0)->set_neighbor(0,Face_handle()); delete_face(v->face()); break; case 1: case 2: // CGAL_triangulation_precondition ( // (dimension() == 1 && number_of_vertices() == 3) || // (dimension() == 2 && number_of_vertices() > 3) ); // the faces incident to v are down graded one dimension // the other faces are deleted std::list to_delete; std::list to_downgrade; Face_iterator ib = face_iterator_base_begin(); for( ; ib != face_iterator_base_end(); ++ib ){ if ( ! ib->has_vertex(v) ) { to_delete.push_back(ib);} else { to_downgrade.push_back(ib);} } typename std::list::iterator lfit = to_downgrade.begin(); int j; for( ; lfit != to_downgrade.end() ; ++lfit) { f = *lfit; j = f->index(v); if (dimension() == 1) { if (j == 0) f->reorient(); f->set_vertex(1,Vertex_handle()); f->set_neighbor(1, Face_handle()); } else { //dimension() == 2 if (j == 0) f->cw_permute(); else if(j == 1) f->ccw_permute(); f->set_vertex(2, Vertex_handle()); f->set_neighbor(2, Face_handle()); } f->vertex(0)->set_face(f); } lfit = to_delete.begin(); for( ; lfit != to_delete.end() ; ++lfit) { delete_face(*lfit); } } delete_vertex(v); set_dimension(dimension() -1); return; } template < class Vb, class Fb> void Triangulation_data_structure_2:: remove_1D(Vertex_handle v) { CGAL_triangulation_precondition( dimension() == 1 && number_of_vertices() > 3); Face_handle f = v->face(); int i = f->index(v); if (i==0) {f = f->neighbor(1);} CGAL_triangulation_assertion( f->index(v) == 1); Face_handle g= f->neighbor(0); f->set_vertex(1, g->vertex(1)); set_adjacency(f, 0, g->neighbor(0), 1); g->vertex(1)->set_face(f); delete_face(g); delete_vertex(v); return; } template inline void Triangulation_data_structure_2:: remove_second(Vertex_handle v) { CGAL_triangulation_precondition(number_of_vertices()== 2 && dimension() == 0); remove_dim_down(v); return; } template inline void Triangulation_data_structure_2:: remove_first(Vertex_handle v) { CGAL_triangulation_precondition(number_of_vertices()== 1 && dimension() == -1); remove_dim_down(v); return; } template inline typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: star_hole(List_edges& hole) { Vertex_handle newv = create_vertex(); star_hole(newv, hole); return newv; } template void Triangulation_data_structure_2:: star_hole(Vertex_handle newv, List_edges& hole) // star the hole represented by hole around newv // the triangulation is assumed to have dim=2 // hole is supposed to be ccw oriented { star_hole(newv, hole.begin(), hole.end()); return; } template void Triangulation_data_structure_2:: make_hole(Vertex_handle v, List_edges& hole) // delete the faces incident to v and v // and return the dscription of the hole in hole { CGAL_triangulation_precondition(dimension() == 2); std::list to_delete; Face_handle f, fn; int i =0, in =0; Vertex_handle vv; Face_circulator fc = incident_faces(v); Face_circulator done(fc); do { f = fc ; i = f->index(v); fn = f->neighbor(i); in = mirror_index(f,i); //fn->index(f); vv = f->vertex(cw(i)); if( vv->face()== f) vv->set_face(fn); vv = fc->vertex(ccw(i)); if( vv->face()== f) vv->set_face(fn); fn->set_neighbor(in, Face_handle()); hole.push_back(Edge(fn,in)); to_delete.push_back(f); } while(++fc != done); while (! to_delete.empty()){ delete_face(to_delete.front()); to_delete.pop_front(); } delete_vertex(v); return; } template inline typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: create_vertex() { return vertices().emplace(); } template inline typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: create_vertex(const Vertex &v) { return vertices().insert(v); } template inline typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: create_vertex(Vertex_handle vh) { return vertices().insert(*vh); } template typename Triangulation_data_structure_2::Face_handle Triangulation_data_structure_2:: create_face() { return faces().emplace(); } template typename Triangulation_data_structure_2::Face_handle Triangulation_data_structure_2:: create_face(const Face& f) { return faces().insert(f); } template typename Triangulation_data_structure_2::Face_handle Triangulation_data_structure_2:: create_face( Face_handle fh) { return create_face(*fh); } template typename Triangulation_data_structure_2::Face_handle Triangulation_data_structure_2:: create_face(Face_handle f1, int i1, Face_handle f2, int i2, Face_handle f3, int i3) { Face_handle newf = faces().emplace(f1->vertex(cw(i1)), f2->vertex(cw(i2)), f3->vertex(cw(i3)), f2, f3, f1); f1->set_neighbor(i1,newf); f2->set_neighbor(i2,newf); f3->set_neighbor(i3,newf); return newf; } template typename Triangulation_data_structure_2::Face_handle Triangulation_data_structure_2:: create_face(Face_handle f1, int i1, Face_handle f2, int i2) { Face_handle newf = faces().emplace(f1->vertex(cw(i1)), f2->vertex(cw(i2)), f2->vertex(ccw(i2)), f2, Face_handle(), f1); f1->set_neighbor(i1,newf); f2->set_neighbor(i2,newf); return newf; } template typename Triangulation_data_structure_2::Face_handle Triangulation_data_structure_2:: create_face(Face_handle f1, int i1, Vertex_handle v) { Face_handle newf = create_face(); newf->set_vertices(f1->vertex(cw(i1)), f1->vertex(ccw(i1)), v); newf->set_neighbors(Face_handle(), Face_handle(), f1); f1->set_neighbor(i1,newf); return newf; } template typename Triangulation_data_structure_2::Face_handle Triangulation_data_structure_2:: create_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) { Face_handle newf = faces().emplace(v1, v2, v3); return newf; } template typename Triangulation_data_structure_2::Face_handle Triangulation_data_structure_2:: create_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3, Face_handle f1, Face_handle f2, Face_handle f3) { Face_handle newf = faces().emplace(v1, v2, v3, f1, f2, f3); return(newf); } template inline void Triangulation_data_structure_2:: set_adjacency(Face_handle f0, int i0, Face_handle f1, int i1) const { CGAL_triangulation_assertion(i0 >= 0 && i0 <= dimension()); CGAL_triangulation_assertion(i1 >= 0 && i1 <= dimension()); CGAL_triangulation_assertion(f0 != f1); f0->set_neighbor(i0,f1); f1->set_neighbor(i1,f0); } template inline void Triangulation_data_structure_2:: delete_face(Face_handle f) { CGAL_triangulation_expensive_precondition( dimension() != 2 || is_face(f)); CGAL_triangulation_expensive_precondition( dimension() != 1 || is_edge(f,2)); CGAL_triangulation_expensive_precondition( dimension() != 0 || is_vertex(f->vertex(0)) ); faces().erase(f); } template inline void Triangulation_data_structure_2:: delete_vertex(Vertex_handle v) { CGAL_triangulation_expensive_precondition( is_vertex(v) ); vertices().erase(v); } // split and join operations template typename Triangulation_data_structure_2::Fourtuple Triangulation_data_structure_2:: split_vertex(Vertex_handle v, Face_handle f1, Face_handle g1) { /* // The following method preforms a split operation of the vertex v // using the faces f1 and g1. The split operation is shown // below. // The names of the variables in the method correspond to the // quantities in the drawings below // // The configuration before the split: // // cw(i1) v3 ccw(i2) // *-----*-----* // / \ | / \ // / \ f1|f2 / \ // / \ | / \ // / \ | / \ // / \|/v \ // *-----------*-----------* // \ /|\ / // \ / | \ / // \ / | \ / // \ / g2|g1 \ / // \ / | \ / // *-----*-----* // ccw(j2) v4 cw(j1) // // // The configuration after the split: // // // cw(i1) v3 ccw(i2) // *---------*---------* // / \ / \ / \ // / \ f1 / \ f2 / \ // / \ / f \ / \ // / \ / v2\ / \ // *---------*---------*---------* // \ / \v1 / \ / // \ / \ g / \ / // \ / g2 \ / g1 \ / // \ / \ / \ / // *---------*---------* // ccw(j2) v4 cw(j1) // */ CGAL_triangulation_expensive_precondition( is_valid() ); CGAL_triangulation_precondition( dimension() == 2 ); CGAL_triangulation_precondition( f1 != Face_handle() && f1->has_vertex(v) ); CGAL_triangulation_precondition( g1 != Face_handle() && g1->has_vertex(v) ); // 1. first we read some information that we will need int i1 = f1->index(v); int j1 = g1->index(v); Face_handle f2 = f1->neighbor( cw(i1) ); Face_handle g2 = g1->neighbor( cw(j1) ); int i2 = f2->index(v); int j2 = g2->index(v); Vertex_handle v3 = f1->vertex( ccw(i1) ); Vertex_handle v4 = g1->vertex( ccw(j1) ); // lst is the list of faces adjecent to v stored in // counterclockwise order from g2 to f1) inclusive. // the list idx contains the indices of v in the // faces in lst. std::list lst; std::list idx; Face_circulator fc(v, g1); Face_handle ff(fc); while ( ff != f2 ) { lst.push_back( ff ); idx.push_back( ff->index(v) ); fc++; ff = Face_handle(fc); } lst.push_back( ff ); idx.push_back( ff->index(v) ); // 2. we create the new vertices and the two new faces Vertex_handle v1 = v; Vertex_handle v2 = create_vertex(); Face_handle f = create_face(v1, v2, v3); Face_handle g = create_face(v2, v1, v4); // 3. we update the adjacency information for the new vertices and // the new faces f->set_neighbor(0, f2); f->set_neighbor(1, f1); f->set_neighbor(2, g); g->set_neighbor(0, g2); g->set_neighbor(1, g1); g->set_neighbor(2, f); v1->set_face(f); v2->set_face(g); // 4. update the vertex for the faces f2 through g1 in // counterclockwise order typename std::list::iterator fit = lst.begin(); typename std::list::iterator iit = idx.begin(); for (; fit != lst.end(); ++fit, ++iit) { (*fit)->set_vertex(*iit, v2); } lst.clear(); idx.clear(); // 5. make f and g the new neighbors of f1, f2 and g1, g2 // respectively. f1->set_neighbor( cw(i1), f ); f2->set_neighbor( ccw(i2), f ); g1->set_neighbor( cw(j1), g ); g2->set_neighbor( ccw(j2), g ); CGAL_triangulation_expensive_postcondition( is_valid() ); // 6. return the new stuff return Fourtuple(v1, v2, f, g); } template typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: join_vertices(Face_handle f, int i, Vertex_handle v) { CGAL_triangulation_expensive_precondition( is_valid() ); CGAL_triangulation_precondition( f != Face_handle() ); CGAL_triangulation_precondition( i >= 0 && i <= 2 ); // this methods does the "join"-operation and preserves // the vertex v among the two vertices that define the edge (f, i) Vertex_handle v1 = f->vertex( ccw(i) ); Vertex_handle v2 = f->vertex( cw(i) ); CGAL_triangulation_precondition( v == v1 || v == v2 ); if ( v == v2 ) { return join_vertices(f->neighbor(i), mirror_index(f,i), v); } size_type deg2 = degree(v2); CGAL_triangulation_precondition( deg2 >= 3 ); if ( deg2 == 3 ) { remove_degree_3(v2, f->neighbor(ccw(i))); return v1; } /* // The following drawing corrsponds to the variables // used in this part... // The vertex v1 is returned... // // itl i=v3 itr // *---------*---------* // \ / \ / // \ tl / \ tr / // \ / f \ / // \ / \ / // v1=ccw(i) *---------* cw(i)=v2 // / \ / \ // / \ g / \ // / bl \ / br \ // / \ / \ // *---------*---------* // ibl j=v4 ibr // // The situation after the "join"-operation is as follows: // // i // *-----*-----* // \ | / // \ tl|tr / // \ | / // \ | / // \|/ // * v1 // /|\ // / | \ // / | \ // / bl|br \ // / | \ // *-----*-----* // */ // first we register all the needed info Face_handle g = f->neighbor(i); int j = mirror_index(f,i); Face_handle tl = f->neighbor( cw(i) ); Face_handle tr = f->neighbor( ccw(i) ); int itl = mirror_index(f, cw(i) ); int itr = mirror_index(f, ccw(i) ); Face_handle bl = g->neighbor( ccw(j) ); Face_handle br = g->neighbor( cw(j) ); int ibl = mirror_index(g, ccw(j) ); int ibr = mirror_index(g, cw(j) ); // we need to store the faces adjacent to v2 as well as the // indices of v2 w.r.t. these faces, so that afterwards we can set // v1 to be the vertex for these faces std::vector star_faces_of_v2; std::vector star_indices_of_v2; Face_circulator fc_start(v2); Face_circulator fc = fc_start; do { Face_handle ff(fc); star_faces_of_v2.push_back(ff); star_indices_of_v2.push_back(ff->index(v2)); ++fc; } while ( fc != fc_start ); CGAL_triangulation_assertion( static_cast(star_faces_of_v2.size()) == deg2 ); // from this point and on we modify the values // first set the neighbors set_adjacency(tl, itl, tr, itr); set_adjacency(bl, ibl, br, ibr); // make sure that all the faces containing v2 as a vertex, now // contain v1 for (unsigned int k = 0; k < star_faces_of_v2.size(); k++) { int id = star_indices_of_v2[k]; CGAL_triangulation_assertion( star_faces_of_v2[k]->vertex(id) == v2 ); star_faces_of_v2[k]->set_vertex( id, v1 ); } // then make sure that all the vertices have correct pointers to // faces Vertex_handle v3 = f->vertex(i); Vertex_handle v4 = g->vertex(j); if ( v3->face() == f ) v3->set_face(tr); if ( v4->face() == g ) v4->set_face(br); if ( v1->face() == f || v1->face() == g ) v1->set_face(tl); #if ! defined(CGAL_TRIANGULATION_NO_ASSERTIONS) && ! defined(CGAL_NO_ASSERTIONS) for (Face_iterator fit = faces_begin(); fit != faces_end(); ++fit) { int id; CGAL_triangulation_assertion( !fit->has_vertex(v2, id) ); } #endif // memory management star_faces_of_v2.clear(); star_indices_of_v2.clear(); delete_face(f); delete_face(g); delete_vertex(v2); CGAL_triangulation_expensive_postcondition( is_valid() ); return v1; } // insert_degree_2 and remove_degree_2 operations template typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: insert_degree_2(Face_handle f, int i) { /* // This method basically does the following transformation // The remove_degree_2 method performs the same operation in the // opposite direction // // // * // i / \ // * / \ // / \ / f \ // / \ / _____ \ // / f \ / / f1 \ \ // / \ |/ v \| // v0=ccw(i) *---------* v1=cw(i) ===> v0 *----*----* v1 // \ / |\ f2 /| // \ g / \ \_____/ / // \ / \ / // \ / \ g / // * \ / // j \ / // * // */ Face_handle g = f->neighbor(i); int j = mirror_index(f,i); Vertex_handle v = create_vertex(); Vertex_handle v0 = f->vertex( ccw(i) ); Vertex_handle v1 = f->vertex( cw(i) ); Face_handle f_undef; Face_handle f1 = create_face(v0, v, v1, f_undef, f, f_undef); Face_handle f2 = create_face(v0, v1, v, f_undef, f_undef, g); set_adjacency(f1, 0, f2, 0); set_adjacency(f1, 2, f2, 1); f->set_neighbor(i, f1); g->set_neighbor(j, f2); v->set_face(f1); return v; } template void Triangulation_data_structure_2:: remove_degree_2(Vertex_handle v) { CGAL_precondition( degree(v) == 2 ); Face_handle f1 = v->face(); int i = f1->index(v); Face_handle f2 = f1->neighbor( ccw(i) ); int j = f2->index(v); Face_handle ff1 = f1->neighbor( i ); Face_handle ff2 = f2->neighbor( j ); int id1 = mirror_index(f1,i); int id2 = mirror_index(f2,j); set_adjacency(ff1, id1, ff2, id2); Vertex_handle v1 = f1->vertex( ccw(i) ); // if ( v1->face() == f1 || v1->face() == f2 ) { v1->set_face(ff1); // } Vertex_handle v2 = f1->vertex( cw(i) ); // if ( v2->face() == f1 || v2->face() == f2 ) { v2->set_face(ff2); // } delete_face(f1); delete_face(f2); delete_vertex(v); } // CHECKING template < class Vb, class Fb> bool Triangulation_data_structure_2:: is_valid(bool verbose, int level) const { if(number_of_vertices() == 0){ return (dimension() == -2); } bool result = (dimension()>= -1); CGAL_triangulation_assertion(result); //count and test the validity of the faces (for positive dimensions) Face_iterator ib = face_iterator_base_begin(); Face_iterator ib_end = face_iterator_base_end(); size_type count_stored_faces =0; for ( ; ib != ib_end ; ++ib){ count_stored_faces += 1; if (dimension()>= 0) { result = result && ib->is_valid(verbose,level); CGAL_triangulation_assertion(result); } } result = result && (count_stored_faces == number_of_full_dim_faces()); CGAL_triangulation_assertion( count_stored_faces == number_of_full_dim_faces()); // vertex count size_type vertex_count = 0; for(Vertex_iterator vit = vertices_begin(); vit != vertices_end(); ++vit) { CGAL_triangulation_assertion( vit->face() != Face_handle()); result = result && vit->is_valid(verbose,level); CGAL_triangulation_assertion( result ); ++vertex_count; } result = result && (number_of_vertices() == vertex_count); CGAL_triangulation_assertion( number_of_vertices() == vertex_count ); //edge count size_type edge_count = 0; for(Edge_iterator eit = edges_begin(); eit != edges_end(); ++eit) { ++edge_count; } // face count size_type face_count = 0; for(Face_iterator fit = faces_begin(); fit != faces_end(); ++fit) { ++face_count; } switch(dimension()) { case -1: result = result && vertex_count == 1 && face_count == 0 && edge_count == 0; CGAL_triangulation_assertion(result); break; case 0: result = result && vertex_count == 2 && face_count == 0 && edge_count == 0; CGAL_triangulation_assertion(result); break; case 1: result = result && edge_count == vertex_count; CGAL_triangulation_assertion(result); result = result && face_count == 0; CGAL_triangulation_assertion(result); break; case 2: result = result && edge_count == 3*face_count/2 ; CGAL_triangulation_assertion(edge_count == 3*face_count/2); break; default: result = false; CGAL_triangulation_assertion(result); } return result; } template template typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: copy_tds(const TDS_src& tds_src, typename TDS_src::Vertex_handle vert, const ConvertVertex& convert_vertex, const ConvertFace& convert_face) { if (vert != typename TDS_src::Vertex_handle()) CGAL_triangulation_precondition( tds_src.is_vertex(vert)); clear(); size_type n = tds_src.number_of_vertices(); set_dimension(tds_src.dimension()); // Number of pointers to cell/vertex to copy per cell. int dim = (std::max)(1, dimension() + 1); if(n == 0) {return Vertex_handle();} //initializes maps Unique_hash_map vmap; Unique_hash_map fmap; // create vertices typename TDS_src::Vertex_iterator vit1 = tds_src.vertices_begin(); for( ; vit1 != tds_src.vertices_end(); ++vit1) { Vertex_handle vh = create_vertex( convert_vertex(*vit1) ); vmap[vit1] = vh; convert_vertex(*vit1, *vh); } //create faces typename TDS_src::Face_iterator fit1 = tds_src.faces().begin(); for( ; fit1 != tds_src.faces_end(); ++fit1) { Face_handle fh = create_face( convert_face(*fit1) ); fmap[fit1] = fh; convert_face(*fit1, *fh); } //link vertices to a cell vit1 = tds_src.vertices_begin(); for ( ; vit1 != tds_src.vertices_end(); vit1++) { vmap[vit1]->set_face(fmap[vit1->face()]); } //update vertices and neighbor pointers fit1 = tds_src.faces().begin(); for ( ; fit1 != tds_src.faces_end(); ++fit1) { for (int j = 0; j < dim ; ++j) { fmap[fit1]->set_vertex(j, vmap[fit1->vertex(j)] ); fmap[fit1]->set_neighbor(j, fmap[fit1->neighbor(j)]); } } // remove the post condition because it is false when copying the // TDS of a regular triangulation because of hidden vertices // CGAL_triangulation_postcondition( is_valid() ); return (vert == typename TDS_src::Vertex_handle()) ? Vertex_handle() : vmap[vert]; } //utilities for copy_tds namespace internal { namespace TDS_2{ template struct Default_vertex_converter { Vertex_tgt operator()(const Vertex_src& src) const { return Vertex_tgt( src.point() ); } void operator()(const Vertex_src&,Vertex_tgt&) const {} }; template struct Default_face_converter { Face_tgt operator()(const Face_src& /*src*/) const { return Face_tgt(); } void operator()(const Face_src&,Face_tgt&) const {} }; template struct Default_vertex_converter { const Vertex& operator()(const Vertex& src) const { return src; } void operator()(const Vertex&,Vertex&) const {} }; template struct Default_face_converter{ const Face& operator()(const Face& src) const { return src; } void operator()(const Face&,Face&) const {} }; } } //namespace internal::TDS_2 template < class Vb, class Fb> template < class TDS_src> typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: copy_tds(const TDS_src &src, typename TDS_src::Vertex_handle vh) // return the vertex corresponding to vh in the new tds { if (this == &src) return Vertex_handle(); internal::TDS_2::Default_vertex_converter setv; internal::TDS_2::Default_face_converter setf; return copy_tds(src,vh,setv,setf); } template < class Vb, class Fb> void Triangulation_data_structure_2:: file_output( std::ostream& os, Vertex_handle v, bool skip_first) const { // ouput to a file // if non nullptr, v is the vertex to be output first // if skip_first is true, the point in the first vertex is not output // (it may be for instance the infinite vertex of the triangulation) size_type n = number_of_vertices(); size_type m = number_of_full_dim_faces(); if(is_ascii(os)) os << n << ' ' << m << ' ' << dimension() << std::endl; else os << n << m << dimension(); if (n==0) return; Unique_hash_map V; Unique_hash_map F; // first vertex int inum = 0; if ( v != Vertex_handle()) { V[v] = inum++; if( ! skip_first){ // os << v->point(); os << *v ; if(is_ascii(os)) os << std::endl; } } // other vertices for( Vertex_iterator vit= vertices_begin(); vit != vertices_end() ; ++vit) { if ( v != vit ) { V[vit] = inum++; // os << vit->point(); os << *vit; if(is_ascii(os)) os << "\n"; } } if(is_ascii(os)) os << "\n"; // vertices of the faces inum = 0; int dim = (dimension() == -1 ? 1 : dimension() + 1); for( Face_iterator ib = face_iterator_base_begin(); ib != face_iterator_base_end(); ++ib) { F[ib] = inum++; for(int j = 0; j < dim ; ++j) { os << V[ib->vertex(j)]; if(is_ascii(os)) os << " "; } os << *ib ; if(is_ascii(os)) os << "\n"; } if(is_ascii(os)) os << "\n"; // neighbor pointers of the faces for( Face_iterator it = face_iterator_base_begin(); it != face_iterator_base_end(); ++it) { for(int j = 0; j < dimension()+1; ++j){ os << F[it->neighbor(j)]; if(is_ascii(os)) os << " "; } if(is_ascii(os)) os << "\n"; } return ; } template < class Vb, class Fb> typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: file_input( std::istream& is, bool skip_first) { //input from file //return a pointer to the first input vertex // if skip_first is true, a first vertex is added (infinite_vertex) //set this first vertex as infinite_Vertex if(number_of_vertices() != 0) clear(); size_type n, m; int d; is >> n >> m >> d; if (n==0){ return Vertex_handle();} set_dimension(d); std::vector V(n); std::vector F(m); // read vertices size_type i = 0; if(skip_first){ V[0] = create_vertex(); ++i; } for( ; i < n; ++i) { V[i] = create_vertex(); is >> *(V[i]); } // Creation of the faces int index; int dim = (dimension() == -1 ? 1 : dimension() + 1); { for(i = 0; i < m; ++i) { F[i] = create_face() ; for(int j = 0; j < dim ; ++j){ is >> index; F[i]->set_vertex(j, V[index]); // The face pointer of vertices is set too often, // but otherwise we had to use a further map V[index]->set_face(F[i]); } // read in non combinatorial info of the face is >> *(F[i]) ; } } // Setting the neighbor pointers { for(i = 0; i < m; ++i) { for(int j = 0; j < dimension()+1; ++j){ is >> index; F[i]->set_neighbor(j, F[index]); } } } return V[0]; } template < class Vb, class Fb> void Triangulation_data_structure_2:: vrml_output( std::ostream& os, Vertex_handle v, bool skip_infinite) const { // ouput to a vrml file style // Point are assumed to be 3d points with a stream oprator << // if non nullptr, v is the vertex to be output first // if skip_inf is true, the point in the first vertex is not output // and the faces incident to v are not output // (it may be for instance the infinite vertex of the terrain) os << "#VRML V2.0 utf8" << std::endl; os << "Shape {" << std::endl; os << "\tgeometry IndexedFaceSet {" << std::endl; os << "\t\tcoord Coordinate {" << std::endl; os << "\t\t\tpoint [" << std::endl; Unique_hash_map vmap; Vertex_iterator vit; Face_iterator fit; //first vertex int inum = 0; if ( v != Vertex_handle()) { vmap[v] = inum++; if( ! skip_infinite) os << "\t\t\t\t" << *v << std::endl; } //other vertices for( vit= vertices_begin(); vit != vertices_end() ; ++vit) { if ( v != vit) { vmap[vit] = inum++; os << "\t\t\t\t" << *vit << std::endl; } } os << "\t\t\t]" << std::endl; os << "\t\t}" << std::endl; os << "\t\tcoordIndex [" << std::endl; // faces for(fit= faces_begin(); fit != faces_end(); ++fit) { if (!skip_infinite || !fit->has_vertex(v)) { os << "\t\t\t"; os << vmap[(*fit).vertex(0)] << ", "; os << vmap[(*fit).vertex(1)] << ", "; os << vmap[(*fit).vertex(2)] << ", "; os << "-1, " << std::endl; } } os << "\t\t]" << std::endl; os << "\t}" << std::endl; os << "}" << std::endl; return; } template < class Vb, class Fb> typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: off_file_input( std::istream& is, bool verbose) { // input from an OFF file // assume a dimension 2 triangulation // create an infinite-vertex and infinite faces with the // boundary edges if any. // return the infinite vertex if created Vertex_handle vinf; File_scanner_OFF scanner(is, verbose); if (! is) { if (scanner.verbose()) { std::cerr << " " << std::endl; std::cerr << "TDS::off_file_input" << std::endl; std::cerr << " input error: file format is not OFF." << std::endl; } return vinf; } if(number_of_vertices() != 0) clear(); int dim = 2; set_dimension(dim); std::vector vvh(scanner.size_of_vertices()); std::map edge_map; typedef typename Vb::Point Point; // read vertices std::size_t i; for ( i = 0; i < scanner.size_of_vertices(); i++) { Point p; file_scan_vertex( scanner, p); vvh[i] = create_vertex(); vvh[i]->set_point(p); scanner.skip_to_next_vertex( i); } if ( ! is ) { is.clear( std::ios::badbit); return vinf; } //vinf = vvh[0]; // create the facets for ( i = 0; i < scanner.size_of_facets(); i++) { Face_handle fh = create_face(); std::size_t no; scanner.scan_facet( no, i); if( ! is || no != 3) { if ( scanner.verbose()) { std::cerr << " " << std::endl; std::cerr << "TDS::off_file_input" << std::endl; std::cerr << "facet " << i << "does not have 3 vertices." << std::endl; } is.clear( std::ios::badbit); return vinf; } for ( std::size_t j = 0; j < no; ++j) { std::size_t index; scanner.scan_facet_vertex_index( index, i); fh->set_vertex(j, vvh[index]); vvh[index]->set_face(fh); } for (std::size_t ih = 0; ih < no; ++ih) { set_adjacency(fh, ih, edge_map); } } // deal with boundaries if ( !edge_map.empty()) { vinf = create_vertex(); std::map inf_edge_map; while (!edge_map.empty()) { Face_handle fh = edge_map.begin()->second.first; int ih = edge_map.begin()->second.second; Face_handle fn = create_face( vinf, fh->vertex(cw(ih)), fh->vertex(ccw(ih))); vinf->set_face(fn); set_adjacency(fn, 0, fh, ih); set_adjacency(fn, 1, inf_edge_map); set_adjacency(fn, 2, inf_edge_map); edge_map.erase(edge_map.begin()); } CGAL_triangulation_assertion(inf_edge_map.empty()); } // coherent orientation reorient_faces(); return vinf; } template < class Vb, class Fb> void Triangulation_data_structure_2:: set_adjacency(Face_handle fh, int ih, std::map< Vh_pair, Edge>& edge_map) { // set adjacency to (fh,ih) using the the map edge_map // or insert (fh,ih) in edge map Vertex_handle vhcw = fh->vertex(cw(ih)); Vertex_handle vhccw = fh->vertex(ccw(ih)); Vh_pair vhp = vhcw < vhccw ? std::make_pair(vhcw, vhccw) : std::make_pair(vhccw, vhcw) ; typename std::map::iterator emapit = edge_map.find(vhp); if (emapit == edge_map.end()) {// not found, insert edge edge_map.insert(std::make_pair(vhp, Edge(fh,ih))); } else { //found set adjacency and erase Edge e = emapit->second; set_adjacency( fh,ih, e.first, e.second); edge_map.erase(emapit); } } template < class Vb, class Fb> void Triangulation_data_structure_2:: reorient_faces() { // reorient the faces of a triangulation // needed for example in off_file_input // because the genus is not known, the number of faces std::set oriented_set; std::stack st; Face_iterator fit = faces_begin(); std::ptrdiff_t nf = std::distance(faces_begin(),faces_end()); while (0 != nf) { while ( !oriented_set.insert(fit).second ){ ++fit; // find a germ for non oriented components } // orient component --nf; st.push(fit); while ( ! st.empty()) { Face_handle fh = st.top(); st.pop(); for(int ih = 0 ; ih < 3 ; ++ih){ Face_handle fn = fh->neighbor(ih); if (oriented_set.insert(fn).second){ int in = fn->index(fh); if (fn->vertex(cw(in)) != fh->vertex(ccw(ih))) fn->reorient(); --nf; st.push(fn); } } } } return; } template < class Vb, class Fb> std::istream& operator>>(std::istream& is, Triangulation_data_structure_2& tds) { tds.file_input(is); return is; } template < class Vb, class Fb> std::ostream& operator<<(std::ostream& os, const Triangulation_data_structure_2 &tds) { tds.file_output(os); return os; } } //namespace CGAL #endif //CGAL_TRIANGULATION_DATA_STRUCTURE_2_H