BWAPI
|
00001 // Copyright (c) 1997 ETH Zurich (Switzerland). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00005 // the terms of the Q Public License version 1.0. 00006 // See the file LICENSE.QPL distributed with CGAL. 00007 // 00008 // Licensees holding a valid commercial license may use this file in 00009 // accordance with the commercial license agreement provided with the software. 00010 // 00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00013 // 00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Polyhedron/include/CGAL/Polyhedron_incremental_builder_3.h $ 00015 // $Id: Polyhedron_incremental_builder_3.h 43752 2008-06-24 19:00:46Z afabri $ 00016 // 00017 // 00018 // Author(s) : Lutz Kettner <kettner@mpi-sb.mpg.de>) 00019 00020 #ifndef CGAL_POLYHEDRON_INCREMENTAL_BUILDER_3_H 00021 #define CGAL_POLYHEDRON_INCREMENTAL_BUILDER_3_H 1 00022 00023 #include <CGAL/basic.h> 00024 #include <CGAL/Random_access_adaptor.h> 00025 #include <CGAL/HalfedgeDS_decorator.h> 00026 #include <CGAL/Unique_hash_map.h> 00027 #include <CGAL/IO/Verbose_ostream.h> 00028 #include <vector> 00029 #include <cstddef> 00030 00031 CGAL_BEGIN_NAMESPACE 00032 00033 template < class HalfedgeDS_> 00034 class Polyhedron_incremental_builder_3 { 00035 public: 00036 typedef HalfedgeDS_ HDS; // internal 00037 typedef HalfedgeDS_ HalfedgeDS; 00038 typedef typename HDS::Vertex Vertex; 00039 typedef typename HDS::Halfedge Halfedge; 00040 typedef typename HDS::Face Face; 00041 typedef typename HDS::Vertex_handle Vertex_handle; 00042 typedef typename HDS::Halfedge_handle Halfedge_handle; 00043 typedef typename HDS::Face_handle Face_handle; 00044 typedef typename HDS::Face_handle Facet_handle; 00045 typedef typename Vertex::Base VBase; 00046 typedef typename Halfedge::Base HBase; 00047 typedef typename Vertex::Point Point_3; 00048 typedef typename HDS::size_type size_type; 00049 00050 protected: 00051 typedef typename HDS::Supports_vertex_halfedge Supports_vertex_halfedge; 00052 typedef typename HDS::Supports_removal Supports_removal; 00053 typedef typename HDS::Vertex_iterator Vertex_iterator; 00054 typedef typename HDS::Halfedge_iterator Halfedge_iterator; 00055 typedef Random_access_adaptor<Vertex_iterator> Random_access_index; 00056 00057 bool m_error; 00058 bool m_verbose; 00059 HDS& hds; 00060 size_type rollback_v; 00061 size_type rollback_f; 00062 size_type rollback_h; 00063 size_type new_vertices; 00064 size_type new_faces; 00065 size_type new_halfedges; 00066 Face_handle current_face; 00067 Random_access_index index_to_vertex_map; 00068 std::vector< Halfedge_handle> vertex_to_edge_map; 00069 00070 Halfedge_handle g1; // first halfedge, 0 denotes none. 00071 Halfedge_handle gprime; 00072 Halfedge_handle h1; // current halfedge 00073 size_type w1; // first vertex. 00074 size_type w2; // second vertex. 00075 size_type v1; // current vertex 00076 bool first_vertex; 00077 bool last_vertex; 00078 00079 CGAL_assertion_code( int check_protocoll;) // use to check protocoll. 00080 // states for checking: 0 = created, 1 = constructing, 2 = make face. 00081 00082 // Implement the vertex_to_edge_map either with an array or 00083 // the halfedge pointer in the vertices (if supported). 00084 // ---------------------------------------------------- 00085 void initialize_vertex_to_edge_map( size_type n, bool mode, Tag_true) { 00086 vertex_to_edge_map.clear(); 00087 vertex_to_edge_map.resize(n); 00088 if ( mode) { 00089 // go through all halfedges and keep a halfedge for each 00090 // vertex found in a hashmap. 00091 size_type i = 0; 00092 for ( Vertex_iterator vi = hds.vertices_begin(); 00093 vi != hds.vertices_end(); 00094 ++vi) { 00095 set_vertex_to_edge_map( i, vi->halfedge()); 00096 ++i; 00097 } 00098 } 00099 } 00100 void initialize_vertex_to_edge_map( size_type n, bool mode, Tag_false){ 00101 vertex_to_edge_map.clear(); 00102 vertex_to_edge_map.resize(n); 00103 if ( mode) { 00104 // go through all halfedges and keep a halfedge for each 00105 // vertex found in a hashmap. 00106 typedef Unique_hash_map< Vertex_iterator, Halfedge_handle> V_map; 00107 Halfedge_handle hh; 00108 V_map v_map( hh, hds.size_of_vertices()); 00109 for ( Halfedge_iterator hi = hds.halfedges_begin(); 00110 hi != hds.halfedges_end(); 00111 ++hi) { 00112 v_map[ hi->vertex()] = hi; 00113 } 00114 size_type i = 0; 00115 for ( Vertex_iterator vi = hds.vertices_begin(); 00116 vi != hds.vertices_end(); 00117 ++vi) { 00118 //set_vertex_to_edge_map( i, v_map[ index_to_vertex_map[i]]); 00119 set_vertex_to_edge_map( i, v_map[ vi]); 00120 ++i; 00121 } 00122 } 00123 } 00124 void initialize_vertex_to_edge_map( size_type n, bool mode) { 00125 initialize_vertex_to_edge_map(n, mode, Supports_vertex_halfedge()); 00126 } 00127 void push_back_vertex_to_edge_map( Halfedge_handle h, Tag_true) { 00128 push_back_vertex_to_edge_map( h, Tag_false()); 00129 } 00130 void push_back_vertex_to_edge_map( Halfedge_handle h, Tag_false) { 00131 vertex_to_edge_map.push_back(h); 00132 } 00133 void push_back_vertex_to_edge_map( Halfedge_handle h) { 00134 push_back_vertex_to_edge_map( h, Supports_vertex_halfedge()); 00135 } 00136 Halfedge_handle get_vertex_to_edge_map( size_type i, Tag_true) { 00137 // Use the halfedge pointer within the vertex. 00138 //CGAL_assertion( index_to_vertex_map[i]->halfedge() == get_vertex_to_edge_map(i, Tag_false())); 00139 return index_to_vertex_map[i]->halfedge(); 00140 } 00141 Halfedge_handle get_vertex_to_edge_map( size_type i, Tag_false) { 00142 // Use the self-managed array vertex_to_edge_map. 00143 return vertex_to_edge_map[i]; 00144 } 00145 Halfedge_handle get_vertex_to_edge_map( size_type i) { 00146 return get_vertex_to_edge_map( i, Supports_vertex_halfedge()); 00147 } 00148 void set_vertex_to_edge_map( size_type i, Halfedge_handle h, Tag_true) { 00149 set_vertex_to_edge_map( i, h, Tag_false()); 00150 // Use the halfedge pointer within the vertex. 00151 index_to_vertex_map[i]->VBase::set_halfedge(h); 00152 } 00153 void set_vertex_to_edge_map( size_type i, Halfedge_handle h, Tag_false) { 00154 // Use the self-managed array vertex_to_edge_map. 00155 CGAL_assertion(i < vertex_to_edge_map.size()); 00156 vertex_to_edge_map[i] = h; 00157 } 00158 void set_vertex_to_edge_map( size_type i, Halfedge_handle h) { 00159 set_vertex_to_edge_map( i, h, Supports_vertex_halfedge()); 00160 } 00161 00162 // An Incremental Builder for Polyhedral Surfaces 00163 // ---------------------------------------------- 00164 // DEFINITION 00165 // 00166 // Polyhedron_incremental_builder_3<HDS> is an auxiliary class that 00167 // supports the incremental construction of polyhedral surfaces. This is 00168 // for example convinient when constructing polyhedral surfaces from 00169 // files. The incremental construction starts with a list of all point 00170 // coordinates and concludes with a list of all facet polygons. Edges are 00171 // not explicitly specified. They are derived from the incidence 00172 // information provided from the facet polygons. These are given as a 00173 // sequence of vertex indices. The correct protocol of method calls to 00174 // build a polyhedral surface can be stated as regular expression: 00175 // 00176 // `begin_surface (add_vertex | (begin_facet add_vertex_to_facet* 00177 // end_facet))* end_surface ' 00178 // 00179 // PARAMETERS 00180 // 00181 // `HDS' is the halfedge data structure used to represent the 00182 // polyhedral surface that is to be constructed. 00183 // 00184 // CREATION 00185 public: 00186 bool error() const { return m_error; } 00187 00188 Polyhedron_incremental_builder_3( HDS& h, bool verbose = false) 00189 // stores a reference to the halfedge data structure `h' in the 00190 // internal state. The previous polyhedral surface in `h' 00191 // remains unchanged. The incremental builder adds the new 00192 // polyhedral surface to the old one. 00193 : m_error( false), m_verbose( verbose), hds(h) { 00194 CGAL_assertion_code(check_protocoll = 0;) 00195 } 00196 00197 ~Polyhedron_incremental_builder_3() { 00198 CGAL_assertion( check_protocoll == 0); 00199 } 00200 00201 // OPERATIONS 00202 enum { RELATIVE_INDEXING = 0, ABSOLUTE_INDEXING = 1}; 00203 00204 00205 void begin_surface( std::size_t v, std::size_t f, std::size_t h = 0, 00206 int mode = RELATIVE_INDEXING); 00207 // starts the construction. v is the number of new 00208 // vertices to expect, f the number of new facets, and h the number of 00209 // new halfedges. If h is unspecified (`== 0') it is estimated using 00210 // Euler equations (plus 5% for the so far unkown holes and genus 00211 // of the object). These values are used to reserve space in the 00212 // polyhedron representation `HDS'. If the representation 00213 // supports insertion these values do not restrict the class of 00214 // readable polyhedrons. If the representation does not support 00215 // insertion the object must fit in the reserved sizes. 00216 // If `mode' is set to ABSOLUTE_INDEXING the incremental builder 00217 // uses absolute indexing and the vertices of the old polyhedral 00218 // surface can be used in new facets. Otherwise relative indexing is 00219 // used starting with new indices for the new construction. 00220 00221 00222 Vertex_handle add_vertex( const Point_3& p) { 00223 // adds p to the vertex list. 00224 CGAL_assertion( check_protocoll == 1); 00225 if ( hds.size_of_vertices() >= hds.capacity_of_vertices()) { 00226 Verbose_ostream verr( m_verbose); 00227 verr << " " << std::endl; 00228 verr << "CGAL::Polyhedron_incremental_builder_3<HDS>::" 00229 << std::endl; 00230 verr << "add_vertex(): capacity error: more than " << new_vertices 00231 << " vertices added." << std::endl; 00232 m_error = true; 00233 return Vertex_handle(); 00234 } 00235 HalfedgeDS_decorator<HDS> decorator(hds); 00236 Vertex_handle v = decorator.vertices_push_back( Vertex(p)); 00237 index_to_vertex_map.push_back( v); 00238 decorator.set_vertex_halfedge( v, Halfedge_handle()); 00239 push_back_vertex_to_edge_map( Halfedge_handle()); 00240 ++new_vertices; 00241 return v; 00242 } 00243 00244 // returns handle for the vertex of index i 00245 Vertex_handle vertex( std::size_t i) { 00246 if ( i < new_vertices) 00247 return index_to_vertex_map[i]; 00248 return Vertex_handle(); 00249 } 00250 00251 Facet_handle begin_facet() { 00252 // starts a facet. 00253 if ( m_error) 00254 return Facet_handle(); 00255 CGAL_assertion( check_protocoll == 1); 00256 CGAL_assertion_code( check_protocoll = 2;) 00257 if ( hds.size_of_faces() >= hds.capacity_of_faces()) { 00258 Verbose_ostream verr( m_verbose); 00259 verr << " " << std::endl; 00260 verr << "CGAL::Polyhedron_incremental_builder_3<HDS>::" 00261 << std::endl; 00262 verr << "begin_facet(): capacity error: more than " << new_vertices 00263 << " facets added." << std::endl; 00264 m_error = true; 00265 return Facet_handle(); 00266 } 00267 // initialize all status variables. 00268 first_vertex = true; // denotes 'no vertex yet' 00269 g1 = Halfedge_handle(); // denotes 'no halfedge yet' 00270 last_vertex = false; 00271 00272 HalfedgeDS_decorator<HDS> decorator(hds); 00273 current_face = decorator.faces_push_back( Face()); 00274 return current_face; 00275 } 00276 00277 void add_vertex_to_facet( std::size_t i); 00278 // adds a vertex with index i to the current facet. The first 00279 // point added with `add_vertex()' has the index 0. 00280 00281 Halfedge_handle end_facet() { 00282 // ends a facet. 00283 if ( m_error) 00284 return Halfedge_handle(); 00285 CGAL_assertion( check_protocoll == 2); 00286 CGAL_assertion( ! first_vertex); 00287 // cleanup all static status variables 00288 add_vertex_to_facet( w1); 00289 if ( m_error) 00290 return Halfedge_handle(); 00291 last_vertex = true; 00292 add_vertex_to_facet( w2); 00293 if ( m_error) 00294 return Halfedge_handle(); 00295 CGAL_assertion( check_protocoll == 2); 00296 CGAL_assertion_code( check_protocoll = 1;) 00297 HalfedgeDS_items_decorator<HDS> decorator; 00298 Halfedge_handle h = get_vertex_to_edge_map(w1); 00299 decorator.set_face_halfedge( current_face, h); 00300 ++new_faces; 00301 return h; 00302 } 00303 00304 template <class InputIterator> 00305 Halfedge_handle add_facet( InputIterator first, InputIterator beyond) { 00306 // synonym for begin_facet(), a call to add_vertex_to_facet() for each iterator 00307 // value type, and end_facet(). 00308 begin_facet(); 00309 for ( ; ! m_error && first != beyond; ++first) 00310 add_vertex_to_facet( *first); 00311 if ( m_error) 00312 return Halfedge_handle(); 00313 return end_facet(); 00314 } 00315 00316 template <class InputIterator> 00317 bool test_facet( InputIterator first, InputIterator beyond) { 00318 // tests if the facet described by the vertex indices in the 00319 // range [first,beyond) can be inserted without creating a 00320 // a non-manifold (and therefore invalid) situation. 00321 // First, create a copy of the indices and close it cyclically 00322 std::vector< std::size_t> indices( first, beyond); 00323 if ( indices.size() < 3) 00324 return false; 00325 indices.push_back( indices[0]); 00326 return test_facet_indices( indices); 00327 } 00328 00329 bool test_facet_indices( std::vector< std::size_t> indices); 00330 00331 void end_surface(); 00332 // ends the construction. 00333 00334 bool check_unconnected_vertices(); 00335 // returns `true' if unconnected vertices are detected. If `verb' 00336 // is set to `true' debug information about the unconnected 00337 // vertices is printed. 00338 00339 bool remove_unconnected_vertices( Tag_true); 00340 bool remove_unconnected_vertices( Tag_false) { 00341 return ! check_unconnected_vertices(); 00342 } 00343 bool remove_unconnected_vertices() { 00344 // returns `true' if all unconnected vertices could be removed 00345 // succesfully. 00346 return remove_unconnected_vertices( Supports_removal()); 00347 } 00348 00349 void rollback(); 00350 00351 protected: 00352 Halfedge_handle lookup_hole( std::size_t w) { 00353 CGAL_assertion( w < new_vertices); 00354 return lookup_hole( get_vertex_to_edge_map( w)); 00355 } 00356 00357 size_type find_vertex( Vertex_handle v) { 00358 // Returns 0 if v == NULL. 00359 if ( v == Vertex_handle() ) 00360 return 0; 00361 size_type n = 0; 00362 typename HDS::Vertex_iterator it = hds.vertices_begin(); 00363 while ( it != v) { 00364 CGAL_assertion( it != hds.vertices_end()); 00365 ++n; 00366 ++it; 00367 } 00368 n = n - rollback_v; 00369 return n; 00370 } 00371 00372 size_type find_facet( Face_handle f) { 00373 // Returns 0 if f == NULL. 00374 if ( f == Face_handle()) 00375 return 0; 00376 size_type n = 0; 00377 typename HDS::Face_iterator it = hds.faces_begin(); 00378 while ( it != f) { 00379 CGAL_assertion( it != hds.faces_end()); 00380 ++n; 00381 ++it; 00382 } 00383 n = n - rollback_f; 00384 return n; 00385 } 00386 00387 Halfedge_handle lookup_halfedge( size_type w, size_type v) { 00388 // Pre: 0 <= w,v < new_vertices 00389 // Case a: It exists an halfedge g from w to v: 00390 // g must be a border halfedge and the facet of g->opposite() 00391 // must be set and different from the current facet. 00392 // Set the facet of g to the current facet. Return the 00393 // halfedge pointing to g. 00394 // Case b: It exists no halfedge from w to v: 00395 // Create a new pair of halfedges g and g->opposite(). 00396 // Set the facet of g to the current facet and g->opposite() 00397 // to a border halfedge. Assign the vertex references. 00398 // Set g->opposite()->next() to g. Return g->opposite(). 00399 typedef typename HDS::Supports_halfedge_vertex 00400 Supports_halfedge_vertex; 00401 Assert_compile_time_tag( Supports_halfedge_vertex(), Tag_true()); 00402 CGAL_assertion( w < new_vertices); 00403 CGAL_assertion( v < new_vertices); 00404 CGAL_assertion( ! last_vertex); 00405 HalfedgeDS_items_decorator<HDS> decorator; 00406 Halfedge_handle e = get_vertex_to_edge_map( w); 00407 if ( e != Halfedge_handle()) { 00408 CGAL_assertion( e->vertex() == index_to_vertex_map[w]); 00409 // check that the facet has no self intersections 00410 if ( current_face != Face_handle() 00411 && current_face == decorator.get_face(e)) { 00412 Verbose_ostream verr( m_verbose); 00413 verr << " " << std::endl; 00414 verr << "CGAL::Polyhedron_incremental_builder_3<HDS>::" 00415 << std::endl; 00416 verr << "lookup_halfedge(): input error: facet " 00417 << new_faces << " has a self intersection at vertex " 00418 << w << "." << std::endl; 00419 m_error = true; 00420 return Halfedge_handle(); 00421 } 00422 Halfedge_handle start_edge( e); 00423 do { 00424 if ( e->next()->vertex() == index_to_vertex_map[v]) { 00425 if ( ! e->next()->is_border()) { 00426 Verbose_ostream verr( m_verbose); 00427 verr << " " << std::endl; 00428 verr << "CGAL::Polyhedron_incremental_builder_3" 00429 "<HDS>::" << std::endl; 00430 verr << "lookup_halfedge(): input error: facet " 00431 << new_faces << " shares a halfedge from " 00432 "vertex " << w << " to vertex " << v 00433 << " with"; 00434 if ( m_verbose && current_face != Face_handle()) 00435 verr << " facet " 00436 << find_facet( decorator.get_face(e->next())) 00437 << '.' << std::endl; 00438 else 00439 verr << " another facet." << std::endl; 00440 m_error = true; 00441 return Halfedge_handle(); 00442 } 00443 CGAL_assertion( ! e->next()->opposite()->is_border()); 00444 if ( current_face != Face_handle() && current_face == 00445 decorator.get_face( e->next()->opposite())) { 00446 Verbose_ostream verr( m_verbose); 00447 verr << " " << std::endl; 00448 verr << "CGAL::Polyhedron_incremental_builder_3" 00449 "<HDS>::" << std::endl; 00450 verr << "lookup_halfedge(): input error: facet " 00451 << new_faces << " has a self intersection " 00452 "at the halfedge from vertex " << w 00453 << " to vertex " << v << "." << std::endl; 00454 m_error = true; 00455 return Halfedge_handle(); 00456 } 00457 decorator.set_face( e->next(), current_face); 00458 return e; 00459 } 00460 e = e->next()->opposite(); 00461 } while ( e != start_edge); 00462 } 00463 // create a new halfedge 00464 if ( hds.size_of_halfedges() >= hds.capacity_of_halfedges()) { 00465 Verbose_ostream verr( m_verbose); 00466 verr << " " << std::endl; 00467 verr << "CGAL::Polyhedron_incremental_builder_3<HDS>::" 00468 << std::endl; 00469 verr << "lookup_halfedge(): capacity error: more than " 00470 << new_halfedges << " halfedges added while creating facet" 00471 << new_faces << '.' << std::endl; 00472 m_error = true; 00473 return Halfedge_handle(); 00474 } 00475 e = hds.edges_push_back( Halfedge(), Halfedge()); 00476 new_halfedges++; 00477 new_halfedges++; 00478 decorator.set_face( e, current_face); 00479 e->HBase::set_vertex( index_to_vertex_map[v]); 00480 e->HBase::set_next( Halfedge_handle()); 00481 decorator.set_prev( e, e->opposite()); 00482 e = e->opposite(); 00483 e->HBase::set_vertex( index_to_vertex_map[w]); 00484 e->HBase::set_next( e->opposite()); 00485 return e; 00486 } 00487 00488 Halfedge_handle lookup_hole( Halfedge_handle e) { 00489 // Halfedge e points to a vertex w. Walk around w to find a hole 00490 // in the facet structure. Report an error if none exist. Return 00491 // the halfedge at this hole that points to the vertex w. 00492 CGAL_assertion( e != Halfedge_handle()); 00493 HalfedgeDS_items_decorator<HDS> decorator; 00494 Halfedge_handle start_edge( e); 00495 do { 00496 if ( e->next()->is_border()) { 00497 return e; 00498 } 00499 e = e->next()->opposite(); 00500 } while ( e != start_edge); 00501 00502 Verbose_ostream verr( m_verbose); 00503 verr << " " << std::endl; 00504 verr << "CGAL::Polyhedron_incremental_builder_3<HDS>::" << std::endl; 00505 verr << "lookup_hole(): input error: at vertex " 00506 << find_vertex( e->vertex()) 00507 << " a closed surface already exists and facet " 00508 << new_faces << " is nonetheless adjacent." << std::endl; 00509 if ( m_verbose && current_face != Face_handle()) { 00510 verr << " The closed cycle of facets is:"; 00511 do { 00512 if ( ! e->is_border()) 00513 verr << " " << find_facet( decorator.get_face(e)); 00514 e = e->next()->opposite(); 00515 } while ( e != start_edge); 00516 verr << '.' << std::endl; 00517 } 00518 m_error = true; 00519 return Halfedge_handle(); 00520 } 00521 }; 00522 00523 template < class HDS> 00524 void 00525 Polyhedron_incremental_builder_3<HDS>:: 00526 rollback() { 00527 CGAL_assertion( rollback_v <= hds.size_of_vertices()); 00528 CGAL_assertion( rollback_h <= hds.size_of_halfedges()); 00529 CGAL_assertion( rollback_f <= hds.size_of_faces()); 00530 if ( rollback_v == 0 && rollback_h == 0 && rollback_f == 0) { 00531 hds.clear(); 00532 } else { 00533 while ( rollback_v != hds.size_of_vertices()) 00534 hds.vertices_pop_back(); 00535 CGAL_assertion((( hds.size_of_halfedges() - rollback_h) & 1) == 0); 00536 while ( rollback_h != hds.size_of_halfedges()) 00537 hds.edges_pop_back(); 00538 while ( rollback_f != hds.size_of_faces()) 00539 hds.faces_pop_back(); 00540 } 00541 m_error = false; 00542 CGAL_assertion_code( check_protocoll = 0;) 00543 } 00544 00545 template < class HDS> CGAL_MEDIUM_INLINE 00546 void 00547 Polyhedron_incremental_builder_3<HDS>:: 00548 begin_surface( std::size_t v, std::size_t f, std::size_t h, int mode) { 00549 CGAL_assertion( check_protocoll == 0); 00550 CGAL_assertion_code( check_protocoll = 1;) 00551 CGAL_assertion( ! m_error); 00552 if ( mode == RELATIVE_INDEXING) { 00553 new_vertices = 0; 00554 new_faces = 0; 00555 new_halfedges = 0; 00556 rollback_v = hds.size_of_vertices(); 00557 rollback_f = hds.size_of_faces(); 00558 rollback_h = hds.size_of_halfedges(); 00559 } else { 00560 new_vertices = hds.size_of_vertices(); 00561 new_faces = hds.size_of_faces(); 00562 new_halfedges = hds.size_of_halfedges(); 00563 rollback_v = 0; 00564 rollback_f = 0; 00565 rollback_h = 0; 00566 } 00567 if ( h == 0) { 00568 // Use the Eulerian equation for connected planar graphs. We do 00569 // not know the number of facets that are holes and we do not 00570 // know the genus of the surface. So we add 12 and a factor of 00571 // 5 percent. 00572 h = int((v + f - 2 + 12) * 2.1); 00573 } 00574 hds.reserve( hds.size_of_vertices() + v, 00575 hds.size_of_halfedges() + h, 00576 hds.size_of_faces() + f); 00577 if ( mode == RELATIVE_INDEXING) { 00578 index_to_vertex_map = Random_access_index( hds.vertices_end()); 00579 index_to_vertex_map.reserve(v); 00580 initialize_vertex_to_edge_map( v, false); 00581 } else { 00582 index_to_vertex_map = Random_access_index( hds.vertices_begin(), 00583 hds.vertices_end()); 00584 index_to_vertex_map.reserve( hds.size_of_vertices() + v); 00585 initialize_vertex_to_edge_map( hds.size_of_vertices() + v, true); 00586 } 00587 } 00588 00589 template < class HDS> 00590 void 00591 Polyhedron_incremental_builder_3<HDS>:: 00592 add_vertex_to_facet( std::size_t v2) { 00593 if ( m_error) 00594 return; 00595 CGAL_assertion( check_protocoll == 2); 00596 if ( v2 >= new_vertices) { 00597 Verbose_ostream verr( m_verbose); 00598 verr << " " << std::endl; 00599 verr << "CGAL::Polyhedron_incremental_builder_3<HDS>::" 00600 << std::endl; 00601 verr << "add_vertex_to_facet(): vertex index " << v2 00602 << " is out-of-range [0," << new_vertices-1 << "]." 00603 << std::endl; 00604 m_error = true; 00605 return; 00606 } 00607 HalfedgeDS_items_decorator<HDS> decorator; 00608 00609 if ( first_vertex) { 00610 CGAL_assertion( ! last_vertex); 00611 w1 = v2; 00612 first_vertex = false; 00613 return; 00614 } 00615 if ( g1 == Halfedge_handle()) { 00616 CGAL_assertion( ! last_vertex); 00617 gprime = lookup_halfedge( w1, v2); 00618 if ( m_error) 00619 return; 00620 h1 = g1 = gprime->next(); 00621 v1 = w2 = v2; 00622 return; 00623 } 00624 // g1, h1, v1, w1, w2 are set. Insert halfedge. 00625 // Lookup v1-->v2 00626 Halfedge_handle hprime; 00627 if ( last_vertex) 00628 hprime = gprime; 00629 else { 00630 hprime = lookup_halfedge( v1, v2); 00631 if ( m_error) 00632 return; 00633 } 00634 Halfedge_handle h2 = hprime->next(); 00635 CGAL_assertion( ! last_vertex || h2 == g1); 00636 Halfedge_handle prev = h1->next(); 00637 h1->HBase::set_next( h2); 00638 decorator.set_prev( h2, h1); 00639 00640 if ( get_vertex_to_edge_map( v1) == Halfedge_handle()) { // case 1: 00641 h2->opposite()->HBase::set_next( h1->opposite()); 00642 decorator.set_prev( h1->opposite(), h2->opposite()); 00643 } else { // case 2: 00644 bool b1 = h1->opposite()->is_border(); 00645 bool b2 = h2->opposite()->is_border(); 00646 if ( b1 && b2) { 00647 Halfedge_handle hole = lookup_hole( v1); 00648 if ( m_error) 00649 return; 00650 CGAL_assertion( hole != Halfedge_handle()); 00651 h2->opposite()->HBase::set_next( hole->next()); 00652 decorator.set_prev( hole->next(), h2->opposite()); 00653 hole->HBase::set_next( h1->opposite()); 00654 decorator.set_prev( h1->opposite(), hole); 00655 } else if ( b2) { // case 2.b: 00656 CGAL_assertion( prev->is_border()); 00657 h2->opposite()->HBase::set_next( prev); 00658 decorator.set_prev( prev, h2->opposite()); 00659 } else if ( b1) { // case 2.c: 00660 CGAL_assertion( hprime->is_border()); 00661 hprime->HBase::set_next( h1->opposite()); 00662 decorator.set_prev( h1->opposite(), hprime); 00663 } else if ( h2->opposite()->next() == h1->opposite()) {// case 2.d: 00664 // f1 == f2 00665 CGAL_assertion( decorator.get_face( h1->opposite()) == 00666 decorator.get_face( h2->opposite())); 00667 } else { // case 2.e: 00668 if ( prev == h2) { // case _i: 00669 // nothing to be done, hole is closed. 00670 } else { // case _ii: 00671 CGAL_assertion( prev->is_border()); 00672 CGAL_assertion( hprime->is_border()); 00673 hprime->HBase::set_next( prev); 00674 decorator.set_prev( prev, hprime); 00675 // Check whether the halfedges around v1 are connected. 00676 // It is sufficient to check it for h1 to prev. 00677 // Assert loop termination: 00678 CGAL_assertion_code( std::size_t k = 0;) 00679 // Look for a hole in the facet complex starting at h1. 00680 Halfedge_handle hole; 00681 Halfedge_handle e = h1; 00682 do { 00683 if ( e->is_border()) 00684 hole = e; 00685 e = e->next()->opposite(); 00686 CGAL_assertion( k++ < hds.size_of_halfedges()); 00687 } while ( e->next() != prev && e != h1); 00688 if ( e == h1) { 00689 // disconnected facet complexes 00690 if ( hole != Halfedge_handle()) { 00691 // The complex can be connected with 00692 // the hole at hprime. 00693 hprime->HBase::set_next( hole->next()); 00694 decorator.set_prev( hole->next(), hprime); 00695 hole->HBase::set_next( prev); 00696 decorator.set_prev( prev, hole); 00697 } else { 00698 Verbose_ostream verr( m_verbose); 00699 verr << " " << std::endl; 00700 verr << "CGAL::Polyhedron_incremental_builder_3<" 00701 "HDS>::" << std::endl; 00702 verr << "add_vertex_to_facet(): input error: " 00703 "disconnected facet complexes at vertex " 00704 << v1 << ":" << std::endl; 00705 00706 if ( m_verbose && current_face != Face_handle()) { 00707 verr << " involved facets are:"; 00708 do { 00709 if ( ! e->is_border()) 00710 verr << " " << find_facet( 00711 decorator.get_face(e)); 00712 e = e->next()->opposite(); 00713 } while ( e != h1); 00714 verr << " (closed cycle) and"; 00715 e = hprime; 00716 do { 00717 if ( ! e->is_border()) 00718 verr << " " << find_facet( 00719 decorator.get_face(e)); 00720 } while ( e != hprime); 00721 verr << "." << std::endl; 00722 } 00723 m_error = true; 00724 return; 00725 } 00726 } 00727 } 00728 } 00729 } 00730 if ( h1->vertex() == index_to_vertex_map[v1]) 00731 set_vertex_to_edge_map( v1, h1); 00732 CGAL_assertion( h1->vertex() == index_to_vertex_map[v1]); 00733 h1 = h2; 00734 v1 = v2; 00735 } 00736 00737 template < class HDS> 00738 bool 00739 Polyhedron_incremental_builder_3<HDS>:: 00740 test_facet_indices( std::vector< std::size_t> indices) { 00741 typedef typename HDS::Supports_halfedge_vertex Supports_halfedge_vertex; 00742 Assert_compile_time_tag( Supports_halfedge_vertex(), Tag_true()); 00743 // tests if the facet described by the vertex indices can be inserted 00744 // without creating a a non-manifold (and therefore invalid) situation. 00745 // indices are cyclically closed once. 00746 std::size_t n = indices.size() - 1; 00747 // Test if a vertex is not twice in the indices 00748 for ( std::size_t i = 0; i < n; ++i) { 00749 CGAL_precondition( indices[i] < new_vertices); 00750 // check if vertex indices[i] is already in the sequence [0..i-1] 00751 for ( std::size_t k = 0; k+1 < i; ++k) { 00752 if ( indices[k] == indices[i]) 00753 return false; 00754 } 00755 } 00756 // Test non-manifold edges 00757 for ( std::size_t i = 0; i < n; ++i) { 00758 // edge goes from vertex indices[i] to indices[i+1] 00759 // we know already that the edge is only once in the sequence 00760 // (otherwise the end-vertices would be twice in the sequence too) 00761 // check if edge is already in the HDS and is not border edge 00762 Halfedge_handle v = get_vertex_to_edge_map(indices[i]); 00763 Vertex_handle w = index_to_vertex_map[indices[i+1]]; 00764 if ( v != Halfedge_handle() 00765 && get_vertex_to_edge_map(indices[i+1]) != Halfedge_handle()) { 00766 // cycle through halfedge-loop and find edge to indices[i+1] 00767 Halfedge_handle vstart = v; 00768 do { 00769 v = v->next()->opposite(); 00770 } while ( v->next()->vertex() != w && v != vstart); 00771 if ( v->next()->vertex() == w && ! v->next()->is_border()) 00772 return false; 00773 } 00774 } 00775 // test non-manifold vertices 00776 for ( std::size_t i = 0; i < n; ++i) { 00777 // since we don't allow duplicates in indices[..] and we 00778 // tested for non-manifold edges already, we just need to check 00779 // if the vertex indices[i] is not a closed manifold yet. 00780 Halfedge_handle v = get_vertex_to_edge_map(indices[i]); 00781 if ( v != Halfedge_handle()) { 00782 Halfedge_handle vstart = v; 00783 do { 00784 v = v->next()->opposite(); 00785 } while ( ! v->is_border() && v != vstart); 00786 if ( ! v->is_border()) 00787 return false; 00788 } 00789 } 00790 return true; 00791 } 00792 00793 00794 template < class HDS> CGAL_MEDIUM_INLINE 00795 void 00796 Polyhedron_incremental_builder_3<HDS>:: 00797 end_surface() { 00798 if ( m_error) 00799 return; 00800 CGAL_assertion( check_protocoll == 1); 00801 CGAL_assertion_code( check_protocoll = 0;) 00802 } 00803 00804 template < class HDS> 00805 bool 00806 Polyhedron_incremental_builder_3<HDS>:: 00807 check_unconnected_vertices() { 00808 if ( m_error) 00809 return false; 00810 bool unconnected = false; 00811 Verbose_ostream verr( m_verbose); 00812 for ( std::size_t i = 0; i < new_vertices; i++) { 00813 if ( get_vertex_to_edge_map( i) == Halfedge_handle()) { 00814 verr << "CGAL::Polyhedron_incremental_builder_3<HDS>::\n" 00815 << "check_unconnected_vertices( verb = true): " 00816 << "vertex " << i << " is unconnected." << std::endl; 00817 unconnected = true; 00818 } 00819 } 00820 return unconnected; 00821 } 00822 00823 template < class HDS> 00824 bool 00825 Polyhedron_incremental_builder_3<HDS>:: 00826 remove_unconnected_vertices( Tag_true) { 00827 if ( m_error) 00828 return true; 00829 for( std::size_t i = 0; i < new_vertices; i++) { 00830 if( get_vertex_to_edge_map( i) == Halfedge_handle()) { 00831 hds.vertices_erase( index_to_vertex_map[i]); 00832 } 00833 } 00834 return true; 00835 } 00836 00837 CGAL_END_NAMESPACE 00838 00839 #endif // CGAL_POLYHEDRON_INCREMENTAL_BUILDER_3_H // 00840 // EOF //