BWAPI
|
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 //