BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Polyhedron_incremental_builder_3.h
Go to the documentation of this file.
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 //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines