// 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; either version 3 of the License, // or (at your option) any later version. // // 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 #include #include #include #include #include #include #include #include #include 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 Storage_= Combinatorial_map_storage_1 > class Combinatorial_map_base: public Storage_ { template friend struct CGAL::internal::Call_merge_functor; template friend struct CGAL::internal::Call_split_functor; template friend struct Remove_cell_functor; template friend struct Contract_cell_functor; template friend struct internal::Reverse_orientation_of_map_functor; template friend struct internal::Reverse_orientation_of_connected_component_functor; template friend struct internal::Init_attribute_functor; public: template < unsigned int A, class B, class I, class D, class S > friend class Combinatorial_map_base; /// Types definition typedef Storage_ Storage; typedef Storage Base; typedef Combinatorial_map_base Self; typedef typename Base::Dart Dart; typedef typename Base::Dart_handle Dart_handle; typedef typename Base::Dart_const_handle Dart_const_handle; typedef typename Base::Dart_container Dart_container; typedef typename Base::Dart_wrapper Dart_wrapper; typedef typename Base::size_type size_type; typedef typename Base::Helper Helper; typedef typename Base::Attributes Attributes; typedef typename Base::Items Items; typedef typename Base::Alloc Alloc; typedef typename Base::Use_index Use_index; static const size_type NB_MARKS = Base::NB_MARKS; static const unsigned int dimension = Base::dimension; typedef typename Base::Null_handle_type Null_handle_type; static Null_handle_type null_handle; using Base::null_dart_handle; using Base::mdarts; using Base::get_beta; using Base::is_free; using Base::set_dart_mark; using Base::get_dart_mark; using Base::flip_dart_mark; using Base::set_dart_marks; using Base::get_dart_marks; using Base::dart_link_beta; using Base::dart_unlink_beta; using Base::attribute; using Base::mattribute_containers; using Base::get_attribute; using Base::dart_of_attribute; using Base::set_dart_of_attribute; using Base::info_of_attribute; using Base::info; using Base::dart; /// 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 for attributes template struct Attribute_type: public Base::template Attribute_type {}; template struct Attribute_handle: public Base::template Attribute_handle {}; template struct Attribute_const_handle: public Base::template Attribute_const_handle {}; template struct Attribute_range: public Base::template Attribute_range {}; template struct Attribute_const_range: public Base::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->init_storage(); this->mnb_used_marks = 0; this->mmask_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; this->mnb_times_reserved_marks[i] = 0; } this->automatic_attributes_management = true; init_dart(null_dart_handle); CGAL_assertion(number_of_darts()==0); } /** Copy the given combinatorial map into *this. * Note that both CMap can have different dimensions and/or non void attributes. * @param amap the combinatorial map to copy. * @post *this is valid. */ template void copy(const CMap2& amap, const Converters& converters, const Pointconverter& pointconverter) { this->clear(); this->mnb_used_marks = amap.mnb_used_marks; this->mmask_marks = amap.mmask_marks; for (size_type i = 0; i < NB_MARKS; ++i) { this->mfree_marks_stack[i] = amap.mfree_marks_stack[i]; this->mindex_marks[i] = amap.mindex_marks[i]; this->mnb_marked_darts[i] = amap.mnb_marked_darts[i]; this->mnb_times_reserved_marks[i] = amap.mnb_times_reserved_marks[i]; } init_dart(null_dart_handle, amap.get_marks(amap.null_dart_handle)); // Create an mapping between darts of the two maps (originals->copies). // TODO: replace the std::map by a boost::unordered_map // (here we cannot use CGAL::Unique_hash_map because it does not provide // iterators... std::map dartmap; for (typename CMap2::Dart_const_range::const_iterator it=amap.darts().begin(), itend=amap.darts().end(); it!=itend; ++it) { dartmap[it]=mdarts.emplace(); init_dart(dartmap[it], amap.get_marks(it)); } unsigned int min_dim=(dimension ::iterator dartmap_iter, dartmap_iter_end=dartmap.end(); for (dartmap_iter=dartmap.begin(); dartmap_iter!=dartmap_iter_end; ++dartmap_iter) { for (unsigned int i=0; i<=min_dim; i++) { if (!amap.is_free(dartmap_iter->first,i) && (dartmap_iter->first)<(amap.beta(dartmap_iter->first,i))) { basic_link_beta(dartmap_iter->second, dartmap[amap.beta(dartmap_iter->first,i)], i); } } } /** Copy attributes */ for (dartmap_iter=dartmap.begin(); dartmap_iter!=dartmap_iter_end; ++dartmap_iter) { Helper::template Foreach_enabled_attributes < internal::Copy_attributes_functor >:: run(&amap, static_cast(this), dartmap_iter->first, dartmap_iter->second, converters, pointconverter); } CGAL_assertion (is_valid () == 1); } template void copy(const CMap2& amap) { CGAL::cpp11::tuple<> converters; Default_converter_cmap_0attributes_with_point pointconverter; return copy< CMap2, CGAL::cpp11::tuple<>, Default_converter_cmap_0attributes_with_point > (amap, converters, pointconverter); } template void copy(const CMap2& amap, const Converters& converters) { Default_converter_cmap_0attributes_with_point pointconverter; return copy< CMap2, Converters, Default_converter_cmap_0attributes_with_point > (amap, converters, pointconverter); } // Copy constructor from a map having exactly the same type. Combinatorial_map_base (const Self & amap) { copy(amap); } // "Copy constructor" from a map having different type. template Combinatorial_map_base(const CMap2& amap) { copy(amap); } // "Copy constructor" from a map having different type. template Combinatorial_map_base(const CMap2& amap, Converters& converters) { copy(amap, converters); } // "Copy constructor" from a map having different type. template Combinatorial_map_base(const CMap2& amap, Converters& converters, const Pointconverter& pointconverter) { copy (amap, converters, pointconverter); } /** Affectation operation. Copies one map to the other. * @param amap a combinatorial map. * @return A copy of that combinatorial map. */ Self & operator= (const Self & amap) { if (this!=&amap) { Self tmp(amap); this->swap(tmp); } return *this; } /** Swap this combinatorial map with amap, a second combinatorial map. * Note that the two maps have exactly the same type. * @param amap a combinatorial map. */ void swap(Self & amap) { if (this!=&amap) { amap.mdarts.swap(mdarts); std::swap_ranges(mnb_times_reserved_marks, mnb_times_reserved_marks+NB_MARKS, amap.mnb_times_reserved_marks); std::swap(mmask_marks,amap.mmask_marks); std::swap(mnb_used_marks, amap.mnb_used_marks); std::swap_ranges(mindex_marks,mindex_marks+NB_MARKS, amap.mindex_marks); std::swap_ranges(mfree_marks_stack, mfree_marks_stack+NB_MARKS, amap.mfree_marks_stack); std::swap_ranges(mused_marks_stack,mused_marks_stack+NB_MARKS, amap.mused_marks_stack); std::swap_ranges(mnb_marked_darts,mnb_marked_darts+NB_MARKS, amap.mnb_marked_darts); mattribute_containers.swap(amap.mattribute_containers); #ifndef CGAL_CMAP_DEPRECATED std::swap(null_dart_handle, amap.null_dart_handle); this->mnull_dart_container.swap(amap.mnull_dart_container); #endif // CGAL_CMAP_DEPRECATED } } /** 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); this->init_storage(); init_dart(null_dart_handle); } /** 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. */ #ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES template < typename... Args > Dart_handle create_dart(const Args&... args) { Dart_handle res=mdarts.emplace(args...); init_dart(res); return res; } #else Dart_handle create_dart() { Dart_handle res=mdarts.emplace(); init_dart(res); return res; } template < typename T1 > Dart_handle create_dart(const T1 &t1) { Dart_handle res=mdarts.emplace(t1); init_dart(res); return res; } template < typename T1, typename T2 > Dart_handle create_dart(const T1 &t1, const T2 &t2) { Dart_handle res=mdarts.emplace(t1, t2); init_dart(res); return res; } template < typename T1, typename T2, typename T3 > Dart_handle create_dart(const T1 &t1, const T2 &t2, const T3 &t3) { Dart_handle res=mdarts.emplace(t1, t2, t3); init_dart(res); return res; } template < typename T1, typename T2, typename T3, typename T4 > Dart_handle create_dart(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) { Dart_handle res=mdarts.emplace(t1, t2, t3, t4); init_dart(res); return res; } template < typename T1, typename T2, typename T3, typename T4, typename T5 > Dart_handle create_dart(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5) { Dart_handle res=mdarts.emplace(t1, t2, t3, t4, t5); init_dart(res); return res; } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > Dart_handle create_dart(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6) { Dart_handle res=mdarts.emplace(t1, t2, t3, t4, t5, t6); init_dart(res); return res; } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > Dart_handle create_dart(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7) { Dart_handle res=mdarts.emplace(t1, t2, t3, t4, t5, t6, t7); init_dart(res); return res; } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8 > Dart_handle create_dart(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7, const T8 &t8) { Dart_handle res=mdarts.emplace(t1, t2, t3, t4, t5, t6, t7, t8); init_dart(res); return res; } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > Dart_handle create_dart(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7, const T8 &t8, const T9 &t9) { Dart_handle res=mdarts.emplace(t1, t2, t3, t4, t5, t6, t7, t8, t9); init_dart(res); return res; } #endif /** 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); } /** Return the highest dimension for which dh is not free. * @param dh a dart handle * @return the dimension d such that dh is not d-free but k-free for * all k>d. -1 if the dart is free for all d in {0..n} */ int highest_nonfree_dimension(Dart_const_handle dh) const { for (int i=(int)dimension; i>=0; --i) { if ( !is_free(dh, i) ) return i; } return -1; } /** Return a dart belonging to the same edge and to the second vertex * of the current edge (NULL if such a dart does not exist). * @return An handle to the opposite dart. */ Dart_handle opposite(Dart_handle dh) { for (unsigned int i = 2; i <= dimension; ++i) if (!is_free(dh, i)) return beta(dh, i); return null_handle; } Dart_const_handle opposite(Dart_const_handle dh) const { for (unsigned int i = 2; i <= dimension; ++i) if (!is_free(dh, i)) return beta(dh, i); return null_handle; } /** Return a dart incident to the other extremity of the current edge, * but contrary to opposite, non necessary to the same edge * (NULL if such a dart does not exist). * @return An handle to the opposite dart. */ Dart_handle other_extremity(Dart_handle dh) { for (unsigned int i = 1; i <= dimension; ++i) if (!is_free(dh, i)) return beta(dh, i); return null_handle; } Dart_const_handle other_extremity(Dart_const_handle dh) const { for (unsigned int i = 1; i <= dimension; ++i) if (!is_free(dh, i)) return beta(dh, i); return null_handle; } // Set the handle on the i th attribute template void set_dart_attribute(Dart_handle dh, typename Attribute_handle::type ah) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "set_dart_attribute called but i-attributes are disabled."); if ( this->template attribute(dh)==ah ) return; if ( this->template attribute(dh)!=null_handle ) { this->template get_attribute(this->template attribute(dh)). dec_nb_refs(); if ( this->template get_attribute(this->template attribute(dh)). get_nb_refs()==0 ) this->template erase_attribute(this->template attribute(dh)); } this->template basic_set_dart_attribute(dh, ah); if ( ah!=null_handle ) { this->template set_dart_of_attribute(ah, dh); this->template get_attribute(ah).inc_nb_refs(); } } protected: /// Marks can be modified even for const handle; otherwise it is not /// possible to iterate through const combinatorial maps. // Initialize a given dart: all beta to null_dart_handle and all // attributes to null, all marks unmarked. void init_dart(Dart_handle adart) { set_dart_marks(adart, mmask_marks); for (unsigned int i = 0; i <= dimension; ++i) dart_unlink_beta(adart, i); Helper::template Foreach_enabled_attributes >::run(this, adart); } // Initialize a given dart: all beta to null_dart_handle and all // attributes to null, marks are given. void init_dart(Dart_handle adart, const std::bitset& amarks) { set_marks(adart, amarks); for (unsigned int i = 0; i <= dimension; ++i) dart_unlink_beta(adart, i); Helper::template Foreach_enabled_attributes >::run(this, adart); } public: /// @return the betas of ADart (beta are used in the same order than /// they are given as parameters) #ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES template Dart_handle beta(Dart_handle ADart, Betas... betas) { return CGAL::internal::Beta_functor:: run(this, ADart, betas...); } template Dart_const_handle beta(Dart_const_handle ADart, Betas... betas) const { return CGAL::internal::Beta_functor:: run(this, ADart, betas...); } template Dart_handle beta(Dart_handle ADart) { return CGAL::internal::Beta_functor_static:: run(this, ADart); } template Dart_const_handle beta(Dart_const_handle ADart) const { return CGAL::internal::Beta_functor_static:: run(this, ADart); } #else Dart_handle beta(Dart_handle ADart, int B1) { return this->get_beta(ADart, B1); } Dart_handle beta(Dart_handle ADart, int B1, int B2) { return beta(beta(ADart, B1), B2); } Dart_handle beta(Dart_handle ADart, int B1, int B2, int B3) { return beta(beta(ADart, B1), B2, B3); } Dart_handle beta(Dart_handle ADart, int B1, int B2, int B3, int B4) { return beta(beta(ADart, B1), B2, B3, B4); } Dart_handle beta(Dart_handle ADart, int B1, int B2, int B3, int B4, int B5) { return beta(beta(ADart, B1), B2, B3, B4, B5); } Dart_handle beta(Dart_handle ADart, int B1, int B2, int B3, int B4, int B5, int B6) { return beta(beta(ADart, B1), B2, B3, B4, B5, B6); } Dart_handle beta(Dart_handle ADart, int B1, int B2, int B3, int B4, int B5, int B6, int B7) { return beta(beta(ADart, B1), B2, B3, B4, B5, B6, B7); } Dart_handle beta(Dart_handle ADart, int B1, int B2, int B3, int B4, int B5, int B6, int B7, int B8) { return beta(beta(ADart, B1), B2, B3, B4, B5, B6, B7, B8); } Dart_handle beta(Dart_handle ADart, int B1, int B2, int B3, int B4, int B5, int B6, int B7, int B8, int B9) { return beta(beta(ADart, B1), B2, B3, B4, B5, B6, B7, B8, B9); } template Dart_handle beta(Dart_handle ADart) { return this->template get_beta(ADart); } template Dart_handle beta(Dart_handle ADart) { return beta(beta(ADart)); } template Dart_handle beta(Dart_handle ADart) { return beta(beta(ADart)); } template Dart_handle beta(Dart_handle ADart) { return beta(beta(ADart)); } template Dart_handle beta(Dart_handle ADart) { return beta(beta(ADart)); } template Dart_handle beta(Dart_handle ADart) { return beta(beta(ADart)); } template Dart_handle beta(Dart_handle ADart) { return beta(beta(ADart)); } template Dart_handle beta(Dart_handle ADart) { return beta(beta(ADart)); } template Dart_handle beta(Dart_handle ADart) { return beta(beta(ADart)); } Dart_const_handle beta(Dart_const_handle ADart, int B1) const { return this->get_beta(ADart, B1); } Dart_const_handle beta(Dart_const_handle ADart, int B1, int B2) const { return beta(beta(ADart, B1), B2); } Dart_const_handle beta(Dart_const_handle ADart, int B1, int B2, int B3) const { return beta(beta(ADart, B1), B2, B3); } Dart_const_handle beta(Dart_const_handle ADart, int B1, int B2, int B3, int B4) const { return beta(beta(ADart, B1), B2, B3, B4); } Dart_const_handle beta(Dart_const_handle ADart, int B1, int B2, int B3, int B4, int B5) const { return beta(beta(ADart, B1), B2, B3, B4, B5); } Dart_const_handle beta(Dart_const_handle ADart, int B1, int B2, int B3, int B4, int B5, int B6) const { return beta(beta(ADart, B1), B2, B3, B4, B5, B6); } Dart_const_handle beta(Dart_const_handle ADart, int B1, int B2, int B3, int B4, int B5, int B6, int B7) const { return beta(beta(ADart, B1), B2, B3, B4, B5, B6, B7); } Dart_const_handle beta(Dart_const_handle ADart, int B1, int B2, int B3, int B4, int B5, int B6, int B7, int B8) const { return beta(beta(ADart, B1), B2, B3, B4, B5, B6, B7, B8); } Dart_const_handle beta(Dart_const_handle ADart, int B1, int B2, int B3, int B4, int B5, int B6, int B7, int B8, int B9) const { return beta(beta(ADart, B1), B2, B3, B4, B5, B6, B7, B8, B9); } template Dart_const_handle beta(Dart_const_handle ADart) const { return this->template get_beta(ADart); } template Dart_const_handle beta(Dart_const_handle ADart) const { return beta(beta(ADart)); } template Dart_const_handle beta(Dart_const_handle ADart) const { return beta(beta(ADart)); } template Dart_const_handle beta(Dart_const_handle ADart) const { return beta(beta(ADart)); } template Dart_const_handle beta(Dart_const_handle ADart) const { return beta(beta(ADart)); } template Dart_const_handle beta(Dart_const_handle ADart) const { return beta(beta(ADart)); } template Dart_const_handle beta(Dart_const_handle ADart) const { return beta(beta(ADart)); } template Dart_const_handle beta(Dart_const_handle ADart) const { return beta(beta(ADart)); } template Dart_const_handle beta(Dart_const_handle ADart) const { return beta(beta(ADart)); } #endif /** 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)amark1 ) { --mnb_times_reserved_marks[amark]; return; } unmark_all(amark); // 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; mnb_times_reserved_marks[amark]=0; } /** 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 (is_free(it, 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 (is_free(it, 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) * @TODO move into Combinatorial_map_operations ? */ template unsigned int close() { 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 ( this->template is_free(it) ) { d = create_dart(); ++res; link_beta_for_involution(it, d); // Special cases for 0 and 1 if ( !this->template is_free<1>(it) && !this->template is_free(beta<1>(it)) ) link_beta<1>(beta<1,i>(it),d); if ( !this->template is_free<0>(it) && !this->template is_free(beta<0>(it)) ) link_beta<0>(beta<0,i>(it),d); // General case for 2...dimension for ( unsigned int j=2; j<=dimension; ++j) { if ( j+1!=i && j!=i && j!=i+1 && !is_free(it,j) && !this->template is_free(beta(it, j)) ) { basic_link_beta_for_involution(beta(it, j, i), d, j); } } d2 = it; while (d2 != null_dart_handle && !this->template is_free(d2)) { d2 = beta(d2); } if (d2 != null_dart_handle) { if (i==2) basic_link_beta<1>(d2, d); else basic_link_beta_for_involution(d2, d); } } } 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 ((!is_free(it, 0) && beta(it, 0, 1)!=it) || (!is_free(it, 1) && beta(it, 1, 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 (!is_free(it, i) && beta(it, i, 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 (!is_free(it, 0)) { for ( i = 3; i <= dimension; ++i) if ((is_free(it, i) != is_free(beta(it, 0), i)) || (!is_free(it, i) && beta(it, 0, i)!=beta(it, i, 1))) { std::cerr << "Map not valid: beta(0) o beta(" << i << ") is not an involution for " <<&(*it) << std::endl; valid = false; } } if (!is_free(it, 1)) { for ( i = 3; i <= dimension; ++i) if ((is_free(it, i) != is_free(beta(it, 1), i)) || (!is_free(it, i) && beta(it, 1, i)!=beta(it, i, 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 (!is_free(it, i)) { for ( j = i + 2; j <= dimension; ++j) if ((is_free(it, j)!=is_free(beta(it, i), j)) || (!is_free(it, j) && beta(it, i, j)!=beta(it, j, 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; } /// correct invalid attributes in the map void correct_invalid_attributes() { std::vector marks(dimension+1); for ( int i=0; i<=dimension; ++i) marks[i] = -1; Helper::template Foreach_enabled_attributes >:: run(this,&marks); for ( typename Dart_range::iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) { Helper::template Foreach_enabled_attributes >:: run(this,it,&marks); } for ( int i=0; i<=dimension; ++i) if ( marks[i]!=-1 ) { CGAL_assertion( is_whole_map_marked(marks[i]) ); free_mark(marks[i]); } } /// @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, bool attribs=false) 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"; } if ( attribs ) { Helper::template Foreach_enabled_attributes >::run(this, it); } os << std::endl; ++nb; } os << "Number of darts: " << nb <<"(sizeofdarts=" < std::ostream& display_orbits(std::ostream & aos) const { CGAL_static_assertion( (boost::is_same::value) ); 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"); typename Attribute_handle::type res= CGAL::cpp11::get::value> (mattribute_containers).emplace(args...); // Reinitialize the ref counting of the new attribute. This is normally // not required except if create_attribute is used as "copy contructor". this->template get_attribute(res).mrefcounting = 0; return res; } #else template typename Attribute_handle::type create_attribute() { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "create_attribute but i-attributes are disabled"); return CGAL::cpp11::get::value> (mattribute_containers).emplace(); } template typename Attribute_handle::type create_attribute(const T1 &t1) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "create_attribute but i-attributes are disabled"); typename Attribute_handle::type res= CGAL::cpp11::get::value> (mattribute_containers).emplace(t1); this->template get_attribute(res).mrefcounting = 0; return res; } template typename Attribute_handle::type create_attribute(const T1 &t1, const T2 &t2) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "create_attribute but i-attributes are disabled"); return CGAL::cpp11::get::value> (mattribute_containers).emplace(t1, t2); } template typename Attribute_handle::type create_attribute(const T1 &t1, const T2 &t2, const T3 &t3) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "create_attribute but i-attributes are disabled"); return CGAL::cpp11::get::value> (mattribute_containers).emplace(t1, t2, t3); } template typename Attribute_handle::type create_attribute(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "create_attribute but i-attributes are disabled"); return CGAL::cpp11::get::value> (mattribute_containers).emplace(t1, t2, t3, t4); } template typename Attribute_handle::type create_attribute(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "create_attribute but i-attributes are disabled"); return CGAL::cpp11::get::value> (mattribute_containers).emplace(t1, t2, t3, t4, t5); } template typename Attribute_handle::type create_attribute(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "create_attribute but i-attributes are disabled"); return CGAL::cpp11::get::value> (mattribute_containers).emplace(t1, t2, t3, t4, t5, t6); } template typename Attribute_handle::type create_attribute(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "create_attribute but i-attributes are disabled"); return CGAL::cpp11::get::value> (mattribute_containers).emplace(t1, t2, t3, t4, t5, t6, t7); } template typename Attribute_handle::type create_attribute(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7, const T8 &t8) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "create_attribute but i-attributes are disabled"); return CGAL::cpp11::get::value> (mattribute_containers).emplace(t1, t2, t3, t4, t5, t6, t7, t8); } template typename Attribute_handle::type create_attribute(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7, const T8 &t8, const T9 &t9) { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "create_attribute but i-attributes are disabled"); return CGAL::cpp11::get::value> (mattribute_containers).emplace(t1, t2, t3, t4, t5, t6, t7, t8, t9); } #endif /// 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::cpp11::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::cpp11::get::value> (mattribute_containers).size(); } /** 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 dh, typename Attribute_handle::type ah) { CGAL_static_assertion(i<=dimension); CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "set_attribute but i-attributes are disabled"); for ( typename Dart_of_cell_range::iterator it(*this, dh); it.cont(); ++it) { this->template set_dart_attribute(it, ah); } } /// @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::cpp11::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::cpp11::get::value> (mattribute_containers); } // Get the ith dynamic onsplit functor (by reference so that we can // modify it directly). template boost::function::type&, typename Attribute_type::type&)>& onsplit_functor() { CGAL_static_assertion_msg (Helper::template Dimension_index::value>=0, "onsplit_functor but " "i-attributes are disabled"); return CGAL::cpp11::get::value> (m_onsplit_functors); } // Get the ith dynamic onsplit functor (by reference so that we can // modify it directly). template const boost::function::type&, typename Attribute_type::type&)>& onsplit_functor() const { CGAL_static_assertion_msg (Helper::template Dimension_index::value>=0, "onsplit_functor but " "i-attributes are disabled"); return CGAL::cpp11::get::value> (m_onsplit_functors); } // Get the ith dynamic onmerge functor (by reference so that we can // modify it directly). template boost::function::type&, typename Attribute_type::type&)>& onmerge_functor() { CGAL_static_assertion_msg (Helper::template Dimension_index::value>=0, "onsplit_functor but " "i-attributes are disabled"); return CGAL::cpp11::get::value> (m_onmerge_functors); } // Get the ith dynamic onmerge functor (by reference so that we can // modify it directly). template const boost::function::type&, typename Attribute_type::type&)>& onmerge_functor() const { CGAL_static_assertion_msg (Helper::template Dimension_index::value>=0, "onsplit_functor but " "i-attributes are disabled"); return CGAL::cpp11::get::value> (m_onmerge_functors); } /** Double link a dart with beta 0 to a second dart. * \em adart1 is 0-linked to \em adart2 and \em adart2 is 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. */ void basic_link_beta_0(Dart_handle adart1, Dart_handle adart2) { this->template dart_link_beta<0>(adart1, adart2); this->template dart_link_beta<1>(adart2, adart1); } /** Double link a dart with beta 0 to a second dart. * \em adart1 is 0-linked to \em adart2 and \em adart2 is 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. */ void basic_link_beta_1(Dart_handle adart1, Dart_handle adart2) { this->template dart_link_beta<1>(adart1, adart2); this->template dart_link_beta<0>(adart2, adart1); } /** 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. */ template void basic_link_beta_for_involution(Dart_handle adart1, Dart_handle adart2) { CGAL_assertion( i>=2 && i<=dimension ); this->template dart_link_beta(adart1, adart2); this->template dart_link_beta(adart2, adart1); } void basic_link_beta_for_involution(Dart_handle adart1, Dart_handle adart2, unsigned int i) { CGAL_assertion( i>=2 && i<=dimension ); CGAL_assertion( i>=2 && i<=dimension ); dart_link_beta(adart1, adart2, i); dart_link_beta(adart2, 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) { if ( i==0 ) basic_link_beta_0(adart1, adart2); else if ( i==1 ) basic_link_beta_1(adart1, adart2); else basic_link_beta_for_involution(adart1, adart2); } void basic_link_beta(Dart_handle adart1, Dart_handle adart2, unsigned int i) { if ( i==0 ) basic_link_beta_0(adart1, adart2); else if ( i==1 ) basic_link_beta_1(adart1, adart2); else basic_link_beta_for_involution(adart1, adart2, i); } /** Double link two darts, and update the NULL attributes. * \em adart1 is 0-linked to \em adart2 and \em adart2 is 1-linked * with \em adart1. The NULL attributes of \em adart1 are updated to * non NULL attributes associated to \em adart2, and vice-versa. * If both darts have an attribute, the attribute of adart1 is * associated to adart2. * 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. */ void link_beta_0(Dart_handle adart1, Dart_handle adart2) { Helper::template Foreach_enabled_attributes_except , 1>:: run(this,adart1,adart2); this->template dart_link_beta<0>(adart1, adart2); this->template dart_link_beta<1>(adart2, adart1); } /** Double link two darts, and update the NULL attributes. * \em adart1 is 1-linked to \em adart2 and \em adart2 is 0-linked * with \em adart1. The NULL attributes of \em adart1 are updated to * non NULL attributes associated to \em adart2, and vice-versa. * If both darts have an attribute, the attribute of adart1 is * associated to adart2. * 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. */ void link_beta_1(Dart_handle adart1, Dart_handle adart2) { Helper::template Foreach_enabled_attributes_except , 1>:: run(this,adart1,adart2); this->template dart_link_beta<1>(adart1, adart2); this->template dart_link_beta<0>(adart2, adart1); } /** 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. * If both darts have an attribute, the attribute of adart1 is * associated to adart2. * 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. */ template void link_beta_for_involution(Dart_handle adart1, Dart_handle adart2) { CGAL_assertion( 2<=i && i<=dimension ); Helper::template Foreach_enabled_attributes_except , i>:: run(this,adart1,adart2); this->template dart_link_beta(adart1, adart2); this->template dart_link_beta(adart2, adart1); } /** 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. * If both darts have an attribute, the attribute of adart1 is * associated to adart2. * 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) { if ( i==0 ) link_beta_0(adart1, adart2); else if ( i==1 ) link_beta_1(adart1, adart2); else link_beta_for_involution(adart1, adart2); } /** 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, * if both darts have an attribute, the attribute of adart1 is * associated to adart2 (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); } /** Double unlink a dart with beta 0. * 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. */ void unlink_beta_0(Dart_handle adart) { CGAL_assertion(!this->template is_free<0>(adart)); this->template dart_unlink_beta<1>(beta<0>(adart)); this->template dart_unlink_beta<0>(adart); } /** Double unlink a dart with beta 1. * beta1(\em adart) is 0-unlinked and \em adart is 1-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. */ void unlink_beta_1(Dart_handle adart) { CGAL_assertion(!this->template is_free<1>(adart)); this->template dart_unlink_beta<0>(beta<1>(adart)); this->template dart_unlink_beta<1>(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. */ template void unlink_beta_for_involution(Dart_handle adart) { CGAL_assertion(!this->template is_free(adart)); CGAL_assertion(2<=i && i<=dimension); this->template dart_unlink_beta(beta(adart)); this->template dart_unlink_beta(adart); } void unlink_beta_for_involution(Dart_handle adart, unsigned int i) { CGAL_assertion(!is_free(adart,i)); CGAL_assertion(2<=i && i<=dimension); dart_unlink_beta(beta(adart, i), i); dart_unlink_beta(adart, i); } /** Double unlink a dart with beta i. * betai(\em adart) is i-1-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. */ template void unlink_beta(Dart_handle adart) { if ( i==0 ) unlink_beta_0(adart); else if ( i==1 ) unlink_beta_1(adart); else unlink_beta_for_involution(adart); } void unlink_beta(Dart_handle adart, unsigned int i) { if ( i==0 ) unlink_beta_0(adart); else if ( i==1 ) unlink_beta_1(adart); else unlink_beta_for_involution(adart, i); } /** 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 CGAL::internal:: Is_sewable_functor::run(this, adart1, adart2); } /** Topological sew by beta1 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<1>(adart1, adart2). */ void topo_sew_1(Dart_handle adart1, Dart_handle adart2) { CGAL_assertion( (is_sewable<1>(adart1,adart2)) ); if ( adart1==adart2 ) { for ( CGAL::CMap_dart_iterator_of_involution it(*this, adart1); it.cont(); ++it ) { basic_link_beta_1(it, it); } } else { int m = get_new_mark(); std::deque dartv; for ( CGAL::CMap_dart_iterator_basic_of_cell it(*this, adart1, m); it.cont(); ++it ) { mark(it,m); dartv.push_back(it); } CGAL::CMap_dart_iterator_of_involution I1(*this, adart1); CGAL::CMap_dart_iterator_of_involution_inv I2(*this, adart2); for ( ; I1.cont(); ++I1, ++I2 ) { if ( is_marked(I1,m) ) basic_link_beta_1(I1, I2); else basic_link_beta_0(I1, I2); } for ( typename std::deque::iterator it=dartv.begin(); it!=dartv.end(); ++it) { unmark(*it,m); } CGAL_assertion( is_whole_map_unmarked(m) ); free_mark(m); } } /** Topological sew by beta0 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<0>(adart1, adart2). */ void topo_sew_0(Dart_handle adart1, Dart_handle adart2) { topo_sew_1(adart2, adart1); } /** Topological sew by betai 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 2<=i<=dimension. * @pre is_sewable(adart1, adart2). */ template void topo_sew_for_involution(Dart_handle adart1, Dart_handle adart2) { CGAL_assertion( 2<=i && i<=Self::dimension ); CGAL_assertion( (is_sewable(adart1,adart2)) ); CGAL::CMap_dart_iterator_of_involution I1(*this, adart1); CGAL::CMap_dart_iterator_of_involution_inv I2(*this, adart2); for ( ; I1.cont(); ++I1, ++I2 ) { basic_link_beta_for_involution(I1, I2); } } /** Topological sew by betai 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) { if ( i==0 ) topo_sew_1(adart2, adart1); else if ( i==1 ) topo_sew_1(adart1, adart2); else topo_sew_for_involution(adart1, adart2); } /** Sew by beta0 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<0>(adart1, adart2). * @post is_valid() */ void sew_0(Dart_handle adart1, Dart_handle adart2) { CGAL_assertion( (is_sewable<0>(adart1,adart2)) ); if ( adart1==adart2 ) { for ( CGAL::CMap_dart_iterator_of_involution it(*this, adart1); it.cont(); ++it ) { basic_link_beta_1(it, it); } return; } int m = get_new_mark(); std::deque dartv; for ( CGAL::CMap_dart_iterator_basic_of_cell it(*this, adart1, m); it.cont(); ++it ) { mark(it,m); dartv.push_back(it); } int mark = get_new_mark(); CGAL_assertion( mark!=-1 ); CGAL::CMap_dart_iterator_basic_of_involution I1(*this, adart1, mark); CGAL::CMap_dart_iterator_basic_of_involution_inv I2(*this, adart2, mark); // This first loop do not modify the map, but only the attributes // (by calling when required the onmerge functors). for ( ; I1.cont(); ++I1, ++I2 ) { if ( is_marked(I1,m) ) Helper::template Foreach_enabled_attributes_except , 1>:: run(this, I1, I2); else Helper::template Foreach_enabled_attributes_except , 1>:: run(this, I1, I2); } // Now we update the beta links. negate_mark( mark ); for ( I1.rewind(), I2.rewind(); I1.cont(); ++I1, ++I2 ) { if ( is_marked(I1,m) ) basic_link_beta_0(I1, I2); else basic_link_beta_1(I1, I2); } for ( typename std::deque::iterator it=dartv.begin(); it!=dartv.end(); ++it ) { unmark(*it,m); } CGAL_assertion( is_whole_map_unmarked(m) ); free_mark(m); negate_mark( mark ); CGAL_assertion( is_whole_map_unmarked(mark) ); free_mark(mark); } /** Sew by beta1 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<1>(adart1, adart2). * @post is_valid() */ void sew_1(Dart_handle adart1, Dart_handle adart2) { CGAL_assertion( (is_sewable<1>(adart1,adart2)) ); if ( adart1==adart2 ) { for ( CGAL::CMap_dart_iterator_of_involution it(*this, adart1); it.cont(); ++it ) { basic_link_beta_1(it, it); } return; } int m = get_new_mark(); std::deque dartv; for ( CGAL::CMap_dart_iterator_basic_of_cell it(*this, adart1, m); it.cont(); ++it ) { mark(it,m); dartv.push_back(it); } int mark = get_new_mark(); CGAL_assertion( mark!=-1 ); CGAL::CMap_dart_iterator_basic_of_involution I1(*this, adart1, mark); CGAL::CMap_dart_iterator_basic_of_involution_inv I2(*this, adart2, mark); // This first loop do not modify the map, but only the attributes // (by calling when required the onmerge functors). for ( ; I1.cont(); ++I1, ++I2 ) { CGAL_assertion( I2.cont() ); if ( is_marked(I1,m) ) Helper::template Foreach_enabled_attributes_except , 1>:: run(this, I1, I2); else Helper::template Foreach_enabled_attributes_except , 1>:: run(this, I1, I2); } // Now we update the beta links. negate_mark( mark ); for ( I1.rewind(), I2.rewind(); I1.cont(); ++I1, ++I2 ) { if ( is_marked(I1,m) ) basic_link_beta_1(I1, I2); else basic_link_beta_0(I1, I2); } for ( typename std::deque::iterator it=dartv.begin(); it!=dartv.end(); ++it ) { unmark(*it,m); } CGAL_assertion( is_whole_map_unmarked(m) ); free_mark(m); negate_mark( mark ); CGAL_assertion( is_whole_map_unmarked(mark) ); free_mark(mark); } /** 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). * @pre 2<=i<=dimension. * @post is_valid() */ template void sew_for_involution(Dart_handle adart1, Dart_handle adart2) { CGAL_assertion( 2<=i && i<=dimension ); CGAL_assertion( (is_sewable(adart1,adart2)) ); int mark=get_new_mark(); CGAL_assertion( mark!=-1 ); CGAL::CMap_dart_iterator_basic_of_involution I1(*this, adart1, mark); CGAL::CMap_dart_iterator_basic_of_involution_inv I2(*this, adart2, mark); // This first loop do not modify the map, but only the attributes // (by calling when required the onmerge functors). for ( ; I1.cont(); ++I1, ++I2 ) { Helper::template Foreach_enabled_attributes_except , i>:: run(this, I1, I2); } // Now we update the beta links. negate_mark( mark ); for ( I1.rewind(), I2.rewind(); I1.cont(); ++I1, ++I2 ) { basic_link_beta_for_involution(I1, I2); } negate_mark( mark ); CGAL_assertion( is_whole_map_unmarked(mark) ); free_mark(mark); } /** 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) { if ( i==0 ) sew_0(adart1, adart2); else if ( i==1 ) sew_1(adart1, adart2); else sew_for_involution(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 beta1 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(1). */ void topo_unsew_1(Dart_handle adart) { CGAL_assertion( !is_free<1>(adart) ); int m = get_new_mark(); std::deque dartv; for ( CGAL::CMap_dart_iterator_basic_of_cell it(*this, adart, m); it.cont(); ++it ) { mark(*it,m); dartv.push_back(*it); } for ( CGAL::CMap_dart_iterator_of_involution it(*this, adart); it.cont(); ++it ) { if ( is_marked(*it,m) ) unlink_beta_1(*it); else unlink_beta_0(*it); } for ( typename std::deque::iterator it=dartv.begin(); it!=dartv.end(); ++it ) { unmark(*it,m); } CGAL_assertion( is_whole_map_unmarked(m) ); free_mark(m); } /** Topological unsew by beta0 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(0). */ void topo_unsew_0(Dart_handle adart) { CGAL_assertion( !is_free<0>(adart) ); topo_unsew_1( adart->template beta<0>() ); } /** 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). * @pre 2<=i<=dimension. */ template void topo_unsew_for_involution(Dart_handle adart) { CGAL_assertion( !is_free(adart) ); CGAL_assertion( 2<=i && i<=Self::dimension ); for ( CGAL::CMap_dart_iterator_of_involution it(*this, adart); it.cont(); ++it ) { unlink_beta(*it); } } /** 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) { if ( i==0 ) topo_unsew_0(adart); else if ( i==1 ) topo_unsew_1(adart); else topo_unsew_for_involution(adart); } /** Unsew by beta0 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(0). * @post is_valid() */ void unsew_0(Dart_handle adart) { CGAL_assertion( !this->template is_free<0>(adart) ); int m=get_new_mark(); std::deque dartv; std::deque modified_darts; std::deque modified_darts2; for ( CGAL::CMap_dart_iterator_basic_of_cell it(*this, adart, m); it.cont(); ++it ) { mark(it, m); dartv.push_back(it); } for ( CGAL::CMap_dart_iterator_of_involution it(*this, adart); it.cont(); ++it ) { if ( is_marked(it, m) ) { modified_darts.push_back(it); modified_darts2.push_back(beta<0>(it)); unlink_beta_0(it); } else { modified_darts2.push_back(it); modified_darts.push_back(beta<1>(it)); unlink_beta_1(it); } } for ( typename std::deque::iterator it=dartv.begin(); it!=dartv.end(); ++it ) { unmark(*it,m); } CGAL_assertion( is_whole_map_unmarked(m) ); free_mark(m); // We test the split of all the incident cells for all the non // void attributes. Helper::template Foreach_enabled_attributes_except , 1>:: run(this, modified_darts, modified_darts2); } /** Unsew by beta1 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(1). * @post is_valid() */ void unsew_1(Dart_handle adart) { CGAL_assertion( !this->template is_free<1>(adart) ); int m = get_new_mark(); std::deque dartv; std::deque modified_darts; std::deque modified_darts2; for ( CGAL::CMap_dart_iterator_basic_of_cell it(*this, adart, m); it.cont(); ++it) { mark(it, m); dartv.push_back(it); } for ( CGAL::CMap_dart_iterator_of_involution it(*this, adart); it.cont(); ++it ) { if ( is_marked(it, m) ) { modified_darts2.push_back(it); modified_darts.push_back(beta<1>(it)); unlink_beta_1(it); } else { modified_darts.push_back(it); modified_darts2.push_back(beta<0>(it)); unlink_beta_0(it); } } for ( typename std::deque::iterator it=dartv.begin(); it!=dartv.end(); ++it) { unmark(*it, m); } CGAL_assertion( is_whole_map_unmarked(m) ); free_mark(m); // We test the split of all the incident cells for all the non // void attributes. Helper::template Foreach_enabled_attributes_except , 1>:: run(this, modified_darts, modified_darts2); } /** 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() * @pre 2<=i<=dimension */ template void unsew_for_involution(Dart_handle adart) { CGAL_assertion(2<=i && i<=Self::dimension); CGAL_assertion( !this->template is_free(adart) ); std::deque modified_darts; for ( CGAL::CMap_dart_iterator_of_involution it(*this, adart); it.cont(); ++it ) { modified_darts.push_back(it); modified_darts.push_back(beta(it)); unlink_beta_for_involution(it); } // We test the split of all the incident cells for all the non // void attributes. Helper::template Foreach_enabled_attributes_except , i>:: run(this, modified_darts); } /** 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) { if ( i==0 ) unsew_0(adart); else if ( i==1 ) unsew_1(adart); else unsew_for_involution(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); } /** Reverse the orientation (swap beta 0 & 1 links) of the entire map. * A valid map after this operation remains valid. * @param none * @return none */ void reverse_orientation() { internal::Reverse_orientation_of_map_functor::run(this); } /** Reverse the orientation (swap beta 0 & 1 links) of the connected * component containing the given dart. * A valid map after this operation remains valid. * @param adart handle to a dart * @return none */ void reverse_orientation_connected_component (Dart_handle adart) { internal::Reverse_orientation_of_connected_component_functor:: run(this, 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; 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; } /** Count the number of cells in each dimension. * @return a vector containing the number of cells. */ std::vector count_all_cells() const { std::vector dim(dimension+2); for ( unsigned int i=0; i & amarks) const { set_dart_marks(adart, 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_const_handle adart) const { return get_dart_marks(adart) ^ 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)amarkis_free(i)) unlink_beta(d, i); } erase_dart(d); ++res; } } return res; } #ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES //************************************************************************** // Dart_of_orbit_basic_range template struct Dart_of_orbit_basic_range : public CGAL::CMap_range , CGAL::CMap_dart_const_iterator_basic_of_orbit > { typedef CGAL::CMap_range , CGAL::CMap_dart_const_iterator_basic_of_orbit > Base; Dart_of_orbit_basic_range(Self &amap, Dart_handle adart, int amark=-1): Base(amap, adart, amark) {} }; //************************************************************************** // Dart_of_orbit_basic_const_range template struct Dart_of_orbit_basic_const_range : public CGAL::CMap_const_range > { typedef CGAL::CMap_const_range > Base; Dart_of_orbit_basic_const_range(const Self &amap, Dart_const_handle adart, int amark=-1): Base(amap, adart, amark) {} }; //************************************************************************** // Dart_of_orbit_range template struct Dart_of_orbit_range : public CGAL::CMap_range , CGAL::CMap_dart_const_iterator_of_orbit > { typedef CGAL::CMap_range , CGAL::CMap_dart_const_iterator_of_orbit > Base; Dart_of_orbit_range(Self &amap, Dart_handle adart) : Base(amap,adart) {} }; //************************************************************************** // Dart_of_orbit_const_range template struct Dart_of_orbit_const_range : public CGAL::CMap_const_range > { typedef CGAL::CMap_const_range > Base; Dart_of_orbit_const_range(const Self &amap, Dart_const_handle adart): Base(amap,adart) {} }; //************************************************************************** /// @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); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_range darts_of_orbit_basic(Dart_handle adart, int amark=-1) { return Dart_of_orbit_basic_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_const_range darts_of_orbit_basic(Dart_const_handle adart, int amark=-1) const { return Dart_of_orbit_basic_const_range(*this,adart,amark); } //************************************************************************** #else //************************************************************************** // Dart_of_orbit_basic_range template struct Dart_of_orbit_basic_range: public CGAL::CMap_range , CGAL::CMap_dart_const_iterator_basic_of_orbit > { typedef CGAL::CMap_range , CGAL::CMap_dart_const_iterator_basic_of_orbit > Base; Dart_of_orbit_basic_range(Self &amap, Dart_handle adart, int /*amark*/=-1): Base(amap, adart) {} }; //************************************************************************** // Dart_of_orbit_basic_const_range template struct Dart_of_orbit_basic_const_range: public CMap_const_range > { typedef CMap_const_range > Base; Dart_of_orbit_basic_const_range(const Self &amap, Dart_const_handle adart, int amark=-1): Base(amap, adart, amark) {} }; //************************************************************************** // Dart_of_orbit_range template struct Dart_of_orbit_range: public CGAL::CMap_range , CGAL::CMap_dart_const_iterator_of_orbit > { typedef CGAL::CMap_range , CGAL::CMap_dart_const_iterator_of_orbit > Base; Dart_of_orbit_range(Self &amap, Dart_handle adart): Base(amap, adart) {} }; //************************************************************************** // Dart_of_orbit_const_range template struct Dart_of_orbit_const_range: public CMap_const_range > { typedef CMap_const_range > Base; Dart_of_orbit_const_range(const Self &amap, Dart_const_handle adart): Base(amap, adart) {} }; //************************************************************************** /// @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); } //-------------------------------------------------------------------------- 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_handle adart) { 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_range darts_of_orbit(Dart_handle adart) { 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_range darts_of_orbit(Dart_handle adart) { 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_range darts_of_orbit (Dart_handle adart) { 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); } //-------------------------------------------------------------------------- // Const versions. 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_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_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_const_range darts_of_orbit (Dart_const_handle adart) const { return Dart_of_orbit_const_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_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_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_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_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_const_range darts_of_orbit(Dart_const_handle adart) const { return Dart_of_orbit_const_range (*this,adart); } //-------------------------------------------------------------------------- // Basic versions Dart_of_orbit_basic_range<> darts_of_orbit_basic(Dart_handle adart, int amark=-1) { return Dart_of_orbit_basic_range<>(*this,adart,amark); } //-------------------------------------------------------------------------- Dart_of_orbit_basic_const_range<> darts_of_orbit_basic (Dart_const_handle adart,int amark=-1) const { return Dart_of_orbit_basic_const_range<>(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_range darts_of_orbit_basic(Dart_handle adart, int amark=-1) { return Dart_of_orbit_basic_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_const_range darts_of_orbit_basic (Dart_const_handle adart, int amark=-1) const { return Dart_of_orbit_basic_const_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_range darts_of_orbit_basic(Dart_handle adart, int amark=-1) { return Dart_of_orbit_basic_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_const_range darts_of_orbit_basic (Dart_const_handle adart, int amark=-1) const { return Dart_of_orbit_basic_const_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_range darts_of_orbit_basic(Dart_handle adart, int amark=-1) { return Dart_of_orbit_basic_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_const_range darts_of_orbit_basic (Dart_const_handle adart, int amark=-1) const { return Dart_of_orbit_basic_const_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_range darts_of_orbit_basic (Dart_handle adart, int amark=-1) { return Dart_of_orbit_basic_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_const_range darts_of_orbit_basic(Dart_const_handle adart, int amark=-1) const { return Dart_of_orbit_basic_const_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_range darts_of_orbit_basic (Dart_handle adart, int amark=-1) { return Dart_of_orbit_basic_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_const_range darts_of_orbit_basic(Dart_const_handle adart, int amark=-1) const { return Dart_of_orbit_basic_const_range (*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_range darts_of_orbit_basic (Dart_handle adart, int amark=-1) { return Dart_of_orbit_basic_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_const_range darts_of_orbit_basic(Dart_const_handle adart, int amark=-1) const { return Dart_of_orbit_basic_const_range (*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_range darts_of_orbit_basic (Dart_handle adart, int amark=-1) { return Dart_of_orbit_basic_range (*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_const_range darts_of_orbit_basic(Dart_const_handle adart, int amark=-1) const { return Dart_of_orbit_basic_const_range (*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_range darts_of_orbit (Dart_handle adart, int amark=-1) { return Dart_of_orbit_basic_range (*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_const_range darts_of_orbit_basic(Dart_const_handle adart, int amark=-1) const { return Dart_of_orbit_basic_const_range (*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_range darts_of_orbit_basic(Dart_handle adart, int amark=-1) { return Dart_of_orbit_basic_range (*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_orbit_basic_const_range darts_of_orbit_basic(Dart_const_handle adart, int amark=-1) const { return Dart_of_orbit_basic_const_range (*this,adart,amark); } //************************************************************************** #endif //CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES //************************************************************************** // Dart_of_cell_basic_range template struct Dart_of_cell_basic_range: public CGAL::CMap_range , CGAL::CMap_dart_const_iterator_basic_of_cell > { typedef CGAL::CMap_range , CGAL::CMap_dart_const_iterator_basic_of_cell > Base; Dart_of_cell_basic_range(Self &amap, Dart_handle adart, int amark=-1) : Base(amap, adart, amark) {} }; //************************************************************************** // Dart_of_cell_basic_const_range template struct Dart_of_cell_basic_const_range: public CMap_const_range > { typedef CMap_const_range > Base; Dart_of_cell_basic_const_range(const Self &amap, Dart_const_handle adart, int amark=-1) : Base(amap, adart, amark) {} }; //************************************************************************** // Dart_of_cell_range template struct Dart_of_cell_range: public CGAL::CMap_range , CGAL::CMap_dart_const_iterator_of_cell > { typedef CGAL::CMap_range , CGAL::CMap_dart_const_iterator_of_cell > Base; Dart_of_cell_range(Self &amap, Dart_handle adart) : Base(amap, adart) {} }; //************************************************************************** // Dart_of_cell_const_range template struct Dart_of_cell_const_range: public CMap_const_range > { typedef CMap_const_range > Base; Dart_of_cell_const_range(const Self &amap, Dart_const_handle adart) : Base(amap, adart) {} }; //-------------------------------------------------------------------------- /// @return a range on all the darts of the given i-cell template Dart_of_cell_basic_range darts_of_cell_basic(Dart_handle adart, int amark=-1) { return Dart_of_cell_basic_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_cell_basic_const_range darts_of_cell_basic (Dart_const_handle adart, int amark=-1) const { return Dart_of_cell_basic_const_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_cell_basic_range darts_of_cell_basic(Dart_handle adart, int amark=-1) { return darts_of_cell_basic(adart,amark); } //-------------------------------------------------------------------------- template Dart_of_cell_basic_const_range darts_of_cell_basic(Dart_const_handle adart, int amark=-1) const { return darts_of_cell_basic(adart,amark); } //-------------------------------------------------------------------------- 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); } //************************************************************************** // Dart_of_involution_basic_range template struct Dart_of_involution_basic_range: public CGAL::CMap_range , CGAL::CMap_dart_const_iterator_basic_of_involution > { typedef CGAL::CMap_range , CGAL::CMap_dart_const_iterator_basic_of_involution > Base; Dart_of_involution_basic_range(Self &amap, Dart_handle adart, int amark=-1): Base(amap, adart, amark) {} }; //************************************************************************** // Dart_of_involution_basic_const_range template struct Dart_of_involution_basic_const_range: public CMap_const_range > { typedef CMap_const_range > Base; Dart_of_involution_basic_const_range(const Self &amap, Dart_const_handle adart, int amark=-1) : Base(amap, adart, amark) {} }; //************************************************************************** template Dart_of_involution_basic_range darts_of_involution_basic(Dart_handle adart, int amark=-1) { return Dart_of_involution_basic_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_involution_basic_const_range darts_of_involution_basic(Dart_const_handle adart, int amark=-1) const { return Dart_of_involution_basic_const_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_involution_basic_range darts_of_involution_basic(Dart_handle adart, int amark=-1) { return Dart_of_involution_basic_range (*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_involution_basic_const_range darts_of_involution_basic(Dart_const_handle adart, int amark=-1) const { return Dart_of_involution_basic_const_range (*this,adart,amark); } //************************************************************************** // Dart_of_involution_inv_basic_range template struct Dart_of_involution_inv_basic_range: public CGAL::CMap_range , CGAL::CMap_dart_const_iterator_basic_of_involution_inv > { typedef CGAL::CMap_range , CGAL::CMap_dart_const_iterator_basic_of_involution_inv > Base; Dart_of_involution_inv_basic_range(Self &amap, Dart_handle adart, int amark=-1): Base(amap, adart, amark) {} }; //************************************************************************** // Dart_of_involution_inv_basic_const_range template struct Dart_of_involution_inv_basic_const_range: public CMap_const_range > { typedef CMap_const_range > Base; Dart_of_involution_inv_basic_const_range(const Self &amap, Dart_const_handle adart, int amark=-1) : Base(amap, adart, amark) {} }; //************************************************************************** template Dart_of_involution_inv_basic_range darts_of_involution_inv_basic(Dart_handle adart, int amark=-1) { return Dart_of_involution_inv_basic_range(*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_involution_inv_basic_const_range darts_of_involution_inv_basic(Dart_const_handle adart, int amark=-1) const { return Dart_of_involution_inv_basic_const_range (*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_involution_inv_basic_range darts_of_involution_inv_basic(Dart_handle adart, int amark=-1) { return Dart_of_involution_inv_basic_range (*this,adart,amark); } //-------------------------------------------------------------------------- template Dart_of_involution_inv_basic_const_range darts_of_involution_inv_basic(Dart_const_handle adart, int amark=-1) const { return Dart_of_involution_inv_basic_const_range (*this,adart,amark); } //************************************************************************** // Dart_of_involution_range template struct Dart_of_involution_range: public CGAL::CMap_range , CGAL::CMap_dart_const_iterator_of_involution > { typedef CGAL::CMap_range , CGAL::CMap_dart_const_iterator_of_involution > Base; Dart_of_involution_range(Self &amap, Dart_handle adart) : Base(amap, adart) {} }; //************************************************************************** // Dart_of_involution_const_range template struct Dart_of_involution_const_range: public CMap_const_range > { typedef CMap_const_range > Base; Dart_of_involution_const_range(const Self &amap, Dart_const_handle adart): Base(amap, adart) {} }; //************************************************************************** template Dart_of_involution_range darts_of_involution(Dart_handle adart) { return Dart_of_involution_range(*this,adart); } //-------------------------------------------------------------------------- template Dart_of_involution_const_range darts_of_involution(Dart_const_handle adart) const { return Dart_of_involution_const_range(*this,adart); } //-------------------------------------------------------------------------- template Dart_of_involution_range darts_of_involution(Dart_handle adart) { return Dart_of_involution_range(*this,adart); } //-------------------------------------------------------------------------- template Dart_of_involution_const_range darts_of_involution(Dart_const_handle adart) const { return Dart_of_involution_const_range(*this,adart); } //************************************************************************** // Dart_of_involution_inv_range template struct Dart_of_involution_inv_range: public CGAL::CMap_range , CGAL::CMap_dart_const_iterator_of_involution_inv > { typedef CGAL::CMap_range , CGAL::CMap_dart_const_iterator_of_involution_inv > Base; Dart_of_involution_inv_range(Self &amap, Dart_handle adart) : Base(amap, adart) {} }; //************************************************************************** // Dart_of_involution_inv_const_range template struct Dart_of_involution_inv_const_range: public CMap_const_range > { typedef CMap_const_range > Base; Dart_of_involution_inv_const_range(const Self &amap, Dart_const_handle adart): Base(amap, adart) {} }; //************************************************************************** template Dart_of_involution_inv_range darts_of_involution_inv(Dart_handle adart) { return Dart_of_involution_inv_range(*this,adart); } //-------------------------------------------------------------------------- template Dart_of_involution_inv_const_range darts_of_involution_inv(Dart_const_handle adart) const { return Dart_of_involution_inv_const_range(*this,adart); } //-------------------------------------------------------------------------- template Dart_of_involution_inv_range darts_of_involution_inv(Dart_handle adart) { return Dart_of_involution_inv_range(*this,adart); } //-------------------------------------------------------------------------- template Dart_of_involution_inv_const_range darts_of_involution_inv(Dart_const_handle adart) const { return Dart_of_involution_inv_const_range (*this,adart); } //************************************************************************** // Dart_basic_range struct Dart_basic_range { typedef CGAL::CMap_dart_iterator_basic_of_all iterator; typedef CGAL::CMap_dart_const_iterator_basic_of_all const_iterator; Dart_basic_range(Self &amap) : mmap(amap) {} iterator begin() { return iterator(mmap); } iterator end() { return iterator(mmap,mmap.null_handle); } const_iterator begin() const { return const_iterator(mmap); } const_iterator end() const { return const_iterator(mmap,mmap.null_handle); } size_type size() { return mmap.number_of_darts(); } bool empty() const { return mmap.is_empty(); } private: Self & mmap; }; //************************************************************************** // Dart_basic_const_range struct Dart_basic_const_range { typedef CGAL::CMap_dart_const_iterator_basic_of_all const_iterator; Dart_basic_const_range(Self &amap) : mmap(amap) {} const_iterator begin() const { return const_iterator(mmap); } const_iterator end() const { return const_iterator(mmap,mmap.null_handle); } size_type size() const { return mmap.number_of_darts(); } bool empty() const { return mmap.is_empty(); } private: const Self & mmap; }; //************************************************************************** Dart_basic_range darts_basic() { return Dart_basic_range(*this); } //-------------------------------------------------------------------------- Dart_basic_const_range darts_basic() const { return Dart_basic_const_range(*this); } //************************************************************************** // One_dart_per_incident_cell_range template struct One_dart_per_incident_cell_range: public CGAL::CMap_range , CGAL::CMap_one_dart_per_incident_cell_const_iterator > { typedef CGAL::CMap_range , CGAL::CMap_one_dart_per_incident_cell_const_iterator > Base; One_dart_per_incident_cell_range(Self &amap, Dart_handle adart): Base(amap, adart) {} }; //************************************************************************** // One_dart_per_incident_cell_const_range template struct One_dart_per_incident_cell_const_range: public CMap_const_range > { typedef CMap_const_range > Base; One_dart_per_incident_cell_const_range(const Self &amap, Dart_const_handle adart) : Base(amap, adart) {} }; //************************************************************************** // One_dart_per_cell_range template struct One_dart_per_cell_range { typedef CGAL::CMap_one_dart_per_cell_iterator iterator; typedef CGAL::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,mmap.null_handle); } const_iterator begin() const { return const_iterator(mmap); } const_iterator end() const { return const_iterator(mmap,mmap.null_handle); } 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: Self & mmap; size_type msize; }; //************************************************************************** // One_dart_per_cell_const_range template struct One_dart_per_cell_const_range { typedef CGAL::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,mmap.null_handle); } 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; }; //************************************************************************** /// @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: /** Compute the dual of a Combinatorial_map. * @param amap the cmap in which we build the dual of this map. * @param adart a dart of the initial map, NULL by default. * @return adart of the dual map, the dual of adart if adart!=NULL, * any dart otherwise. * As soon as we don't modify this map and amap map, we can iterate * simultaneously through all the darts of the two maps and we have * each time of the iteration two "dual" darts. */ Dart_handle dual(Self& amap, Dart_handle adart=null_handle) { CGAL_assertion( is_without_boundary(dimension) ); CGAL::Unique_hash_map< Dart_handle, Dart_handle, typename Self::Hash_function > dual; Dart_handle d, d2, res = amap.null_handle; // We clear amap. TODO return a new amap ? amap.clear(); // We create a copy of all the dart of the map. for ( typename Dart_range::iterator it=darts().begin(); it!=darts().end(); ++it) { dual[it] = amap.create_dart(); if ( it==adart && res==amap.null_handle ) res = dual[it]; } // Then we link the darts by using the dual formula : // G(B,b1,b2,...,bn-1,bn) => // dual(G)=(B, b(n-1)obn, b(n-2)obn,...,b1obn, bn) // We suppose darts are run in the same order for both maps. typename Dart_range::iterator it2=amap.darts().begin(); for ( typename Dart_range::iterator it=darts().begin(); it!=darts().end(); ++it, ++it2) { d = it2; // The supposition on the order allows to avoid d=dual[it]; CGAL_assertion( it2==dual[it] ); // First case outside the loop since we need to use link_beta1 if ( amap.template is_free<1>(d) && beta(it)!=null_dart_handle ) amap.basic_link_beta_1(d, dual[beta(it)]); // and during the loop we use link_beta(d1,d2,i) for ( unsigned int i=dimension-2; i>=1; --i) { if ( amap.is_free(d,dimension-i) && beta(it, dimension, i)!=null_dart_handle ) amap.basic_link_beta(d, dual[beta(it, dimension, i)], dimension-i); } if ( amap.template is_free(d) ) { CGAL_assertion ( !this->template is_free(it) ); amap.basic_link_beta(d, dual[beta(it)], dimension); } } // CGAL_postcondition(amap2.is_valid()); if ( res==amap.null_handle ) res = amap.darts().begin(); return res; } /** Test if the connected component of cmap containing dart dh1 is * isomorphic to the connected component of map2 containing dart dh2, * starting from dh1 and dh2. * @param dh1 initial dart for this map * @param map2 the second combinatorial map * @param dh2 initial dart for map2 * @param testAttributes Boolean to test the equality of attributes (true) * or not (false) * @return true iff the cc of map is isomorphic to the cc of map2 starting * from dh1 and dh2; by testing the equality of attributes if * testAttributes is true */ template bool are_cc_isomorphic(Dart_const_handle dh1, const Combinatorial_map_base & map2, typename Combinatorial_map_base ::Dart_const_handle dh2, bool testAttributes=true) const { // CGAL_assertion(dimension==map2.dimension); typedef Combinatorial_map_base Map2; bool match = true; // Two stacks used to run through the two maps. std::deque< Dart_const_handle > toTreat1; std::deque< typename Map2::Dart_const_handle > toTreat2; int m1 = get_new_mark(); int m2 = map2.get_new_mark(); toTreat1.push_back(dh1); toTreat2.push_back(dh2); Dart_const_handle current; typename Map2::Dart_const_handle other; unsigned int i = 0; CGAL::Unique_hash_map bijection; if ( testAttributes ) { internal::Test_is_same_attribute_functor:: value = true; internal::Test_is_same_attribute_functor:: value = true; } while (match && !toTreat1.empty()) { // Next dart current = toTreat1.front(); toTreat1.pop_front(); other = toTreat2.front(); toTreat2.pop_front(); if (!is_marked(current, m1)) { if (map2.is_marked(other, m2)) match=false; else { bijection[current] = other; mark(current, m1); map2.mark(other, m2); if (testAttributes) { // We need to test in both direction because // Foreach_enabled_attributes only test non void attributes // of Self. Helper::template Foreach_enabled_attributes < internal::Test_is_same_attribute_functor >:: run(this,&map2,current, other); Map2::Helper::template Foreach_enabled_attributes < internal::Test_is_same_attribute_functor >:: run(&map2,this,other, current); if ( !internal::Test_is_same_attribute_functor:: value || !internal::Test_is_same_attribute_functor:: value ) match=false; } // We test if the injection is valid with its neighboors. // We go out as soon as it is not satisfied. for (i = 0; match && i <= dimension; ++i) { if ( i>map2.dimension ) { if (!is_free(current,i)) match=false; } else { if (is_free(current,i)) { if (!map2.is_free(other,i)) match = false; } else { if (map2.is_free(other,i)) match = false; else { if (is_marked(beta(current,i), m1) != map2.is_marked(map2.beta(other,i), m2)) match = false; else { if (!is_marked(beta(current,i), m1)) { toTreat1.push_back(beta(current,i)); toTreat2.push_back(map2.beta(other,i)); } else { if (bijection[beta(current,i)]!=map2.beta(other,i)) match = false; } } } } } } // Now we test if the second map has more beta links than the first for ( i=dimension+1; match && i<=map2.dimension; ++i ) { if (!map2.is_free(other,i)) match=false; } } } else { if (!map2.is_marked(other, m2)) match = false; } } // Here we test if both queue are empty if ( !toTreat1.empty() || !toTreat2.empty() ) match = false; // Here we unmark all the marked darts. toTreat1.clear(); toTreat2.clear(); toTreat1.push_back(dh1); toTreat2.push_back(dh2); while (!toTreat1.empty()) { current = toTreat1.front(); toTreat1.pop_front(); other = toTreat2.front(); toTreat2.pop_front(); unmark(current, m1); map2.unmark(other, m2); for (i = 0; match && i <= dimension; ++i) { if (!is_free(current,i) && is_marked(beta(current,i), m1)) { CGAL_assertion(!map2.is_free(other,i) && map2.is_marked(map2.beta(other,i), m2)); toTreat1.push_back(beta(current,i)); toTreat2.push_back(map2.beta(other,i)); } } } free_mark(m1); map2.free_mark(m2); return match; } /** Test if this cmap is isomorphic to map2. * @pre cmap is connected. * @param map2 the second combinatorial map * @param testAttributes Boolean to test the equality of attributes (true) * or not (false) * @return true iff this map is isomorphic to map2, testing the equality * of attributes if testAttributes is true */ template bool is_isomorphic_to(const Combinatorial_map_base & map2, bool testAttributes=true) { // if ( dimension!=map2.dimension ) return false; Dart_const_handle d1=darts().begin(); for (typename Combinatorial_map_base:: Dart_range::const_iterator it(map2.darts().begin()), itend(map2.darts().end()); it!=itend; ++it) { if (are_cc_isomorphic(d1, map2, it, testAttributes)) { return true; } } return false; } /** Test if the attributes of this map are automatically updated. * @return true iff the boolean automatic_attributes_management is set to true. */ bool are_attributes_automatically_managed() const { return automatic_attributes_management; } /** Sets the automatic_attributes_management boolean. */ void set_automatic_attributes_management(bool automatic_attributes_management) { if (this->automatic_attributes_management == false && automatic_attributes_management == true) { correct_invalid_attributes(); } this->automatic_attributes_management = automatic_attributes_management; } protected: /// Number of times each mark is reserved. 0 if the mark is free. mutable size_type mnb_times_reserved_marks[NB_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]; /// Automatic management of the attributes: true means attributes are allways maintained updated bool automatic_attributes_management; /// Tuple of unary and binary functors (for all non void attributes). typename Helper::Split_functors m_onsplit_functors; typename Helper::Merge_functors m_onmerge_functors; }; template < unsigned int d_, class Refs, class Items_, class Alloc_, class Storage_ > typename Combinatorial_map_base:: Base::Null_handle_type Combinatorial_map_base::null_handle = Combinatorial_map_base::Base::null_handle; template < unsigned int d_, class Items_=Combinatorial_map_min_items, class Alloc_=CGAL_ALLOCATOR(int), class Storage_= Combinatorial_map_storage_1 > class Combinatorial_map : public Combinatorial_map_base, Items_, Alloc_, Storage_ > { 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; Combinatorial_map() : Base() {} Combinatorial_map(const Self & amap) { Base::template copy(amap); } template < class CMap > Combinatorial_map(const CMap & amap) { Base::template copy(amap); } template < class CMap, typename Converters > Combinatorial_map(const CMap & amap, const Converters& converters) { Base::template copy (amap, converters); } template < class CMap, typename Converters, typename Pointconverter > Combinatorial_map(const CMap & amap, const Converters& converters, const Pointconverter& pointconverter) { Base::template copy (amap, converters, pointconverter); } }; } // namespace CGAL #endif // CGAL_COMBINATORIAL_MAP_H // // EOF //