// Copyright (c) 2010-2011 CNRS and LIRIS' Establishments (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; version 2.1 of the License. // See the file LICENSE.LGPL distributed with CGAL. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // Author(s) : Guillaume Damiand // #ifndef CGAL_COMBINATORIAL_MAP_H #define CGAL_COMBINATORIAL_MAP_H 1 #include #include #include #include #include #include #include #include #include // suppress bogus warning when compiling with gcc 4.3 or 4.4 #if (__GNUC__ == 4 && (__GNUC_MINOR__ == 3 || __GNUC_MINOR__ == 4)) #pragma GCC diagnostic ignored "-Warray-bounds" #endif namespace CGAL { /** @file Combinatorial_map.h * Definition of generic dD Combinatorial map. */ /** Generic definition of combinatorial map in dD. * The Combinatorial_map class describes an dD combinatorial map. It allows * mainly to create darts, to use marks onto these darts, to get and set * the beta links, and to manage enabled attributes. */ template < unsigned int d_, class Refs, class Items_=Combinatorial_map_min_items, class Alloc_=CGAL_ALLOCATOR(int) > class Combinatorial_map_base { template friend struct internal::sew_functor; template friend struct internal::unsew_functor; template friend struct Remove_cell_functor; template friend typename Map::Dart_handle insert_cell_0_in_cell_1(Map& amap, typename Map::Dart_handle adart); template friend typename CMap::Dart_handle insert_cell_1_in_cell_2(CMap& amap, typename CMap::Dart_handle adart1); template friend typename CMap::Dart_handle insert_cell_1_in_cell_2(CMap& amap, typename CMap::Dart_handle adart1, typename CMap::Dart_handle adart2); template friend typename Map::Dart_handle insert_cell_2_in_cell_3(Map& amap, InputIterator afirst, InputIterator alast); template < class Map > friend typename Map::Dart_handle insert_cell_0_in_cell_2(Map& amap, typename Map::Dart_handle adart); template friend struct internal::Degroup_one_attribute_of_dart_functor; template friend struct internal::Degroup_one_attribute_functor; template friend struct internal::Test_is_valid_attribute_functor; template friend struct internal::Group_attribute_functor_of_dart_run; template friend struct internal::Group_attribute_functor_run; template friend struct internal::Group_one_attribute_functor; template friend struct internal::Degroup_attribute_functor_run; template friend struct internal::Update_dart_of_attribute_functor; template friend struct internal::Decrease_attribute_functor; public: /// Types definition typedef Combinatorial_map_base Self; typedef Items_ Items; typedef Alloc_ Alloc; typedef typename Items::template Dart_wrapper Dart_wrapper; typedef typename Dart_wrapper::Dart Dart; typedef typename Alloc::template rebind::other Dart_allocator; typedef Compact_container Dart_container; typedef typename Dart_container::iterator Dart_handle; typedef typename Dart_container::const_iterator Dart_const_handle; typedef typename Dart_container::size_type size_type; /// The dimension of the combinatorial map. static const unsigned int dimension = d_; /// Number of marks static const size_type NB_MARKS = 32; typedef internal::Combinatorial_map_helper Helper; /// Typedef for Dart_range, a range through all the darts of the map. typedef Dart_container Dart_range; typedef const Dart_container Dart_const_range; typedef typename Dart_wrapper::Attributes Attributes; /// Typedef for attributes template struct Attribute_type: public Helper::template Attribute_type {}; template struct Attribute_handle: public Helper::template Attribute_handle {}; template struct Attribute_const_handle: public Helper::template Attribute_const_handle {}; template struct Attribute_range: public Helper::template Attribute_range {}; template struct Attribute_const_range: public Helper::template Attribute_const_range {}; public: /** Default Combinatorial_map constructor. * The map is empty. */ Combinatorial_map_base() { CGAL_static_assertion_msg( Dart::dimension==dimension, "Dimension of dart different from dimension of map"); CGAL_static_assertion_msg( Helper::nb_attribs<=dimension+1, "Too many attributes in the tuple Attributes_enabled"); this->mnb_used_marks = 0; this->mmask_marks.reset(); this->mused_marks.reset(); for (size_type i = 0; i < NB_MARKS; ++i) { this->mfree_marks_stack[i] = (int)i; this->mindex_marks[i] = i; this->mnb_marked_darts[i] = 0; } // We must do this ony once, but problem because null_dart_handle // is static ! if ( mnull_dart_container.empty() ) { null_dart_handle = mnull_dart_container.emplace( std::bitset() ); for (unsigned int i=0; i<=dimension; ++i) { null_dart_handle->unlink_beta(i); } } CGAL_assertion(number_of_darts()==0); } /** Clear the combinatorial map. Remove all darts and all attributes. * Note that reserved marks are not free. */ void clear() { mdarts.clear(); for (unsigned int i = 0; i < NB_MARKS; ++i) this->mnb_marked_darts[i] = 0; internal::Clear_all::run(mattribute_containers); } /** Test if the map is empty. * @return true iff the map is empty. */ bool is_empty() const { return mdarts.empty(); } /** Create a new dart and add it to the map. * The marks of the darts are initialised with mmask_marks, i.e. the dart * is unmarked for all the marks. * @return a Dart_handle on the new dart. */ Dart_handle create_dart() { return mdarts.emplace(mmask_marks); } /** Erase a dart from the list of darts. * @param adart the dart to erase. */ void erase_dart(Dart_handle adart) { // 1) We update the number of marked darts. for (unsigned int i = 0; i < mnb_used_marks; ++i) { if (is_marked(adart, mused_marks_stack[i])) --mnb_marked_darts[mused_marks_stack[i]]; } // 2) We update the attribute_ref_counting. Helper::template Foreach_enabled_attributes >::run(this,adart); // 3) We erase the dart. mdarts.erase(adart); } /// @return a Dart_range (range through all the darts of the map). Dart_range& darts() { return mdarts;} Dart_const_range& darts() const { return mdarts; } /** Get the first dart of this map. * @return the first dart. */ Dart_handle first_dart() { if (darts().begin() == darts().end()) return null_dart_handle; return mdarts.begin(); } Dart_const_handle first_dart() const { if (darts().begin() == darts().end()) return null_dart_handle; return mdarts.begin(); } /// @return the Dart_handle corresponding to the given dart. Dart_handle dart_handle(Dart& adart) { return mdarts.iterator_to(adart); } Dart_const_handle dart_handle(const Dart& adart) const { return mdarts.iterator_to(adart); } /** Count the number of used marks. * @return the number of used marks. */ size_type number_of_used_marks() const { return mnb_used_marks; } /** Test if a given mark is reserved. * @return true iff the mark is reserved (ie in used). */ bool is_reserved(int amark) const { CGAL_assertion(amark>=0 && (size_type)amarkget_mark(amark)!=mmask_marks[(size_type)amark]; } /** Set the mark of a given dart to a state (on or off). * @param adart the dart. * @param amark the given mark. * @param astate the state of the mark (on or off). */ void set_mark_to(Dart_const_handle adart, int amark, bool astate) const { CGAL_assertion( adart != null_dart_handle ); CGAL_assertion( is_reserved(amark) ); if (is_marked(adart, amark) != astate) { if (astate) ++mnb_marked_darts[(size_type)amark]; else --mnb_marked_darts[(size_type)amark]; adart->set_mark(amark, astate ^ mmask_marks[(size_type)amark]); } } /** Mark the given dart. * @param adart the dart. * @param amark the given mark. */ void mark(Dart_const_handle adart, int amark) const { CGAL_assertion( adart != null_dart_handle ); CGAL_assertion( is_reserved(amark) ); if (is_marked(adart, amark)) return; ++mnb_marked_darts[(size_type)amark]; adart->set_mark(amark, !mmask_marks[(size_type)amark]); } /** Unmark the given dart. * @param adart the dart. * @param amark the given mark. */ void unmark(Dart_const_handle adart, int amark) const { CGAL_assertion( adart != null_dart_handle ); CGAL_assertion( is_reserved(amark) ); if (!is_marked(adart, amark)) return; --mnb_marked_darts[(size_type)amark]; adart->set_mark(amark, mmask_marks[(size_type)amark]); } /** Unmark all the darts of the map for a given mark. * If all the darts are marked or unmarked, this operation takes O(1) * operations, otherwise it traverses all the darts of the map. * @param amark the given mark. */ void unmark_all(int amark) const { CGAL_assertion( is_reserved(amark) ); if (is_whole_map_unmarked(amark)) return; if (is_whole_map_marked(amark)) { negate_mark(amark); } else { for (typename Dart_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) unmark(it, amark); } CGAL_assertion(is_whole_map_unmarked(amark)); } /** Free a given mark, previously calling unmark_all_darts. * @param amark the given mark. */ void free_mark(int amark) const { CGAL_assertion( is_reserved(amark) ); unmark_all(amark); mused_marks.set((size_type)amark, false); // 1) We remove amark from the array mused_marks_stack by // replacing it with the last mark in this array. mused_marks_stack[mindex_marks[(size_type)amark]] = mused_marks_stack[--mnb_used_marks]; mindex_marks[mused_marks_stack[mnb_used_marks]] = mindex_marks[(size_type)amark]; // 2) We add amark in the array mfree_marks_stack and update its index. mfree_marks_stack[ mnb_used_marks ] = amark; mindex_marks[(size_type)amark] = mnb_used_marks; } /** Test if this map is without boundary for a given dimension. * @param i the dimension. * @return true iff all the darts are not i-free. * @pre 1<=i<=n */ bool is_without_boundary(unsigned int i) const { CGAL_assertion(1<=i && i<=dimension); for (typename Dart_const_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) if (it->is_free(i)) return false; return true; } /** Test if this map is without boundary for all the dimensions. * @return true iff all the darts are non free. */ bool is_without_boundary() const { for (typename Dart_const_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) for (unsigned int i = 1; i<=dimension; ++i) if (it->is_free(i)) return false; return true; } /** Close the combinatorial map for a given dimension. * @param i the dimension to close * @return the number of new darts. * @pre 2<=i<=n (TODO case i==1) */ unsigned int close(unsigned int i) { CGAL_assertion(2<=i && i<=dimension); unsigned int res = 0; Dart_handle d, d2; for (typename Dart_range::iterator it(darts().begin()); it!=darts().end(); ++it) { if ( it->is_free(i) ) { d = create_dart(); ++res; link_beta(it, d, i); // Special cases for 0 and 1 if ( !it->is_free(1) && !it->beta(1)->is_free(i) ) link_beta<1>(it->beta(1)->beta(i),d); if ( !it->is_free(0) && !it->beta(0)->is_free(i) ) link_beta<0>(it->beta(0)->beta(i),d); // General case for 2...dimension for (unsigned int j=2; j<=dimension; ++j) { if ( j+1!=i && j!=i && j!=i+1 && !it->is_free(j) && !it->beta(j)->is_free(i) ) { link_beta(it->beta(j)->beta(i), d, j); } } d2 = it; while (d2 != null_dart_handle && !d2->is_free(i-1)) { d2 = d2->beta(i-1)->beta(i); } if (d2 != null_dart_handle) { if (i==2) link_beta<1>(d2, d); else link_beta(d2, d, i-1); } } } return res; } /** Test if the map is valid. * @return true iff the map is valid. */ bool is_valid() const { bool valid = true; unsigned int i = 0, j = 0; std::vector marks(dimension+1); for (i=0; i<=dimension; ++i) marks[i] = -1; Helper::template Foreach_enabled_attributes >:: run(this,&marks); for (typename Dart_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) { if ( !valid ) { // We continue the traversal to mark all the darts. for (i=0; i<=dimension; ++i) if (marks[i]!=-1) mark(it,marks[i]); } else { // beta0 must be the inverse of beta1 if ((!it->is_free(0) && it->beta(0)->beta(1)!=it) || (!it->is_free(1) && it->beta(1)->beta(0)!=it )) { std::cerr << "Map not valid: beta(0) " "is not the inverse of beta(1) for " <<&(*it) << std::endl; valid = false; } // Each beta(i>=2) must be an involution for (i = 2; i <= dimension; ++i) if (!it->is_free(i) && it->beta(i)->beta(i)!=it) { std::cerr << "Map not valid: beta(" << i << ") is not an involution for " <<&(*it) << std::endl; valid = false; } // beta1 o betai and beta0 o betai (i>=3) must be involutions if (!it->is_free(0)) { for (i = 3; i <= dimension; ++i) if ((it->is_free(i) != it->beta(0)->is_free(i)) || (!it->is_free(i) && it->beta(0)->beta(i)!=it->beta(i)->beta(1))) { std::cerr << "Map not valid: beta(0) o beta(" << i << ") is not an involution for " <<&(*it) << std::endl; valid = false; } } if (!it->is_free(1)) { for (i = 3; i <= dimension; ++i) if ((it->is_free(i) != it->beta(1)->is_free(i)) || (!it->is_free(i) && it->beta(1)->beta(i)!=it->beta(i)->beta(0))) { std::cerr << "Map not valid: beta(1) o beta(" << i << ") is not an involution for " <<&(*it)<< std::endl; valid = false; } } // beta(i>=2) o beta(j>=i+2) must be an involution for (i = 2; i <= dimension; ++i) { if (!it->is_free(i)) { for (j = i + 2; j <= dimension; ++j) if ((it->is_free(j)!=it->beta(i)->is_free(j)) || (!it->is_free(j) && it->beta(i)->beta(j)!=it->beta(j)->beta(i))) { std::cerr << "Map not valid: beta(" << i << ") o beta(" << j << ") is not an involution for " << &(*it)<< std::endl; valid = false; } } } Helper::template Foreach_enabled_attributes >:: run(this,it,&marks,&valid); } } for (i=0; i<=dimension; ++i) if ( marks[i]!=-1 ) { CGAL_assertion( is_whole_map_marked(marks[i]) ); free_mark(marks[i]); } return valid; } /// @return the number of darts. size_type number_of_darts() const { return mdarts.size(); } /// @return an estimation of the bytes used by the combinatorial map. size_type bytes() const { return mdarts.capacity() * sizeof(Dart) + internal::Count_bytes_all_attributes_functor::run(*this); } /** Write the content of the map: each dart and each beta links. * @param os the ostream. * @return the ostream. */ std::ostream& display_darts(std::ostream & os) const { unsigned int nb = 0; for (typename Dart_range::const_iterator it=darts().begin(); it!=darts().end(); ++it) { os << " dart " << &(*it) << "; beta[i]="; for (unsigned int i=0; i<=dimension; ++i) { os << &(*it->beta(i)) << ",\t"; if (it->is_free(i))os << "\t"; } os << std::endl; ++nb; } os << "Number of darts: " << nb <<"(sizeofdarts=" < std::ostream& display_orbits(std::ostream & aos) const { CGAL_assertion( Ite::is_basic_iterator() ); unsigned int nb = 0; int amark = get_new_mark(); for (typename Dart_range::const_iterator it1(darts().begin()), itend(darts().end()); it1!=itend; ++it1) { if ( !is_marked(it1, amark) ) { ++nb; for ( Ite it2(*this, it1, amark); it2.cont(); ++it2 ) { aos << &(**it2) << " - " << std::flush; mark(*it2, amark); } aos << std::endl; } } CGAL_assertion( is_whole_map_marked(amark) ); free_mark(amark); aos << "Number of orbits: " << nb << std::endl; return aos; } /** Write the content of each i-cell of the map. * @param aos the ostream. * @return the ostream. */ template < unsigned int i > std::ostream& display_cells(std::ostream & aos) const { return display_orbits > (aos); } /** Write the number of darts and cells of the map into a given ostream. * @param os the ostream. * @return the ostream. */ std::ostream& display_characteristics(std::ostream & os) const { std::vector cells(dimension+2); for (unsigned int i=0; i<=dimension+1; ++i) { cells[i]=i; } std::vector res = count_cells(cells); os << "#Darts=" << number_of_darts(); for (unsigned int i=0; i<=dimension; ++i) os<<", #"< but i-attributes are disabled"); return CGAL::cpp0x::get::value> (mattribute_containers).emplace(); } /// Create a new attribute by copy. /// @return a handle on the new attribute. template typename Attribute_handle::type create_attribute(const A&a) { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "create_attribute but i-attributes are disabled"); return CGAL::cpp0x::get::value> (mattribute_containers).emplace(a); } /// Erase an attribute. /// @param h a handle to the attribute to erase. template void erase_attribute(typename Attribute_handle::type h) { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "erase_attribute but i-attributes are disabled"); CGAL::cpp0x::get::value> (mattribute_containers).erase(h); } /// @return the number of attributes. template size_type number_of_attributes() const { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "number_of_attributes but i-attributes are disabled"); return CGAL::cpp0x::get::value> (mattribute_containers).size(); } /// @return a Attributes_range (range through all the /// attributes of the map). template typename Attribute_range::type & attributes() { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "attributes but i-attributes are disabled"); return CGAL::cpp0x::get::value> (mattribute_containers); } template typename Attribute_const_range::type & attributes() const { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "attributes but i-attributes are disabled"); return CGAL::cpp0x::get::value> (mattribute_containers); } /** Double link a dart with beta i to a second dart, when i>=2. * \em adart1 is i-linked to \em adart2 and \em adart2 is i-linked * with \em adart1. Attributes are not updated, thus we can obtain * a non-valid map with darts belonging to a same orbit and having * different attributes. * @param adart1 a first dart. * @param adart2 a second dart. * @param i the dimension of the beta */ void basic_link_beta(Dart_handle adart1, Dart_handle adart2, unsigned int i) { CGAL_assertion( i>=2 && i<=dimension ); CGAL_assertion(adart1 != NULL && adart2 != NULL && adart1!=adart2); CGAL_assertion(adart1 != null_dart_handle && adart2 != null_dart_handle); adart1->basic_link_beta(adart2, i); adart2->basic_link_beta(adart1, i); } /** Double link a dart with betai to a second dart. * \em adart1 is i-linked to \em adart2 and \em adart2 is i^-1-linked * with \em adart1. Attributes are not updated, thus we can obtain * a non-valid map with darts belonging to a same orbit and having * different attributes. * @param adart1 a first dart. * @param adart2 a second dart. */ template void basic_link_beta(Dart_handle adart1, Dart_handle adart2) { internal::basic_link_beta_functor::run(*this,adart1,adart2); } /** Double unlink a dart with beta0. * beta0(\em adart) is 1-unlinked and \em adart is 0-unlinked. * The attributes are not updated, thus we can obtain a non-valid map * with darts belonging to different orbits and having the same * attributes. * @param adart a dart. */ template void unlink_beta(Dart_handle adart) { internal::unlink_beta_functor::run(*this,adart); } /** Double unlink a dart with beta i, for i>=2. * betai(\em adart) is i-unlinked and \em adart is i-unlinked. * The attributes are not updated, thus we can obtain a non-valid map * with darts belonging to different orbits and having the same * attributes. * @param adart a dart. * @param i the dimension of the beta */ void unlink_beta(Dart_handle adart, unsigned int i) { CGAL_assertion(adart!=NULL && adart!=null_dart_handle && !adart->is_free(i)); CGAL_assertion(2<=i && i<=dimension); adart->beta(i)->unlink_beta(i); adart->unlink_beta(i); } /** Double link two darts, and update the NULL attributes. * \em adart1 is i-linked to \em adart2 and \em adart2 is i^-1-linked * with \em adart1. The NULL attributes of \em adart1 are updated to * non NULL attributes associated to \em adart2, and vice-versa. * We can obtain a non-valid map with darts belonging to a same cell * and having different attributes. * @param adart1 a first dart. * @param adart2 a second dart. */ template void link_beta(Dart_handle adart1, Dart_handle adart2) { internal::link_beta_functor::run(*this,adart1,adart2); } /** Double link two darts, and update the NULL attributes. * \em adart1 is i-linked to \em adart2 and \em adart2 is i^-1-linked * with \em adart1. The NULL attributes of \em adart1 are updated to * non NULL attributes associated to \em adart2, and vice-versa. * We can obtain a non-valid map with darts belonging to a same cell * and having different attributes. * @param adart1 a first dart. * @param adart2 a second dart. * @param i the dimension of the beta. * @pre 2<=i<=dimension */ void link_beta(Dart_handle adart1, Dart_handle adart2, unsigned int i) { CGAL_assertion(adart1 != NULL && adart2 != NULL && adart1!=adart2 ); CGAL_assertion(adart1 != null_dart_handle && adart2 != null_dart_handle); CGAL_assertion( 2<=i && i<=dimension ); adart1->basic_link_beta(adart2, i); adart2->basic_link_beta(adart1, i); Helper::template Foreach_enabled_attributes >:: run(this,adart1,adart2,i); } /** Double link a dart with betai to a second dart. * \em adart1 is i-linked to \em adart2 and \em adart2 is i^-1-linked * with \em adart1. The NULL attributes of \em adart1 are updated to * non NULL attributes associated to \em adart2, and vice-versa, only . * if update_attributes==true. * @param adart1 a first dart. * @param adart2 a second dart. * @param update_attributes a boolean to update the enabled attributes */ template void link_beta(Dart_handle adart1, Dart_handle adart2, bool update_attributes) { if ( update_attributes ) link_beta(adart1, adart2); else basic_link_beta(adart1, adart2); } /** Test if it is possible to sew by betai the two given darts * @param adart1 the first dart. * @param adart2 the second dart. * @return true iff \em adart1 can be i-sewn with \em adart2. */ template bool is_sewable(Dart_const_handle adart1, Dart_const_handle adart2) const { return internal::is_sewable_functor::run(*this,adart1,adart2); } /** Topological sew by betai the two given darts plus all the required darts * to satisfy the combinatorial map validity: but do not update attributes * thus the map can be non valid. * @param adart1 the first dart. * @param adart2 the second dart. * @pre is_sewable(adart1, adart2). */ template void topo_sew(Dart_handle adart1, Dart_handle adart2) { return internal::topo_sew_functor::run(*this,adart1,adart2); } /** Sew by betai the two given darts plus all the required darts * to satisfy the combinatorial map validity, and updates enabled * attributes when necessary so that the final map is valid. * @param adart1 the first dart. * @param adart2 the second dart. * @pre is_sewable(adart1, adart2). * @post is_valid() */ template void sew(Dart_handle adart1, Dart_handle adart2) { return internal::sew_functor::run(*this,adart1,adart2); } /** Sew by betai the two given darts plus all the required darts * to satisfy the combinatorial map validity. Enabled attributes * are updated only if update_attributes==true. * @param adart1 the first dart. * @param adart2 the second dart. * @param update_attributes a boolean to update the enabled attributes * @pre is_sewable(adart1, adart2). */ template void sew(Dart_handle adart1, Dart_handle adart2, bool update_attributes) { if ( update_attributes ) sew(adart1, adart2); else topo_sew(adart1, adart2); } /** Topological unsew by betai the given dart plus all the required darts * to satisfy the combinatorial map validity: but do not update attributes * thus the map can be non valid * @param adart first dart. * @pre !adart->is_free(i). */ template void topo_unsew(Dart_handle adart) { return internal::topo_unsew_functor::run(*this,adart); } /** Unsew by betai the given dart plus all the required darts * to satisfy the combinatorial map validity, and update enabled * attributes when necessary so that the final map is valid. * @param adart first dart. * @pre !adart->is_free(i). * @post is_valid() */ template void unsew(Dart_handle adart) { return internal::unsew_functor::run(*this,adart); } /** Unsew by betai the given dart plus all the required darts * to satisfy the combinatorial map validity. Enabled attributes * are updated only if update_attributes==true. * @param adart first dart. * @param update_attributes a boolean to update the enabled attributes * @pre !adart->is_free(i). */ template void unsew(Dart_handle adart, bool update_attributes) { if ( update_attributes ) unsew(adart); else topo_unsew(adart); } /** Count the marked cells (at least one marked dart). * @param amark the mark to consider. * @param avector containing the dimensions of the cells to count. * @return a vector containing the number of cells. */ std::vector count_marked_cells(int amark, const std::vector& acells) const { std::vector res(dimension+2); std::vector marks(dimension+2); // Initialization of the result for (unsigned int i=0; i,dimension+1>:: run(this, it, &marks, &res); } } // Unmarking darts std::vector tounmark; for (unsigned int i=0; i 0 ) { for (typename Dart_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) { for (unsigned int i=0; i count_cells(const std::vector& acells) const { std::vector res(dimension+1); int m = get_new_mark(); negate_mark(m); // We mark all the cells. res = count_marked_cells(m,acells); negate_mark(m); // We unmark the cells free_mark(m); return res; } protected: /** Set simultaneously all the marks of a given dart. * @param adart the dart. * @param amarks the marks to set. */ void set_marks(Dart_handle adart, const std::bitset & amarks) const { CGAL_assertion(adart != NULL && adart!=null_dart_handle); adart->set_marks(amarks ^ mmask_marks); } /** Get simultaneously all the marks of a given dart. * @param adart the dart. * @return allt the marks of adart. */ std::bitset get_marks(Dart_handle adart) const { CGAL_assertion(adart != NULL && adart!=null_dart_handle); return adart->get_marks() ^ mmask_marks; } /** Get the mask associated to a given mark. * @param amark the mark. * @return the mask associated to mark amark. */ bool get_mask_mark(int amark) const { CGAL_assertion(amark>=0 && (size_type)amark void decrease_attribute_ref_counting(Dart_handle adart) { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "decrease_attribute_ref_counting but " "i-attributes are disabled"); if ( adart->template attribute()!=NULL ) { adart->template attribute()->dec_nb_refs(); if ( adart->template attribute()->get_nb_refs()==0 ) erase_attribute(adart->template attribute()); } } /** Update the dart of the given i-cell attribute onto a non marked dart. * @param ah the attribute to update. * @param amark the mark. */ template void update_dart_of_attribute(Dart_handle ah, int amark) { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "update_dart_of_attribute but " "i-attributes are disabled"); CGAL_assertion(ah!=NULL && ah!=null_dart_handle); if ( ah->template attribute()==NULL || ah->template attribute()->dart()==NULL || !is_marked(ah->template attribute()->dart(),amark) ) return; for (CMap_dart_iterator_of_cell it(*this, ah); it.cont(); ++it) { if (!is_marked(it,amark)) { ah->template attribute()->set_dart(it); return; } } ah->template attribute()->set_dart(NULL); } /** Update the dart of all the cell-attributes incident to ah onto a non * marked dart. This method is used before to remove a cell (which is * marked), to put all the darts of the enabled cells onto surviving dart. * @param ah the dart to update. * @param amark the mark. */ void update_dart_of_all_attributes(Dart_handle ah, int amark) { Helper::template Foreach_enabled_attributes >::run(this,ah,amark); } /** Group the i cell-attributes of two darts. * If the two i cell-attribute of \em adart1 and \em adart2 are different, * we set the i cell-attribute of each dart belonging to the i-cell orbit * of \em adart2 onto the i-cell of \em adart1. * We use the functor On_merge and possibly remove the second * cell-attribute if there is no more darts linked to it. * @param adart1 the first dart. * @param adart2 the second dart. */ template void group_enabled_attribute( Dart_handle adart1, Dart_handle adart2) { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "group_enabled_attribute but " "i-attributes are disabled"); CGAL_assertion(adart1 != NULL && adart2 != NULL); CGAL_assertion(adart1 != null_dart_handle && adart2 != null_dart_handle); CGAL_assertion(i<=dimension); typename Attribute_handle::type a1=adart1->template attribute(); typename Attribute_handle::type a2=adart2->template attribute(); // If the two attributes are equal, nothing to do. if ( a1 == a2 ) return; Dart_handle toSet = NULL; // If the attribute associated to adart1 is NULL, set it with // the attribute associated to adart2 (necessarily != NULL) if (a1 == NULL) { toSet = adart1; a1 = a2; } else { toSet = adart2; if (a2 != NULL) { internal::Apply_cell_functor::run(*a1,*a2); } } set_attribute(toSet, a1); } /** Group all the attributes of adart1 and adart2. If both dart have a * i-attribute, the attribute associated to adart1 is kept. * @param adart1 the first dart. * @param adart1 the second dart. */ template void group_attribute(Dart_handle adart1, Dart_handle adart2) { internal::Group_one_attribute_functor::type>::run(this,adart1,adart2); } /** Group the i cell-attributes of two darts. * If the two i cell-attribute of \em adart1 and \em adart2 are different, * we set the i cell-attribute of adart2 onto the attribute of adart1. * @param adart1 the first dart. * @param adart2 the second dart. */ template void group_enabled_attribute_of_dart( Dart_handle dh1, Dart_handle dh2) { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "group_enabled_attribute_of_dart but " "i-attributes are disabled"); CGAL_assertion( dh1!=NULL && dh2!=NULL ); CGAL_assertion( dh1!=null_dart_handle && dh2!=null_dart_handle ); CGAL_assertion(i<=dimension); typename Attribute_handle::type a1=dh1->template attribute(); typename Attribute_handle::type a2=dh2->template attribute(); // If the two attributes are equal, nothing to do. if ( a1 == a2 ) return; if ( a1==NULL ) set_attribute_of_dart(dh1, a2); else set_attribute_of_dart(dh2, a1); } /** Group all the cells attributes of adart1 and adart2, except the * adim-cell attribute. * @param adart1 the first dart. * @param adart1 the second dart. * @param adim the dimension to not group (-1 to group all dimensions). */ void group_all_attributes_except(Dart_handle adart1, Dart_handle adart2, int adim) { CGAL_assertion( adim==-1 || (1<=adim && (unsigned int)adim<=dimension) ); Helper::template Foreach_enabled_attributes >:: run(this,adart1,adart2,adim); } /** Degroup the i-cell attribute of the two given darts, if required. * If the two darts are incident to the same attribute and do not belong to * the same i-cell, we create a new attibute and link each dart * belonging to the i-cell of adart2 onto this new attribute. * The new attribute is initialized by copying the old one then by using * the functor On_split from the original attribute. * @param adart1 the first dart. * @param adart2 the second dart. * @return true iff the attribute is split. */ template bool degroup_enabled_attribute(Dart_handle adart1, Dart_handle adart2) { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "degroup_enabled_attribute but " "i-attributes are disabled"); CGAL_assertion(adart1 != NULL && adart2 != NULL); CGAL_assertion(adart1 != null_dart_handle && adart2 != null_dart_handle); typename Attribute_handle::type a1=adart1->template attribute(); typename Attribute_handle::type a2=NULL; // If the two attributes are not equal, nothing to do. if ( a1 != adart2->template attribute() || a1 == NULL) return false; // If the two darts belong to the same cell, nothing to do. if ( belong_to_same_cell(*this, adart1, adart2) ) return false; // Here we create a new attribute a2 = create_attribute(*a1); // We call the on_split functor internal::Apply_cell_functor::run(*a1,*a2); // We set the dart of the cell a1 onto adart1. a1->set_dart(adart1); // And we set all the dart of the cell of adart2 to v1. set_attribute(adart2, a2); return true; } template bool degroup_attribute(Dart_handle adart1, Dart_handle adart2) { return internal::Degroup_one_attribute_functor::type>::run(this,adart1,adart2); } /** Degroup all the cells attributes of adart1 and adart2, except the * adim-cell attribute. * @param adart1 the first dart. * @param adart1 the second dart. * @param adim the dimension to not degroup (-1 to degroup all). */ void degroup_all_attributes_except(Dart_handle adart1, Dart_handle adart2, int adim) { CGAL_assertion( adim==-1 || (1<=adim && (unsigned int)adim<=dimension) ); Helper::template Foreach_enabled_attributes >:: run(this,adart1,adart2,adim); } /** Degroup all the cells attributes of adart1 and adart2. * @param adart1 the first dart. * @param adart1 the second dart. */ void degroup_all_attributes(Dart_handle adart1, Dart_handle adart2) { degroup_all_attributes_except(adart1, adart2, -1); } /** Degroup the i-cell attribute of the two given darts, if required. * We create a new attibute and link dart2 onto this new attribute. * The new attribute is initialized by copying the old one then by using * the functor On_split from the original attribute. * @param adart1 the first dart. * @param adart2 the second dart. * @return true iff the attribute is split. */ template bool degroup_enabled_attribute_of_dart( Dart_handle dh1, Dart_handle dh2) { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "group_enabled_attribute_of_dart but " "i-attributes are disabled"); CGAL_assertion( dh1!=NULL && dh2!=NULL ); CGAL_assertion( dh1!=null_dart_handle && dh2!=null_dart_handle ); CGAL_assertion(i<=dimension); typename Attribute_handle::type a1=dh1->template attribute(); typename Attribute_handle::type a2=dh2->template attribute(); // If the two attributes are equal, nothing to do. if ( a1==NULL || a1 != a2 ) return false; a2 = create_attribute(*a1); // We call the on_split functor // internal::Apply_cell_functor::run(*a1,*a2); // We set the attribute of dh2 to a2. for (typename Range::iterator it=Range(*this,dh2).begin(), itend=Range(*this,dh2).end(); it!=itend; ++it) { set_attribute_of_dart(it, a2); } return true; } template bool degroup_attribute_of_dart(Dart_handle adart1, Dart_handle adart2) { return internal::Degroup_one_attribute_of_dart_functor::type, Range>::run(this,adart1,adart2); } /** Test the validity of a i-cell-attribute. * ie all the darts belonging to a i-cell are linked to the same attribute. * @param adart a dart. * @param amark a mark used to mark darts of the i-cell. * @return true iff all the darts of the i-cell link to the same attribute. */ template bool is_valid_attribute(Dart_const_handle adart, unsigned int amark) const { CGAL_static_assertion_msg( Helper::template Dimension_index::value>=0, "is_valid_attribute but i-attributes" " are disabled"); if ( is_marked(adart, amark) ) return true; bool valid = true; typename Attribute_const_handle::type a=adart->template attribute(); unsigned int nb = 0; for (CMap_dart_const_iterator_basic_of_cell it(*this,adart,amark); it.cont(); ++it) { if ( it->template attribute() != a ) valid = false; mark(it, amark); ++nb; } if ( a!=NULL && a->get_nb_refs()!=nb ) valid = false; return valid; } /** Erase marked darts from the map. * Marked darts are unlinked before to be removed, thus surviving darts * are correctly linked, but the map is not necessarily valid depending * on the configuration of removed darts. User must check carefully marked * darts before calling this method. * @param amark the mark of darts to erase. * @return the number of removed darts. */ unsigned int erase_marked_darts(int amark) { unsigned int res = 0, i = 0; Dart_handle d; for (typename Dart_range::iterator it(darts().begin()), itend(darts().end()); it!=itend; ) { d = it++; if (is_marked(d, amark)) { for (i = 0; i <= dimension; ++i) { if (!d->is_free(i)) unlink_beta(d, i); } erase_dart(d); ++res; } } return res; } public: /** Set the i th attribute of the given dart. * @param adart a dart. * @param ah the attribute to set. */ template void set_attribute_of_dart(Dart_handle adart, typename Attribute_handle::type ah) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "set_attribute_of_dart but " "i-attributes are disabled"); CGAL_assertion( adart!=NULL && adart!=null_dart_handle && ah!=NULL ); if ( adart->template attribute()==ah ) return; decrease_attribute_ref_counting(adart); adart->set_attribute(ah); ah->set_dart(adart); } /** Set the i th attribute of all the darts of a given i-cell. * @param adart a dart of the i-cell. * @param ah the vertex to set. */ template void set_attribute(Dart_handle adart, typename Attribute_handle::type ah) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "set_attribute but i-attributes are disabled"); CGAL_assertion( adart!=NULL && adart!=null_dart_handle && ah!=NULL ); for (CMap_dart_iterator_of_cell it(*this, adart); it.cont(); ++it) { if ( it->template attribute()!=ah ) { decrease_attribute_ref_counting(it); it->set_attribute(ah); } } ah->set_dart(adart); } #ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES //**************************************************************************** // Dart_of_orbit_range template struct Dart_of_orbit_range { typedef CMap_dart_iterator_of_orbit iterator; typedef CMap_dart_const_iterator_of_orbit const_iterator; Dart_of_orbit_range(Self &amap, Dart_handle adart) : mmap(amap), mdart(adart), msize(0) {} iterator begin() { return iterator(mmap,mdart); } iterator end() { return iterator(mmap,NULL); } const_iterator begin() const { return const_iterator(mmap,mdart); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for ( iterator it=begin(),itend=end(); it!=itend; ++it) ++msize; return msize; } bool empty() const { return mdart==NULL; } private: Self & mmap; Dart_handle mdart; size_type msize; }; //**************************************************************************** // Dart_of_orbit_const_range template struct Dart_of_orbit_const_range { typedef CMap_dart_const_iterator_of_orbit const_iterator; Dart_of_orbit_const_range(const Self &amap, Dart_const_handle adart) : mmap(amap), mdart(adart), msize(0) {} const_iterator begin() const { return const_iterator(mmap,mdart); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for ( const_iterator it=begin(),itend=end(); it!=itend; ++it) ++msize; return msize; } bool empty() const { return mdart==NULL; } private: const Self & mmap; Dart_const_handle mdart; size_type msize; }; #else //**************************************************************************** // Dart_of_orbit_range template struct Dart_of_orbit_range { typedef CMap_dart_iterator_of_orbit iterator; typedef CMap_dart_const_iterator_of_orbit const_iterator; Dart_of_orbit_range(Self &amap, Dart_handle adart) : mmap(amap), mdart(adart), msize(0) {} iterator begin() { return iterator(mmap,mdart); } iterator end() { return iterator(mmap,NULL); } const_iterator begin() const { return const_iterator(mmap,mdart); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for ( iterator it=begin(),itend=end(); it!=itend; ++it) ++msize; return msize; } bool empty() const { return mdart==NULL; } private: Self & mmap; Dart_handle mdart; size_type msize; }; //**************************************************************************** // Dart_of_orbit_const_range template struct Dart_of_orbit_const_range { typedef CMap_dart_const_iterator_of_orbit const_iterator; Dart_of_orbit_const_range(const Self &amap, Dart_const_handle adart) : mmap(amap), mdart(adart), msize(0) {} const_iterator begin() const { return const_iterator(mmap,mdart); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for ( const_iterator it=begin(),itend=end(); it!=itend; ++it) ++msize; return msize; } bool empty() const { return mdart==NULL; } private: const Self & mmap; Dart_const_handle mdart; size_type msize; }; #endif //CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES //**************************************************************************** // Dart_of_cell_range template struct Dart_of_cell_range { typedef CMap_dart_iterator_of_cell iterator; typedef CMap_dart_const_iterator_of_cell const_iterator; Dart_of_cell_range(Self &amap, Dart_handle adart) : mmap(amap), mdart(adart), msize(0) {} iterator begin() { return iterator(mmap,mdart); } iterator end() { return iterator(mmap,NULL); } const_iterator begin() const { return const_iterator(mmap,mdart); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for ( iterator it=begin(); it!=end(); ++it) ++msize; return msize; } bool empty() const { return mdart==NULL; } private: Self & mmap; Dart_handle mdart; size_type msize; }; //**************************************************************************** // Dart_of_cell_const_range template struct Dart_of_cell_const_range { typedef CMap_dart_const_iterator_of_cell const_iterator; Dart_of_cell_const_range(const Self &amap, Dart_const_handle adart) : mmap(amap), mdart(adart), msize(0) {} const_iterator begin() const { return const_iterator(mmap,mdart); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for ( const_iterator it=begin(); it!=end(); ++it) ++msize; return msize; } bool empty() const { return mdart==NULL; } private: const Self & mmap; Dart_const_handle mdart; size_type msize; }; //**************************************************************************** #ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES /// @return a range on all the darts of the given orbit template Dart_of_orbit_range darts_of_orbit(Dart_handle adart) { return Dart_of_orbit_range(*this,adart); } template Dart_of_orbit_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_range(*this,adart); } #else /// @return a range on all the darts of the given orbit Dart_of_orbit_range<> darts_of_orbit(Dart_handle adart) { return Dart_of_orbit_range<>(*this,adart); } Dart_of_orbit_const_range<> darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_range<>(*this,adart); } template Dart_of_orbit_range darts_of_orbit(Dart_handle adart) { return Dart_of_orbit_range(*this,adart); } template Dart_of_orbit_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_range(*this,adart); } template Dart_of_orbit_range darts_of_orbit(Dart_handle adart) { return Dart_of_orbit_range(*this,adart); } template Dart_of_orbit_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_range(*this,adart); } template Dart_of_orbit_range darts_of_orbit(Dart_handle adart) { return Dart_of_orbit_range(*this,adart); } template Dart_of_orbit_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_range(*this,adart); } template Dart_of_orbit_range darts_of_orbit(Dart_handle adart) { return Dart_of_orbit_range(*this,adart); } template Dart_of_orbit_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_range(*this,adart); } template Dart_of_orbit_range darts_of_orbit(Dart_handle adart) { return Dart_of_orbit_range(*this,adart); } template Dart_of_orbit_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_range(*this,adart); } template Dart_of_orbit_range darts_of_orbit(Dart_handle adart) { return Dart_of_orbit_range(*this,adart); } template Dart_of_orbit_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_range(*this,adart); } template Dart_of_orbit_range darts_of_orbit(Dart_handle adart) { return Dart_of_orbit_range(*this,adart); } template Dart_of_orbit_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_range(*this,adart); } template Dart_of_orbit_range darts_of_orbit (Dart_handle adart) { return Dart_of_orbit_range(*this,adart); } template Dart_of_orbit_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_range(*this,adart); } template Dart_of_orbit_range darts_of_orbit(Dart_handle adart) { return Dart_of_orbit_range(*this,adart); } template Dart_of_orbit_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_range (*this,adart); } #endif //CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES /// @return a range on all the darts of the given i-cell template Dart_of_cell_range darts_of_cell(Dart_handle adart) { return Dart_of_cell_range(*this,adart); } template Dart_of_cell_const_range darts_of_cell(Dart_const_handle adart) const { return Dart_of_cell_const_range(*this,adart); } template Dart_of_cell_range darts_of_cell(Dart_handle adart) { return darts_of_cell(adart); } template Dart_of_cell_const_range darts_of_cell(Dart_const_handle adart) const { return darts_of_cell(adart); } //************************************************************************** // One_dart_per_incident_cell_range template struct One_dart_per_incident_cell_range { typedef CMap_one_dart_per_incident_cell_iterator iterator; typedef CMap_one_dart_per_incident_cell_const_iterator const_iterator; One_dart_per_incident_cell_range(Self &amap, Dart_handle adart) : mmap(amap), mdart(adart),msize(0) {} iterator begin() { return iterator(mmap,mdart); } iterator end() { return iterator(mmap,NULL); } const_iterator begin() const { return const_iterator(mmap,mdart); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for ( iterator it=begin(); it!=end(); ++it) ++msize; return msize; } bool empty() const { return mdart==NULL; } private: Self & mmap; Dart_handle mdart; size_type msize; }; //************************************************************************** // One_dart_per_incident_cell_const_range template struct One_dart_per_incident_cell_const_range { typedef CMap_one_dart_per_incident_cell_const_iterator const_iterator; One_dart_per_incident_cell_const_range(const Self &amap, Dart_const_handle adart) : mmap(amap), mdart(adart), msize(0) {} const_iterator begin() const { return const_iterator(mmap,mdart); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for ( const_iterator it=begin(); it!=end(); ++it) ++msize; return msize; } bool empty() const { return mdart==NULL; } private: const Self & mmap; Dart_const_handle mdart; size_type msize; }; //************************************************************************** // One_dart_per_cell_range template struct One_dart_per_cell_range { typedef CMap_one_dart_per_cell_iterator iterator; typedef CMap_one_dart_per_cell_const_iterator const_iterator; One_dart_per_cell_range(Self &amap) : mmap(amap), msize(0) {} iterator begin() { return iterator(mmap); } iterator end() { return iterator(mmap,NULL); } const_iterator begin() const { return const_iterator(mmap); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for ( iterator it=begin(); it!=end(); ++it) ++msize; return msize; } bool empty() const { return mmap.is_empty(); } private: Self & mmap; size_type msize; }; //************************************************************************** // One_dart_per_cell_const_range template struct One_dart_per_cell_const_range { typedef CMap_one_dart_per_cell_const_iterator const_iterator; One_dart_per_cell_const_range(const Self &amap) : mmap(amap), msize(0) {} const_iterator begin() const { return const_iterator(mmap); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for ( const_iterator it=begin(); it!=end(); ++it) ++msize; return msize; } bool empty() const { return mmap.is_empty(); } private: const Self & mmap; size_type msize; }; //************************************************************************** // Dart_of_involution_range template struct Dart_of_involution_range { typedef CMap_dart_iterator_of_involution iterator; typedef CMap_dart_const_iterator_of_involution const_iterator; Dart_of_involution_range(Self &amap, Dart_handle adart) : mmap(amap), mdart(adart), msize(0) {} iterator begin() { return iterator(mmap,mdart); } iterator end() { return iterator(mmap,NULL); } const_iterator begin() const { return const_iterator(mmap,mdart); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for (iterator it=begin(); it!=end(); ++it) ++msize; return msize; } bool empty() const { return mmap.is_empty(); } private: Self & mmap; Dart_handle mdart; size_type msize; }; //************************************************************************** // Dart_of_involution_const_range template struct Dart_of_involution_const_range { typedef CMap_dart_const_iterator_of_involution const_iterator; Dart_of_involution_const_range(const Self &amap, Dart_const_handle adart) : mmap(amap), mdart(adart), msize(0) {} const_iterator begin() const { return const_iterator(mmap,mdart); } const_iterator end() const { return const_iterator(mmap,NULL); } size_type size() { if (msize==0) for (const_iterator it=begin(); it!=end(); ++it) ++msize; return msize; } bool empty() const { return mmap.is_empty(); } private: const Self & mmap; Dart_const_handle mdart; size_type msize; }; //************************************************************************** /// @return a range on the i-cells incindent to the given j-cell. template One_dart_per_incident_cell_range one_dart_per_incident_cell(Dart_handle adart) { return One_dart_per_incident_cell_range(*this,adart); } template One_dart_per_incident_cell_const_range one_dart_per_incident_cell(Dart_const_handle adart) const { return One_dart_per_incident_cell_const_range(*this,adart); } template One_dart_per_incident_cell_range one_dart_per_incident_cell(Dart_handle adart) { return one_dart_per_incident_cell(adart); } template One_dart_per_incident_cell_const_range one_dart_per_incident_cell(Dart_const_handle adart) const { return one_dart_per_incident_cell(adart); } /// @return a range on all the i-cells template One_dart_per_cell_range one_dart_per_cell() { return One_dart_per_cell_range(*this); } template One_dart_per_cell_const_range one_dart_per_cell() const { return One_dart_per_cell_const_range(*this); } template One_dart_per_cell_range one_dart_per_cell() { return one_dart_per_cell(); } template One_dart_per_cell_const_range one_dart_per_cell() const { return one_dart_per_cell(); } public: /// Void dart. A dart d is i-free if beta_i(d)=null_dart_handle. static Dart_handle null_dart_handle; private: /// Dart container. Dart_container mdarts; /// Container for the null_dart_handle, static data member. static Dart_container mnull_dart_container; /// Array of reserved marks: mused_marks[i] true <=> mark number i is /// in used, otherwise the mark is free. mutable std::bitset mused_marks; /// Mask marks to know the value of unmark dart, for each index i. mutable std::bitset mmask_marks; /// Number of used marks. mutable size_type mnb_used_marks; /// Index of each mark, in mfree_marks_stack or in mfree_marks_stack. mutable size_type mindex_marks[NB_MARKS]; /// "Stack" of free marks. mutable int mfree_marks_stack[NB_MARKS]; /// "Stack" of used marks. mutable int mused_marks_stack[NB_MARKS]; /// Number of marked darts for each used marks. mutable size_type mnb_marked_darts[NB_MARKS]; /// Tuple of attributes containers typename Helper::Attribute_containers mattribute_containers; }; /// Allocation of static data members /// mnull_dart_container template < unsigned int d_, class Refs, class Items_, class Alloc_ > typename Combinatorial_map_base::Dart_container Combinatorial_map_base::mnull_dart_container; /// null_dart_handle template < unsigned int d_, class Refs, class Items_, class Alloc_ > typename Combinatorial_map_base::Dart_handle Combinatorial_map_base::null_dart_handle; // = mnull_dart_container.emplace( std::bitset() ); // Does not work on windows => segfault // Thus we initialize null_dart_handle in the Combinatorial_map constructor // Not thread safe ! template < unsigned int d_, class Items_=Combinatorial_map_min_items, class Alloc_=CGAL_ALLOCATOR(int) > class Combinatorial_map : public Combinatorial_map_base, Items_, Alloc_ > { public: typedef Combinatorial_map Self; typedef Combinatorial_map_base Base; typedef typename Base::Dart_handle Dart_handle; typedef typename Base::Dart_const_handle Dart_const_handle; typedef typename Base::Alloc Alloc; }; } // namespace CGAL #endif // CGAL_COMBINATORIAL_MAP_H // // EOF //