BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/HalfedgeDS_decorator.h
Go to the documentation of this file.
00001 // Copyright (c) 1997  Utrecht University (The Netherlands),
00002 // ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany),
00003 // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg
00004 // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria),
00005 // and Tel-Aviv University (Israel).  All rights reserved.
00006 //
00007 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public License as
00009 // published by the Free Software Foundation; version 2.1 of the License.
00010 // See the file LICENSE.LGPL distributed with CGAL.
00011 //
00012 // Licensees holding a valid commercial license may use this file in
00013 // accordance with the commercial license agreement provided with the software.
00014 //
00015 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 //
00018 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/HalfedgeDS/include/CGAL/HalfedgeDS_decorator.h $
00019 // $Id: HalfedgeDS_decorator.h 49918 2009-06-15 13:09:47Z lsaboret $
00020 //
00021 //
00022 // Author(s)     : Lutz Kettner  <kettner@mpi-sb.mpg.de>
00023 
00024 #ifndef CGAL_HALFEDGEDS_DECORATOR_H
00025 #define CGAL_HALFEDGEDS_DECORATOR_H 1
00026 
00027 #include <CGAL/HalfedgeDS_items_decorator.h>
00028 #include <CGAL/HalfedgeDS_const_decorator.h>
00029 #include <CGAL/HalfedgeDS_iterator.h>
00030 #include <CGAL/IO/Verbose_ostream.h>
00031 
00032 #include <vector>
00033 #include <map>
00034 #include <list>
00035 
00036 CGAL_BEGIN_NAMESPACE
00037 
00038 template < class p_HDS >
00039 class HalfedgeDS_decorator : public HalfedgeDS_items_decorator<p_HDS> {
00040 
00041 // TYPES (inherited from Items_decorator, but have to be repeated)
00042 // ---------------------------------------------------------------
00043 public:
00044     typedef p_HDS                                 HDS;
00045     typedef p_HDS                                 HalfedgeDS;
00046     typedef typename HDS::Traits                  Traits;
00047     typedef typename HDS::Vertex                  Vertex;
00048     typedef typename HDS::Halfedge                Halfedge;
00049     typedef typename HDS::Face                    Face;
00050 
00051     typedef typename HDS::Vertex_handle           Vertex_handle;
00052     typedef typename HDS::Vertex_const_handle     Vertex_const_handle;
00053     typedef typename HDS::Vertex_iterator         Vertex_iterator;
00054     typedef typename HDS::Vertex_const_iterator   Vertex_const_iterator;
00055 
00056     typedef typename HDS::Halfedge_handle         Halfedge_handle;
00057     typedef typename HDS::Halfedge_const_handle   Halfedge_const_handle;
00058     typedef typename HDS::Halfedge_iterator       Halfedge_iterator;
00059     typedef typename HDS::Halfedge_const_iterator Halfedge_const_iterator;
00060 
00061     typedef typename HDS::Face_handle             Face_handle;
00062     typedef typename HDS::Face_const_handle       Face_const_handle;
00063     typedef typename HDS::Face_iterator           Face_iterator;
00064     typedef typename HDS::Face_const_iterator     Face_const_iterator;
00065 
00066     typedef typename HDS::size_type               size_type;
00067     typedef typename HDS::difference_type         difference_type;
00068     typedef typename HDS::iterator_category       iterator_category;
00069 
00070 // The following types are equal to either `Tag_true' or `Tag_false',
00071 // dependent whether the named feature is supported or not.
00072 
00073     typedef typename HDS::Supports_vertex_halfedge
00074                                                   Supports_vertex_halfedge;
00075     typedef typename HDS::Supports_halfedge_prev  Supports_halfedge_prev;
00076     typedef typename HDS::Supports_halfedge_vertex
00077                                                   Supports_halfedge_vertex;
00078     typedef typename HDS::Supports_halfedge_face  Supports_halfedge_face;
00079     typedef typename HDS::Supports_face_halfedge  Supports_face_halfedge;
00080 
00081     typedef typename HDS::Supports_removal        Supports_removal;
00082 
00083 protected:
00084     typedef typename Vertex::Base                 VBase;
00085     typedef typename Halfedge::Base               HBase;
00086     typedef typename Halfedge::Base_base          HBase_base;
00087     typedef typename Face::Base                   FBase;
00088 
00089 // PRIVATE MEMBER VARIABLES
00090 // ----------------------------------
00091 private:
00092     p_HDS*  hds;
00093 
00094 // CREATION
00095     // ----------------------------------
00096 public:
00097     // No default constructor, keeps always a reference to a HDS!
00098 
00099     HalfedgeDS_decorator( p_HDS& h) : hds(&h) {}
00100         // keeps internally a reference to `hds'.
00101 
00102 // Creation of New Elements
00103 // ----------------------------------
00104 
00105     Vertex_handle vertices_push_back( const Vertex& v) {
00106         // appends a copy of v to `hds' if vertices are supported. Returns
00107         // handle of the new vertex, or `Vertex_handle()' otherwise.
00108         return vertices_push_back( v, Supports_halfedge_vertex());
00109     }
00110 
00111     Face_handle faces_push_back( const Face& f) {
00112         // appends a copy of f to `hds' if faces are supported. Returns
00113         // handle of the new face, or `Face_handle()' otherwise.
00114         return faces_push_back( f, Supports_halfedge_face());
00115     }
00116 
00117 private:
00118     Vertex_handle vertices_push_back( Vertex_const_handle v) {
00119         // appends a copy of *v to `hds' if vertices are supported. Returns
00120         // handle of the new vertex, or `Vertex_handle()' otherwise.
00121         return vertices_push_back( v, Supports_halfedge_vertex());
00122     }
00123 
00124     Face_handle faces_push_back( Face_const_handle f) {
00125         // appends a copy of *f to `hds' if faces are supported. Returns
00126         // handle of the new face, or `Face_handle()' otherwise.
00127         return faces_push_back( f, Supports_halfedge_face());
00128     }
00129 public:
00130 
00131 // Creation of New Composed Items
00132 // ----------------------------------
00133 
00134     Halfedge_handle create_loop() {
00135         // returns handle of a halfedge from a newly created loop in `hds'
00136         // consisting of a single closed edge, one vertex and two faces
00137         // (if supported respectively).
00138         Halfedge_handle h = hds->edges_push_back( Halfedge(), Halfedge());
00139         h->HBase::set_next( h);
00140         h->opposite()->HBase::set_next( h->opposite());
00141         set_prev( h, h);
00142         set_prev( h->opposite(), h->opposite());
00143         set_vertex( h, vertices_push_back( Vertex()));
00144         set_vertex( h->opposite(), get_vertex(h));
00145         set_face( h, faces_push_back( Face()));
00146         set_face( h->opposite(), faces_push_back( Face()));
00147         set_face_halfedge( h);
00148         set_face_halfedge( h->opposite());
00149         set_vertex_halfedge( h);
00150         return h;
00151     }
00152 
00153     Halfedge_handle create_segment() {
00154         // returns a halfedge from a newly created segment in `hds'
00155         // consisting of a single open edge, two vertices and one face (if
00156         // supported respectively).
00157         Halfedge_handle h = hds->edges_push_back( Halfedge(), Halfedge());
00158         h->HBase::set_next( h->opposite());
00159         h->opposite()->HBase::set_next( h);
00160         set_prev( h, h->opposite());
00161         set_prev( h->opposite(), h);
00162         set_vertex( h, vertices_push_back( Vertex()));
00163         set_vertex( h->opposite(), vertices_push_back( Vertex()));
00164         set_face( h, faces_push_back( Face()));
00165         set_face( h->opposite(), get_face(h));
00166         set_face_halfedge( h);
00167         set_vertex_halfedge( h);
00168         set_vertex_halfedge( h->opposite());
00169         return h;
00170     }
00171 
00172 // Removal of Elements
00173 // ----------------------------------
00174 
00175     void vertices_pop_front() {
00176         // removes the first vertex if vertices are supported.
00177         // Precondition: `Supports_removal' == `Tag_true'.
00178         vertices_pop_front( Supports_halfedge_vertex());
00179     }
00180     void vertices_pop_back() {
00181         // removes the last vertex if vertices are supported.
00182         vertices_pop_back( Supports_halfedge_vertex());
00183     }
00184     void vertices_erase( Vertex_handle v) {
00185         // removes the vertex v if vertices are supported. Precondition:
00186         // `Supports_removal' == `Tag_true'.
00187         vertices_erase( v, Supports_halfedge_vertex());
00188     }
00189     void vertices_erase( Vertex_handle first, Vertex_handle last) {
00190         // removes the range of vertices `[first,last)' if vertices
00191         // are supported. Precondition: `Supports_removal' ==
00192         // `Tag_true'.
00193         vertices_erase( first, last, Supports_halfedge_vertex());
00194     }
00195 
00196     void faces_pop_front() {
00197         // removes the first face if faces are supported. Precondition:
00198         // `Supports_removal' == `Tag_true'.
00199         faces_pop_front( Supports_halfedge_face());
00200     }
00201     void faces_pop_back() {
00202         // removes the last face if faces are supported.
00203         faces_pop_back( Supports_halfedge_face());
00204     }
00205     void faces_erase( Face_handle f) {
00206         // removes the face f if faces are supported. Precondition:
00207         // `Supports_removal' == `Tag_true'.
00208         faces_erase( f, Supports_halfedge_face());
00209     }
00210     void faces_erase( Face_handle first, Face_handle last) {
00211         // removes the range of faces `[first,last)' if faces
00212         // are supported. Precondition: `Supports_removal' ==
00213         // `Tag_true'.
00214         faces_erase( first, last, Supports_halfedge_face());
00215     }
00216 
00217 
00218 // Modifying Functions (Euler Operators)
00219 // -------------------------------------
00220 
00221 // The following Euler operations modify consistently the combinatorial
00222 // structure of the halfedge data structure. The geometry remains
00223 // unchanged. Note that well known graph operations are also captured with
00224 // these Euler operators, for example an edge contraction is equal to a
00225 // `join_vertex()' operation, or an edge removal to `join_face()'.
00226 //
00227 // Given a halfedge data structure `hds' and a halfedge handle h four
00228 // special applications of the Euler operators are worth mentioning:
00229 // `split_vertex(h,h)' results in an antenna emanating from the tip of `h';
00230 // `split_vertex(h,h->next()->opposite())' results in an edge split of
00231 // the halfedge `h->next' with a new vertex in-between; `split_face(h,h)'
00232 // results in a loop directly following `h'; and `split_face(h,h->next())'
00233 // results in a bridge parallel to the halfedge `h->next' with a new face
00234 // in-between.
00235 
00236     Halfedge_handle split_face( Halfedge_handle h, Halfedge_handle g) {
00237         // splits the face incident to `h' and `g' into two faces with a
00238         // new diagonal between the two vertices denoted by `h' and `g'
00239         // respectively. The second (new) face obtained from `hds' is a
00240         // copy of the first face. The new diagonal is returned. The time
00241         // is proportional to the distance from `h' to `g' around the
00242         // face.
00243         Halfedge_handle hnew = hds->edges_push_back( Halfedge(),
00244                                                      Halfedge());
00245         Face_handle fnew = faces_push_back( get_face(h));
00246         insert_tip( hnew, g);
00247         insert_tip( hnew->opposite(), h);
00248         set_face( hnew, get_face(h));
00249         set_face_in_face_loop( hnew->opposite(), fnew);
00250         set_face_halfedge( hnew);
00251         set_face_halfedge( hnew->opposite());
00252         return hnew;
00253     }
00254 
00255     Halfedge_handle join_face( Halfedge_handle h) {
00256         // joins the two faces incident to h. The face incident to
00257         // `h->opposite()' gets removed from `hds'. Both faces might be
00258         // holes. Returns the predecessor of h around the face. The
00259         // invariant `join_face( split_face( h, g))' returns h and keeps
00260         // the data structure unchanged. The time is proportional to the
00261         // size of the face removed and the time to compute `h->prev()'.
00262         // Precondition: `Supports_removal' == `Tag_true'.
00263         Assert_compile_time_tag( Tag_true(), Supports_removal());
00264         Halfedge_handle hprev = find_prev( h);
00265         Halfedge_handle gprev = find_prev( h->opposite());
00266         remove_tip( hprev);
00267         remove_tip( gprev);
00268         hds->edges_erase( h);
00269         if ( get_face( gprev) != Face_handle())
00270             faces_erase( get_face( gprev));
00271         h = hprev;
00272         // 'half' of the halfedges have their correct faces.
00273         // Here we do the remaining halfedges.
00274         CGAL_assertion_code( std::size_t termination_count = 0;)
00275         while ( h != gprev) {
00276             CGAL_assertion( ++termination_count != 0);
00277             h = h->next();
00278             set_face( h, get_face( hprev));
00279         }
00280         if ( get_face( hprev) != Face_handle())
00281             set_face_halfedge(  hprev);
00282         set_vertex_halfedge( hprev);
00283         set_vertex_halfedge( gprev);
00284         return hprev;
00285     }
00286 
00287     Halfedge_handle split_vertex( Halfedge_handle h, Halfedge_handle g) {
00288         // splits the vertex incident to `h' and `g' into two vertices and
00289         // connects them with a new edge. The second (new) vertex obtained
00290         // from `hds' is a copy of the first vertex. The new edge is
00291         // returned. The time is proportional to the distance from `h' to
00292         // `g' around the vertex.
00293         Halfedge_handle hnew = hds->edges_push_back( Halfedge(),
00294                                                      Halfedge());
00295         Vertex_handle vnew = vertices_push_back( get_vertex(h));
00296         insert_halfedge( hnew, g);
00297         insert_halfedge( hnew->opposite(), h);
00298         set_vertex( hnew, get_vertex(h));
00299         set_vertex_in_vertex_loop( hnew->opposite(), vnew);
00300         set_vertex_halfedge( hnew);
00301         set_vertex_halfedge( hnew->opposite());
00302         return hnew;
00303     }
00304 
00305     Halfedge_handle join_vertex( Halfedge_handle h) {
00306         // joins the two vertices incident to h. The vertex denoted by
00307         // `h->opposite()' gets removed by `hds'. Returns the predecessor
00308         // of h around the vertex. The invariant `join_vertex(
00309         // split_vertex( h, g))' returns h and keeps the polyhedron
00310         // unchanged. The time is proportional to the degree of the vertex
00311         // removed and the time to compute `h->prev()'. Precondition:
00312         // `Supports_removal' == `Tag_true'.
00313         Assert_compile_time_tag( Tag_true(), Supports_removal());
00314         Halfedge_handle hprev = find_prev( h->opposite());
00315         Halfedge_handle gprev = find_prev( h);
00316         remove_halfedge( hprev);
00317         remove_halfedge( gprev);
00318         hds->edges_erase( h);
00319         vertices_erase( get_vertex( gprev));
00320         // 'half' of the halfedges have their correct vertex.
00321         // Here we do the remaining halfedges.
00322         h = hprev;
00323         CGAL_assertion_code( std::size_t termination_count = 0;)
00324         while ( h != gprev) {
00325             CGAL_assertion( ++termination_count != 0);
00326             h = h->next()->opposite();
00327             set_vertex( h, get_vertex( hprev));
00328         }
00329         set_vertex_halfedge( hprev);
00330         if ( ! hprev->is_border())
00331             set_face_halfedge(  hprev);
00332         if ( ! gprev->is_border())
00333             set_face_halfedge(  gprev);
00334         return hprev;
00335     }
00336 
00337     Halfedge_handle create_center_vertex( Halfedge_handle h) {
00338         Halfedge_handle hnew = hds->edges_push_back( Halfedge(),
00339                                                      Halfedge());
00340         Vertex_handle vnew = vertices_push_back( get_vertex( h));
00341         close_tip( hnew, vnew);
00342         insert_tip( hnew->opposite(), h);
00343         set_face( hnew, get_face( h));
00344         set_face_halfedge( h);
00345         Halfedge_handle g = hnew->opposite()->next();
00346         while ( g->next() != hnew) {
00347             Halfedge_handle gnew = hds->edges_push_back( Halfedge(),
00348                                                          Halfedge());
00349             insert_tip( gnew, hnew);
00350             insert_tip( gnew->opposite(), g);
00351             Face_handle fnew = faces_push_back( get_face(hnew));
00352             set_face( g, fnew);
00353             set_face( gnew, fnew);
00354             set_face( gnew->next(), fnew);
00355             set_face_halfedge( g);
00356             g = gnew->opposite()->next();
00357         }
00358         set_face( hnew->next(), get_face( hnew));
00359         set_vertex_halfedge( hnew);
00360         return hnew;
00361     }
00362 
00363     Halfedge_handle erase_center_vertex( Halfedge_handle h) {
00364         // h points to the vertex that gets removed
00365         Halfedge_handle g    = h->next()->opposite();
00366         Halfedge_handle hret = find_prev( h);
00367         while ( g != h) {
00368             Halfedge_handle gprev = find_prev( g);
00369             set_vertex_halfedge( gprev);
00370             remove_tip( gprev);
00371             if ( get_face( g) != Face_handle())
00372                 faces_erase( get_face( g));
00373             Halfedge_handle gnext = g->next()->opposite();
00374             hds->edges_erase( g);
00375             g = gnext;
00376         }
00377         set_vertex_halfedge( hret);
00378         remove_tip( hret);
00379         vertices_erase( get_vertex( h));
00380         hds->edges_erase( h);
00381         set_face_in_face_loop( hret, get_face( hret));
00382         set_face_halfedge(hret);
00383         return hret;
00384     }
00385 
00386     Halfedge_handle split_loop( Halfedge_handle h,
00387                                 Halfedge_handle i,
00388                                 Halfedge_handle j) {
00389         // cuts the halfedge data structure into two parts along the cycle
00390         // (h,i,j). Three new vertices (one copy for each vertex in the
00391         // cycle) and three new halfedges (one copy for each halfedge in
00392         // the cycle), and two new triangles are created. h,i,j will be
00393         // incident to the first new triangle. The return value will be
00394         // the halfedge incident to the second new triangle which is the
00395         // copy of `h-opposite()'. Precondition: h,i,j denote distinct,
00396         // consecutive vertices of the halfedge data structure and form a
00397         // cycle: i.e. `h->vertex() == i->opposite()->vertex()', ...,
00398         // `j->vertex() == h->opposite()->vertex()'.
00399         CGAL_precondition( h != i);
00400         CGAL_precondition( h != j);
00401         CGAL_precondition( i != j);
00402         CGAL_precondition( get_vertex(h) == get_vertex(i->opposite()));
00403         CGAL_precondition( get_vertex(i) == get_vertex(j->opposite()));
00404         CGAL_precondition( get_vertex(j) == get_vertex(h->opposite()));
00405         // Create a copy of the triangle.
00406         Halfedge_handle hnew = hds->edges_push_back( *h);
00407         Halfedge_handle inew = hds->edges_push_back( *i);
00408         Halfedge_handle jnew = hds->edges_push_back( *j);
00409         close_tip( hnew, vertices_push_back( get_vertex( h)));
00410         close_tip( inew, vertices_push_back( get_vertex( i)));
00411         close_tip( jnew, vertices_push_back( get_vertex( j)));
00412         insert_tip( inew->opposite(), hnew);
00413         insert_tip( jnew->opposite(), inew);
00414         insert_tip( hnew->opposite(), jnew);
00415         // Make the new incidences with the old stucture.
00416         CGAL_assertion_code( std::size_t termination_count = 0;)
00417         if ( h->next() != i) {
00418             Halfedge_handle g = h->next();
00419             h->HBase::set_next( i);
00420             set_prev( i, h);
00421             hnew->HBase::set_next( g);
00422             set_prev( g, hnew);
00423             g = g->opposite();
00424             while ( g->next() != i) {
00425                 CGAL_assertion( ++termination_count != 0);
00426                 set_vertex( g, get_vertex( hnew));
00427                 g = g->next()->opposite();
00428             }
00429             set_vertex( g, get_vertex( hnew));
00430             g->HBase::set_next( inew);
00431             set_prev( inew, g);
00432         }
00433         if ( i->next() != j) {
00434             Halfedge_handle g = i->next();
00435             i->HBase::set_next( j);
00436             set_prev( j, i);
00437             inew->HBase::set_next( g);
00438             set_prev( g, inew);
00439             g = g->opposite();
00440             while ( g->next() != j) {
00441                 CGAL_assertion( ++termination_count != 0);
00442                 set_vertex( g, get_vertex( inew));
00443                 g = g->next()->opposite();
00444             }
00445             set_vertex( g, get_vertex( inew));
00446             g->HBase::set_next( jnew);
00447             set_prev( jnew, g);
00448         }
00449         if ( j->next() != h) {
00450             Halfedge_handle g = j->next();
00451             j->HBase::set_next( h);
00452             set_prev( h, j);
00453             jnew->HBase::set_next( g);
00454             set_prev( g, jnew);
00455             g = g->opposite();
00456             while ( g->next() != h) {
00457                 CGAL_assertion( ++termination_count != 0);
00458                 set_vertex( g, get_vertex( jnew));
00459                 g = g->next()->opposite();
00460             }
00461             set_vertex( g, get_vertex( jnew));
00462             g->HBase::set_next( hnew);
00463             set_prev( hnew, g);
00464         }
00465         // Fill the holes with two new faces.
00466         Face_handle f = faces_push_back( Face());
00467         set_face( h, f);
00468         set_face( i, f);
00469         set_face( j, f);
00470         set_face_halfedge( h);
00471         f = faces_push_back( Face());
00472         set_face( hnew->opposite(), f);
00473         set_face( inew->opposite(), f);
00474         set_face( jnew->opposite(), f);
00475         set_face_halfedge( hnew->opposite());
00476         // Take care of maybe changed halfedge pointers.
00477         set_face_halfedge( hnew);
00478         set_face_halfedge( inew);
00479         set_face_halfedge( jnew);
00480         set_vertex_halfedge( hnew);
00481         set_vertex_halfedge( inew);
00482         set_vertex_halfedge( jnew);
00483         return hnew->opposite();
00484     }
00485 
00486     Halfedge_handle join_loop( Halfedge_handle h, Halfedge_handle g) {
00487         // glues the boundary of the two faces denoted by h and g together
00488         // and returns h. Both faces and the vertices along the face
00489         // denoted by g gets removed. Both faces may be holes. The
00490         // invariant `join_loop( h, split_loop( h, i, j))' returns h and
00491         // keeps the data structure unchanged. Precondition:
00492         // `Supports_removal' == `Tag_true'. The faces denoted by h
00493         // and g are different and have equal degree (i.e. number of
00494         // edges).
00495         Assert_compile_time_tag( Tag_true(), Supports_removal());
00496         CGAL_precondition(    get_face(h) == Face_handle()
00497                     || get_face(h) != get_face(g));
00498         if ( get_face( h) != Face_handle())
00499             faces_erase( get_face(h));
00500         if ( get_face( g) != Face_handle())
00501             faces_erase( get_face(g));
00502         Halfedge_handle hi = h;
00503         Halfedge_handle gi = g;
00504         CGAL_assertion_code( std::size_t termination_count = 0;)
00505         do {
00506             CGAL_assertion( ++termination_count != 0);
00507             Halfedge_handle hii = hi;
00508             Halfedge_handle gii = gi;
00509             hi = hi->next();
00510             // gi = find_prev(gi); // Replaced by search around vertex.
00511             set_face( hii, get_face( gii->opposite()));
00512             set_face_halfedge( hii);
00513             vertices_erase( get_vertex( gii->opposite()));
00514             if ( gii->opposite()->next()->opposite()->next() == gii) {
00515                 gi = gii->opposite()->next()->opposite();
00516             } else {
00517                 hii->HBase::set_next( gii->opposite()->next());
00518                 set_prev( hii->next(), hii);
00519                 gii = gii->opposite()->next()->opposite();
00520                 set_vertex( gii, get_vertex(hii));
00521                 while ( gii->next()->opposite()->next() != gi) {
00522                     CGAL_assertion( ++termination_count != 0);
00523                     gii = gii->next()->opposite();
00524                     set_vertex( gii, get_vertex(hii));
00525                 }
00526                 gi = gii->next()->opposite();
00527                 gii->HBase::set_next( hi);
00528                 set_prev( gii->next(), gii);
00529             }
00530         } while ( hi != h);
00531         CGAL_assertion( gi == g);
00532         do {
00533             Halfedge_handle gii = gi;
00534             gi = gi->next();
00535             hds->edges_erase( gii);
00536         } while ( gi != g);
00537         return h;
00538     }
00539 
00540   protected:
00541     // supports face or not.
00542     void make_hole( Halfedge_handle, Tag_false) {}
00543     void fill_hole( Halfedge_handle, Tag_false) {}
00544     void fill_hole( Halfedge_handle, const Face&, Tag_false) {}
00545 
00546     void make_hole( Halfedge_handle h, Tag_true) {
00547         Assert_compile_time_tag( Tag_true(), Supports_removal());
00548         CGAL_precondition( h != Halfedge_handle());
00549         CGAL_precondition( ! h->is_border());
00550         hds->faces_erase( h->face());
00551         set_face_in_face_loop( h, Face_handle());
00552     }
00553 
00554     void fill_hole( Halfedge_handle h, Tag_true) {
00555         CGAL_precondition( h != Halfedge_handle());
00556         CGAL_precondition( h->is_border());
00557         Face_handle f = faces_push_back( Face());
00558         set_face_in_face_loop( h, f);
00559         set_face_halfedge( h);
00560     }
00561 
00562     void fill_hole( Halfedge_handle h, const Face& f, Tag_true) {
00563         CGAL_precondition( h != Halfedge_handle());
00564         CGAL_precondition( h->is_border());
00565         Face_handle fh = faces_push_back( f);
00566         set_face_in_face_loop( h, fh);
00567         set_face_halfedge( h);
00568     }
00569 
00570   public:
00571 
00572     Halfedge_handle make_hole( Halfedge_handle h) {
00573         // removes the face incident to `h' from `hds' and creates a hole.
00574         // Precondition: `h != Halfedge_handle()' and `!(h->is_border())'.
00575         // If faces are supported, `Supports_removal' == `Tag_true'.
00576         make_hole( h, Supports_halfedge_face());
00577         return h;
00578     }
00579 
00580     Halfedge_handle fill_hole( Halfedge_handle h) {
00581         // fills the hole incident to `h' with a new face from `hds'.
00582         // Precondition: `h != Halfedge_handle()' and `h->is_border()'.
00583         fill_hole( h, Supports_halfedge_face());
00584         return h;
00585     }
00586 
00587     Halfedge_handle fill_hole( Halfedge_handle h, const Face& f) {
00588         // fills the hole incident to `h' with a copy of face f.
00589         // Precondition: `h != Halfedge_handle()' and `h->is_border()'.
00590         fill_hole( h, f, Supports_halfedge_face());
00591         return h;
00592     }
00593 
00594     Halfedge_handle add_face_to_border( Halfedge_handle h,
00595                                         Halfedge_handle g,
00596                                         const Face& f) {
00597         // extends the surface with a copy of face f into the hole
00598         // incident to h and g. It creates a new edge connecting the tip
00599         // of g with the tip of h and fills this separated part of the
00600         // hole with a copy of face f, such that the new face is incident
00601         // to g. Returns the new halfedge that is incident to the new
00602         // face. Precondition: `h != Halfedge_handle()', `g !=
00603         // Halfedge_handle()', `h->is_border()', `g->is_border()' and g
00604         // can be reached along the hole starting with h.
00605         CGAL_precondition( h != Halfedge_handle());
00606         CGAL_precondition( g != Halfedge_handle());
00607         CGAL_precondition( h->is_border());
00608         CGAL_precondition( g->is_border());
00609         Halfedge_handle hh = hds->edges_push_back( Halfedge(), Halfedge());
00610         insert_tip( hh, h);
00611         insert_tip( hh->opposite(), g);
00612         fill_hole( g, f);
00613         return hh;
00614     }
00615 
00616     Halfedge_handle add_face_to_border( Halfedge_handle h,
00617                                         Halfedge_handle g) {
00618         // extends the surface with a new face from `hds' into the hole
00619         // incident to h and g. It creates a new edge connecting the tip
00620         // of g with the tip of h and fills this separated part of the
00621         // hole with a new face, such that the new face is incident to g.
00622         // Returns the new halfedge that is incident to the new face.
00623         // Precondition: `h != Halfedge_handle()', `g != Halfedge_handle(
00624         // )', `h->is_border()', `g->is_border()' and g can be reached
00625         // along the hole starting with h.
00626         return add_face_to_border( h, g, Face());
00627     }
00628 
00629 // Erasing
00630 // ----------------------------------
00631   protected:
00632     // supports face or not.
00633     void erase_face( Halfedge_handle,   Tag_false) {}
00634     void erase_face( Halfedge_handle h, Tag_true)  {
00635         Assert_compile_time_tag( Tag_true(), Supports_removal());
00636         CGAL_precondition( h != Halfedge_handle());
00637         CGAL_precondition( ! h->is_border());
00638         hds->faces_erase( h->face());
00639         CGAL_assertion_code( std::size_t termination_count = 0;)
00640         Halfedge_handle end = h;
00641         do {
00642             CGAL_assertion( ++termination_count != 0);
00643             set_face( h, Face_handle());
00644             Halfedge_handle g = h->next();
00645             bool h_tag = h->opposite()->is_border();
00646             bool g_tag = g->opposite()->is_border();
00647             if ( h_tag && g_tag && g->opposite()->next() == h->opposite()){
00648                 vertices_erase( get_vertex(h));
00649                 if ( h != end)
00650                     hds->edges_erase( h);
00651             } else {
00652                 if ( g_tag) {
00653                     set_vertex_halfedge(g->opposite()->next()->opposite());
00654                     remove_tip(h);
00655                 }
00656                 if ( h_tag) {
00657                     set_vertex_halfedge(h->next()->opposite());
00658                     remove_tip( find_prev_around_vertex( h->opposite()));
00659                     if ( h != end)
00660                         hds->edges_erase(h);
00661                 }
00662             }
00663             h = g;
00664         } while ( h != end);
00665         if ( h->opposite()->is_border())
00666             hds->edges_erase( h);
00667     }
00668 
00669   public:
00670     void erase_face( Halfedge_handle h) {
00671         // removes the face incident to `h' from `hds' and changes all
00672         // halfedges incident to the face into border edges or removes
00673         // them from the halfedge data structure if they were already
00674         // border edges. See `make_hole(h)' for a more specialized
00675         // variant. Precondition: `h != Halfedge_handle()'. If faces are
00676         // supported, `Supports_removal' == `Tag_true'.
00677         erase_face( h, Supports_halfedge_face());
00678     }
00679 
00680   protected:                               // Supports_halfedge_vertices
00681       void erase_connected_component_vertex( Halfedge_handle  ,Tag_false){}
00682       void erase_connected_component_vertex( Halfedge_handle h, Tag_true) {
00683           // Erases the the vertex incident to h and sets all references
00684           // from halfedges around this vertex to Halfedge_handle(),
00685           // if the incident vertex handle is not already equal to
00686           // Halfedge_handle(). It is used to erase vertices as soon
00687           // as an vertex is encountered in the graph traversal. At this
00688           // point of the graph traversal the halfedge cycle around the
00689           // vertex is still closed. Lateron it will be broken.
00690           if ( h->vertex() != Vertex_handle()) {
00691               hds->vertices_erase( h->vertex());
00692               set_vertex_in_vertex_loop( h, Vertex_handle());
00693           }
00694       }
00695       void erase_connected_component_vertex( Halfedge_handle h) {
00696           erase_connected_component_vertex( h, Supports_halfedge_vertex());
00697       }
00698 
00699       void erase_connected_component_face_cycle( Halfedge_handle h,
00700                   std::vector<Halfedge_handle>& stack) {
00701           // Delete incident face and set all incidences to Face_handle().
00702           if ( get_face(h) != Face_handle()) {
00703               faces_erase( get_face(h));
00704               set_face_in_face_loop( h, Face_handle());
00705           }
00706           // Cycle around face, delete incident vertices, push new
00707           // edges on the stack and mark edges as visited.
00708           erase_connected_component_vertex( h);
00709           Halfedge_handle g = h->next();
00710           h->HBase::set_next( Halfedge_handle());
00711           while (g != h) {
00712               erase_connected_component_vertex( g);
00713               if ( g->opposite()->next() != Halfedge_handle())
00714                   stack.push_back( g->opposite());
00715               Halfedge_handle gg = g->next();
00716               g->HBase::set_next( Halfedge_handle());
00717               g = gg;
00718           }
00719       }
00720 
00721   public:
00722     void erase_connected_component( Halfedge_handle h) {
00723         // removes the vertices, halfedges, and facets that belong to the
00724         // connected component of h. Precondition: `Supports_removal'
00725         // == `Tag_true'. For all halfedges g in the connected
00726         // component `g.next() != Halfedge_handle()'.
00727         Assert_compile_time_tag( Tag_true(), Supports_removal());
00728         typedef std::vector<Halfedge_handle> HVector;
00729         HVector stack;
00730         // Algorithm: The next() pointer is used as visited tag
00731         //     for a graph search. If the next pointer of an halfedge
00732         //     or its opposite halfedge is set to Halfedge_handle(),
00733         //     this edge has already been visited and must not be put
00734         //     on the stack again.
00735         // Initializing: Cycle through the face-cycle of h and put
00736         //     all opposite halfedges on the stack. Put h->opposite()
00737         //     on the stack. Note that even if the face cycle of h looks
00738         //     ugly ( e.g. h->opposite() is also in the cycle), neither
00739         //     h nor h->opposite() will be put on the stack. If
00740         //     h->opposite() is in the cycle, when h will be popped from
00741         //     the stack it will be immediately deleted.
00742         // Loop invariant: For each edge h on the stack h->opposite()->
00743         //     next() == Halfedge_handle().
00744         // Looping: For each edge h on the stack, if h->next() is
00745         //     not already equal to Halfedge_handle(), cycle through
00746         //     the face-cycle of h and put all opposite halfedges on
00747         //     the stack. Delete h.
00748         // Where: Cycle through a face means: If h->face() !=
00749         //     Halfedge_handle() delete h->face() and set all face
00750         //     handles to Halfedge_handle(). Loop through the
00751         //     halfedges g around the face, call
00752         //     erase_connected_component_vertex for each g, push
00753         //     g->opposite() on the stack if g->opposite()->next()
00754         //     is not already Halfedge_handle(). This implies that
00755         //     h->opposite() is not put on the stack again.
00756         erase_connected_component_face_cycle( h, stack);
00757         stack.push_back( h->opposite());
00758         while ( ! stack.empty()) {
00759             h = stack.back();
00760             stack.pop_back();
00761             CGAL_assertion( h->opposite()->next() == Halfedge_handle());
00762             if ( h->next() != Halfedge_handle())
00763                 erase_connected_component_face_cycle( h, stack);
00764             hds->edges_erase( h);
00765         }
00766     }
00767 
00777     unsigned int keep_largest_connected_components(unsigned int nb_components_to_keep)
00778     {
00779         Assert_compile_time_tag(Supports_removal(), Tag_true());
00780         Assert_compile_time_tag(Supports_vertex_halfedge(), Tag_true());
00781 
00782         unsigned int nb_erased_components = 0,
00783                      nb_isolated_vertices = 0;
00784 
00785         // Gets list of connected components, ordered by size (i.e. number of vertices)
00786         std::vector<Vertex_handle> components;
00787         get_connected_components(std::back_inserter(components));
00788 
00789         // Erases all connected components but the largest
00790         while (components.size() > nb_components_to_keep)
00791         {
00792           Vertex_handle vertex = *(components.begin());
00793 
00794           // Removes component from list
00795           components.erase(components.begin());
00796 
00797           if (vertex->halfedge() != NULL) // if not isolated vertex
00798           {
00799             erase_connected_component(vertex->halfedge());
00800             nb_erased_components++;
00801           }
00802           else // if isolated vertex
00803           {
00804             vertices_erase(vertex);
00805             nb_isolated_vertices++;
00806           }
00807         }
00808 
00809 //         if (nb_isolated_vertices > 0)
00810 //           std::cerr << "  Erased " << nb_isolated_vertices << " isolated vertices\n";
00811 
00812         return nb_erased_components;
00813     }
00814 
00815 // Implementing These Functions.
00816 // ====================================================
00817 // Creation of New Elements
00818 // ----------------------------------
00819 private:
00820 
00821     Vertex_handle vertices_push_back( const Vertex&  , Tag_false) {
00822         return Vertex_handle();
00823     }
00824     Vertex_handle vertices_push_back( const Vertex& v, Tag_true) {
00825         return hds->vertices_push_back(v);
00826     }
00827 
00828     Vertex_handle vertices_push_back( Vertex_const_handle  , Tag_false) {
00829         return Vertex_handle();
00830     }
00831     Vertex_handle vertices_push_back( Vertex_const_handle v, Tag_true) {
00832         return hds->vertices_push_back(*v);
00833     }
00834 
00835     Face_handle faces_push_back( const Face&  , Tag_false) {
00836         return Face_handle();
00837     }
00838     Face_handle faces_push_back( const Face& f, Tag_true) {
00839         return hds->faces_push_back(f);
00840     }
00841 
00842     Face_handle faces_push_back( Face_const_handle  , Tag_false) {
00843         return Face_handle();
00844     }
00845     Face_handle faces_push_back( Face_const_handle f, Tag_true) {
00846         return hds->faces_push_back(*f);
00847     }
00848 
00849 
00850 // Removal of Elements
00851 // ----------------------------------
00852 
00853     void vertices_erase( Vertex_handle  , Tag_false) {}
00854     void vertices_erase( Vertex_handle v, Tag_true) {
00855         hds->vertices_erase( v);
00856     }
00857 
00858     void vertices_pop_front( Tag_false) {}
00859     void vertices_pop_front( Tag_true) {
00860         hds->vertices_pop_front();
00861     }
00862 
00863     void vertices_pop_back( Tag_false) {}
00864     void vertices_pop_back( Tag_true) {
00865         hds->vertices_pop_back();
00866     }
00867 
00868     void faces_erase( Face_handle  , Tag_false) {}
00869     void faces_erase( Face_handle f, Tag_true) {
00870         hds->faces_erase( f);
00871     }
00872 
00873     void faces_pop_front( Tag_false) {}
00874     void faces_pop_front( Tag_true) {
00875         hds->faces_pop_front();
00876     }
00877 
00878     void faces_pop_back( Tag_false) {}
00879     void faces_pop_back( Tag_true) {
00880         hds->faces_pop_back();
00881     }
00882 
00886     enum { tag_free, tag_done };
00887 
00894     Vertex_handle get_any_free_vertex(
00895       /*const*/ std::map<Vertex*, int>& tags) 
00896     {
00897         for (Vertex_iterator it = hds->vertices_begin(); it != hds->vertices_end(); it++)
00898         {
00899             if (tags[&*it] == tag_free)
00900                 return it;
00901         }
00902 
00903         return NULL;
00904     }
00905 
00911     unsigned int tag_component(
00912       Vertex_handle pSeedVertex, 
00913       std::map<Vertex*, int>& tags) 
00914     {
00915         // Circulator category.
00916         typedef typename Halfedge::Supports_halfedge_prev  Supports_prev;
00917         typedef HalfedgeDS_circulator_traits<Supports_prev> Ctr;
00918         typedef typename Ctr::iterator_category circulator_category;
00919 
00920         // Circulator around a vertex
00921         typedef I_HalfedgeDS_vertex_circ< Halfedge_handle, circulator_category>
00922                                             Halfedge_around_vertex_circulator;
00923 
00924         unsigned int number_of_vertices = 0; // size (number of vertices) of the component
00925 
00926         std::list<Vertex_handle> vertices;
00927         vertices.push_front(pSeedVertex);
00928         while (!vertices.empty())
00929         {
00930             Vertex_handle pVertex = vertices.front();
00931             vertices.pop_front();
00932 
00933             // Skip vertex if already done
00934             if (tags[&*pVertex] == tag_done)
00935                 continue;
00936 
00937             // Mark vertex done
00938             tags[&*pVertex] = tag_done;
00939             number_of_vertices++;
00940 
00941             // Add vertex's "free" neighbors to the list
00942             Halfedge_around_vertex_circulator neighbor_cir, neighbor_end;
00943             neighbor_cir = pVertex->vertex_begin();
00944             neighbor_end = neighbor_cir;
00945             CGAL_For_all(neighbor_cir,neighbor_end)
00946             {
00947                 Vertex_handle neighbor = neighbor_cir->opposite()->vertex();
00948                 if (tags[&*neighbor] == tag_free)
00949                     vertices.push_front(neighbor);
00950             }
00951         }
00952 
00953         return number_of_vertices;
00954     }
00955 
00963     template<typename OutputIterator>
00964     void get_connected_components(
00965         OutputIterator output) 
00966     {
00967         // Implementation note:
00968         // We tag vertices instead of halfedges to save a factor 6.
00969         // The drawback is that we require the Polyhedron_3<Traits> to support vertices.
00970         // TODO: replace std::map by a property map to tag vertices.
00971         Assert_compile_time_tag(Supports_halfedge_vertex(), Tag_true());
00972         std::map<Vertex*, int> tags;
00973 
00974         // list of all connected components of a polyhedron, ordered by size.
00975         std::multimap<unsigned int, Vertex_handle> components;
00976 
00977         // Tag all mesh vertices as "free".
00978         for (Vertex_iterator it = hds->vertices_begin(); it != hds->vertices_end(); it++)
00979         {
00980             tags[&*it] = tag_free;
00981         }
00982 
00983         // Record each component
00984         Vertex_handle seed_vertex = NULL;
00985         while((seed_vertex = get_any_free_vertex(tags)) != NULL)
00986         {
00987             // Tag it as "done" and compute its size (number of vertices)
00988             unsigned int number_of_vertices = tag_component(seed_vertex, tags);
00989 
00990             // Add component to ordered list
00991             components.insert(std::make_pair(number_of_vertices, seed_vertex));
00992         }
00993 
00994         // Copy ordered list to output iterator
00995         typename std::multimap<unsigned int, Vertex_handle>::iterator src;
00996         for (src = components.begin(); src != components.end(); ++src)
00997           *output++ = src->second;
00998     }
00999 
01000 // Others
01001 // ----------------------------------
01002 public:
01003 
01004     bool normalized_border_is_valid( bool verb = false) const {
01005         // returns `true' if the border halfedges are in normalized
01006         // representation, which is when enumerating all halfedges with
01007         // the halfedge iterator the following holds: The non-border edges
01008         // precede the border edges. For border edges, the second halfedge
01009         // is a border halfedge. (The first halfedge may or may not be a
01010         // border halfedge.) The halfedge iterator `border_halfedges_begin
01011         // ()' denotes the first border edge. If `verbose' is `true',
01012         // statistics are written to `cerr'.
01013         HalfedgeDS_const_decorator<p_HDS> decorator(*hds);
01014         return decorator.normalized_border_is_valid( verb);
01015     }
01016     bool is_valid( bool verb = false, int level = 0) const {
01017         // returns `true' if the halfedge data structure `hds' is valid
01018         // with respect to the `level' value as defined in the reference
01019         // manual. If `verbose' is `true', statistics are written to
01020         // `cerr'.
01021         HalfedgeDS_const_decorator<p_HDS> decorator(*hds);
01022         return decorator.is_valid( verb, level);
01023     }
01024     void reorient_face( Halfedge_handle first);
01025                   // Supports: halfedge pointer in faces.
01026     void inside_out( Tag_false);
01027     void inside_out( Tag_true);
01028 
01029     void inside_out() {
01030         inside_out( Supports_face_halfedge());
01031     }
01032 };
01033 
01034 template < class p_HDS >  CGAL_MEDIUM_INLINE
01035 void
01036 HalfedgeDS_decorator<p_HDS>::
01037 reorient_face( Halfedge_handle first) {
01038     if ( first == Halfedge_handle())
01039         return;
01040     Halfedge_handle last  = first;
01041     Halfedge_handle prev  = first;
01042     Halfedge_handle start = first;
01043     first = first->next();
01044     Vertex_handle  new_v = get_vertex( start);
01045     while (first != last) {
01046         Vertex_handle  tmp_v = get_vertex( first);
01047         set_vertex( first, new_v);
01048         set_vertex_halfedge( first);
01049         new_v = tmp_v;
01050         Halfedge_handle next = first->next();
01051         first->HBase::set_next( prev);
01052         set_prev( first, next);
01053         prev  = first;
01054         first = next;
01055     }
01056     set_vertex( start, new_v);
01057     set_vertex_halfedge( start);
01058     Halfedge_handle next = start->next();
01059     start->HBase::set_next( prev);
01060     set_prev( start, next);
01061 }
01062 
01063 template < class p_HDS >
01064 void                            // Supports: halfedge pointer in faces.
01065 HalfedgeDS_decorator<p_HDS>::
01066 inside_out( Tag_false) {
01067     Halfedge_iterator begin = hds->halfedges_begin();
01068     Halfedge_iterator end   = hds->halfedges_end();
01069     for( ; begin != end; ++begin) {
01070         // Define the halfedge with the `smallest' pointer
01071         // value as the one that is used to reorient the face.
01072         Halfedge_handle h = begin;
01073         bool is_min = true;
01074         Halfedge_handle c = h;
01075         Halfedge_handle d = c;
01076         do {
01077             CGAL_assertion( c != Halfedge_handle());
01078             if ( &*h > &*c)
01079                 is_min = false;
01080             c = c->next();
01081         } while ( c != d && is_min);
01082         if ( is_min)
01083             reorient_face( h);
01084     }
01085 }
01086 
01087 template < class p_HDS >
01088 void                            // Supports: halfedge pointer in faces.
01089 HalfedgeDS_decorator<p_HDS>::
01090 inside_out( Tag_true) {
01091     Face_iterator begin = hds->faces_begin();
01092     Face_iterator end   = hds->faces_end();
01093     for( ; begin != end; ++begin)
01094         reorient_face( begin->halfedge());
01095     // Note: A border edge is now parallel to its opposite edge.
01096     // We scan all border edges for this property. If it holds, we
01097     // reorient the associated hole and search again until no border
01098     // edge with that property exists any longer. Then, all holes are
01099     // reoriented.
01100     Halfedge_iterator first = hds->halfedges_begin();
01101     Halfedge_iterator last  = hds->halfedges_end();
01102     for( ; first != last; ++first) {
01103         if ( first->is_border() &&
01104              first->vertex() == first->opposite()->vertex())
01105             reorient_face( first);
01106     }
01107 }
01108 
01109 CGAL_END_NAMESPACE
01110 
01111 #endif // CGAL_HALFEDGEDS_DECORATOR_H //
01112 // EOF //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines