From 599d700c656e2f14fd418d13ba16d9449d825110 Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Tue, 12 Feb 2013 17:34:25 +0100 Subject: [PATCH] Wip group/degroup and operations --- .../include/CGAL/Combinatorial_map.h | 578 +++++------ .../CGAL/Combinatorial_map_insertions.h | 633 ++++++++++++ .../CGAL/Combinatorial_map_iterators_base.h | 17 +- .../CGAL/Combinatorial_map_operations.h | 767 +------------- .../internal/Combinatorial_map_functors.h | 965 +++++++++--------- .../CGAL/internal/Combinatorial_map_sewable.h | 343 +++++++ .../CGAL/internal/Combinatorial_map_utility.h | 9 +- 7 files changed, 1742 insertions(+), 1570 deletions(-) create mode 100644 Combinatorial_map/include/CGAL/Combinatorial_map_insertions.h create mode 100644 Combinatorial_map/include/CGAL/internal/Combinatorial_map_sewable.h diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map.h b/Combinatorial_map/include/CGAL/Combinatorial_map.h index 9f2a64dabab..967638fec29 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map.h @@ -23,12 +23,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include @@ -96,11 +98,10 @@ namespace CGAL { template friend struct internal::Degroup_attribute_functor_run; - */ template friend struct internal::Degroup_one_attribute_functor; - + */ template friend struct internal::Test_is_valid_attribute_functor; @@ -179,7 +180,7 @@ namespace CGAL { this->mnb_used_marks = 0; this->mmask_marks.reset(); - for (size_type i = 0; i < NB_MARKS; ++i) + for ( size_type i = 0; i < NB_MARKS; ++i) { this->mfree_marks_stack[i] = (int)i; this->mindex_marks[i] = i; @@ -194,7 +195,7 @@ namespace CGAL { null_dart_handle = mnull_dart_container.emplace( std::bitset() ); - for (unsigned int i=0; i<=dimension; ++i) + for ( unsigned int i=0; i<=dimension; ++i) { null_dart_handle->unlink_beta(i); } @@ -209,7 +210,7 @@ namespace CGAL { void clear() { mdarts.clear(); - for (unsigned int i = 0; i < NB_MARKS; ++i) + for ( unsigned int i = 0; i < NB_MARKS; ++i) this->mnb_marked_darts[i] = 0; internal::Clear_all::run(mattribute_containers); @@ -278,7 +279,7 @@ namespace CGAL { void erase_dart(Dart_handle adart) { // 1) We update the number of marked darts. - for (unsigned int i = 0; i < mnb_used_marks; ++i) + 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]]; @@ -574,7 +575,7 @@ namespace CGAL { else { unmark_null_dart(amark); - for (typename Dart_range::const_iterator it(darts().begin()), + for ( typename Dart_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) unmark(it, amark); } @@ -618,7 +619,7 @@ namespace CGAL { bool is_without_boundary(unsigned int i) const { CGAL_assertion(1<=i && i<=dimension); - for (typename Dart_const_range::const_iterator it(darts().begin()), + for ( typename Dart_const_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) if (it->is_free(i)) return false; return true; @@ -629,9 +630,9 @@ namespace CGAL { */ bool is_without_boundary() const { - for (typename Dart_const_range::const_iterator it(darts().begin()), + for ( typename Dart_const_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) - for (unsigned int i = 1; i<=dimension; ++i) + for ( unsigned int i = 1; i<=dimension; ++i) if (it->is_free(i)) return false; return true; } @@ -647,7 +648,7 @@ namespace CGAL { unsigned int res = 0; Dart_handle d, d2; - for (typename Dart_range::iterator it(darts().begin()); + for ( typename Dart_range::iterator it(darts().begin()); it!=darts().end(); ++it) { if ( it->is_free(i) ) @@ -662,7 +663,7 @@ namespace CGAL { if ( !it->is_free(0) && !it->beta(0)->is_free(i) ) link_beta<0>(it->beta(0)->beta(i),d); // General case for 2...dimension - for (unsigned int j=2; j<=dimension; ++j) + for ( unsigned int j=2; j<=dimension; ++j) { if ( j+1!=i && j!=i && j!=i+1 && !it->is_free(j) && !it->beta(j)->is_free(i) ) @@ -692,19 +693,19 @@ namespace CGAL { bool valid = true; unsigned int i = 0, j = 0; std::vector marks(dimension+1); - for (i=0; i<=dimension; ++i) + 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()), + 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) + for ( i=0; i<=dimension; ++i) if (marks[i]!=-1) mark(it,marks[i]); } else @@ -720,7 +721,7 @@ namespace CGAL { } // Each beta(i>=2) must be an involution - for (i = 2; i <= dimension; ++i) + for ( i = 2; i <= dimension; ++i) if (!it->is_free(i) && it->beta(i)->beta(i)!=it) { std::cerr << "Map not valid: beta(" << i @@ -732,7 +733,7 @@ namespace CGAL { // beta1 o betai and beta0 o betai (i>=3) must be involutions if (!it->is_free(0)) { - for (i = 3; i <= dimension; ++i) + for ( i = 3; i <= dimension; ++i) if ((it->is_free(i) != it->beta(0)->is_free(i)) || (!it->is_free(i) && it->beta(0)->beta(i)!=it->beta(i)->beta(1))) @@ -745,7 +746,7 @@ namespace CGAL { } if (!it->is_free(1)) { - for (i = 3; i <= dimension; ++i) + for ( i = 3; i <= dimension; ++i) if ((it->is_free(i) != it->beta(1)->is_free(i)) || (!it->is_free(i) && it->beta(1)->beta(i)!=it->beta(i)->beta(0))) @@ -758,11 +759,11 @@ namespace CGAL { } // beta(i>=2) o beta(j>=i+2) must be an involution - for (i = 2; i <= dimension; ++i) + for ( i = 2; i <= dimension; ++i) { if (!it->is_free(i)) { - for (j = i + 2; j <= dimension; ++j) + for ( j = i + 2; j <= dimension; ++j) if ((it->is_free(j)!=it->beta(i)->is_free(j)) || (!it->is_free(j) && it->beta(i)->beta(j)!=it->beta(j)->beta(i))) @@ -780,7 +781,7 @@ namespace CGAL { run(this,it,&marks,&valid); } } - for (i=0; i<=dimension; ++i) + for ( i=0; i<=dimension; ++i) if ( marks[i]!=-1 ) { CGAL_assertion( is_whole_map_marked(marks[i]) ); @@ -808,11 +809,11 @@ namespace CGAL { std::ostream& display_darts(std::ostream & os) const { unsigned int nb = 0; - for (typename Dart_range::const_iterator it=darts().begin(); + 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) + for ( unsigned int i=0; i<=dimension; ++i) { os << &(*it->beta(i)) << ",\t"; if (it->is_free(i))os << "\t"; @@ -836,7 +837,7 @@ namespace CGAL { Tag_true>::value) ); unsigned int nb = 0; int amark = get_new_mark(); - for (typename Dart_range::const_iterator it1(darts().begin()), + for ( typename Dart_range::const_iterator it1(darts().begin()), itend(darts().end()); it1!=itend; ++it1) { if ( !is_marked(it1, amark) ) @@ -874,13 +875,13 @@ namespace CGAL { std::ostream& display_characteristics(std::ostream & os) const { std::vector cells(dimension+2); - for (unsigned int i=0; i<=dimension+1; ++i) + 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) + for ( unsigned int i=0; i<=dimension; ++i) os<<", #"<is_free(j)!=I2->is_free(j) ) - { - res = false; - } - } - ++I1; ++I2; - } - if (I1.cont() != I2.cont()) - res = false; - - return res; - } - - /** Test if it is possible to sew by beta0 the two given darts - * @param adart1 the first dart. - * @param adart2 the second dart. - * @return true iff \em adart1 can be 0-sewn with \em adart2. - */ - bool is_sewable_0(Dart_const_handle adart1, Dart_const_handle adart2) const - { return is_sewable_1(adart2, adart1); } - - /** Test if it is possible to sew by betai the two given darts - * for 2<=i<=dimension. - * @param adart1 the first dart. - * @param adart2 the second dart. - * @return true iff \em adart1 can be 1-sewn with \em adart2. - */ - template - bool is_sewable_for_involution(Dart_const_handle adart1, - Dart_const_handle adart2) const - { - CGAL_assertion(2<=i && i<=Self::dimension); - CGAL_assertion(adart1!=NULL && adart2!=NULL); - - if ( !adart1->is_free(i) || !adart2->is_free(i) || adart1==adart2 ) - return false; - - CMap_dart_const_iterator_of_involution I1(*this, adart1); - CMap_dart_const_iterator_of_involution_inv I2(*this, adart2); - bool res = true; - while (res && I1.cont() && I2.cont()) - { - // We can remove this constraint which is not required for - // combinatorial map definition, but which is quite "normal" - if ( I1==adart2 || I2==adart1 ) res=false; - - // Special case to consider beta0 and beta1 - if ( i>2 ) - { - if ( I1->is_free(0)!=I2->is_free(1) ) res = false; - else if ( I1->is_free(1)!=I2->is_free(0) ) res = false; - } - - // General case - for (unsigned int j=2;res && j<=Self::dimension; ++j) - { - if ( j+1!=i && j!=i && j!=i+1 && - I1->is_free(j)!=I2->is_free(j) ) - { res = false; } - } - ++I1; ++I2; - } - if (I1.cont() != I2.cont()) - res = false; - - return res; - } - /** Test if it is possible to sew by betai the two given darts * @param adart1 the first dart. * @param adart2 the second dart. @@ -1402,9 +1309,8 @@ namespace CGAL { template bool is_sewable(Dart_const_handle adart1, Dart_const_handle adart2) const { - if ( i==0 ) return is_sewable_0(adart1, adart2); - else if ( i==1 ) return is_sewable_1(adart1, adart2); - else return is_sewable_for_involution(adart1, adart2); + return CGAL::internal:: + Is_sewable_functor::run(this, adart1, adart2); } /** Topological sew by beta1 the two given darts plus all the required darts @@ -1412,15 +1318,15 @@ namespace CGAL { * thus the map can be non valid. * @param adart1 the first dart. * @param adart2 the second dart. - * @pre is_sewable_1(adart1, adart2). + * @pre is_sewable<1>(adart1, adart2). */ void topo_sew_1(Dart_handle adart1, Dart_handle adart2) { - CGAL_assertion( (is_sewable_1(adart1,adart2)) ); + CGAL_assertion( (is_sewable<1>(adart1,adart2)) ); int m = get_new_mark(); std::deque dartv; - for (CMap_dart_iterator_basic_of_cell it(*this,adart1,m); + for ( CMap_dart_iterator_basic_of_cell it(*this,adart1,m); it.cont(); ++it) { mark(it,m); @@ -1429,15 +1335,14 @@ namespace CGAL { CMap_dart_iterator_of_involution I1(*this, adart1); CMap_dart_iterator_of_involution_inv I2(*this, adart2); - while ( I1.cont() ) + for ( ; I1.cont(); ++I1, ++I2 ) { if ( is_marked(I1,m) ) basic_link_beta_1(I1, I2); else basic_link_beta_0(I1, I2); - ++I1; ++I2; } - for (typename std::deque::iterator - it=dartv.begin(); it!=dartv.end(); ++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); @@ -1448,7 +1353,7 @@ namespace CGAL { * thus the map can be non valid. * @param adart1 the first dart. * @param adart2 the second dart. - * @pre is_sewable_0(adart1, adart2). + * @pre is_sewable<0>(adart1, adart2). */ void topo_sew_0(Dart_handle adart1, Dart_handle adart2) { topo_sew_1(adart2, adart1); } @@ -1459,20 +1364,19 @@ namespace CGAL { * @param adart1 the first dart. * @param adart2 the second dart. * @pre 2<=i<=dimension. - * @pre is_sewable_for_involution(adart1, adart2). + * @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_for_involution(adart1,adart2)) ); + CGAL_assertion( 2<=i && i<=Self::dimension ); + CGAL_assertion( (is_sewable(adart1,adart2)) ); - CMap_dart_iterator_of_involution I1(*this, adart1); + CMap_dart_iterator_of_involution I1(*this, adart1); CMap_dart_iterator_of_involution_inv I2(*this, adart2); - while ( I1.cont() ) + for ( ; I1.cont(); ++I1, ++I2 ) { basic_link_beta_for_involution(I1, I2); - ++I1; ++I2; } } @@ -1486,7 +1390,7 @@ namespace CGAL { template void topo_sew(Dart_handle adart1, Dart_handle adart2) { - if ( i==0 ) topo_sew_0(adart1, 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); } @@ -1496,48 +1400,67 @@ namespace CGAL { * 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). + * @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)) ); + CGAL_assertion( (is_sewable<0>(adart1,adart2)) ); int m = get_new_mark(); - std::vector dartv; - for (CMap_dart_iterator_basic_of_cell it(*this,adart1,m); + std::deque dartv; + for ( CMap_dart_iterator_basic_of_cell it(*this,adart1,m); it.cont(); ++it) { mark(it,m); dartv.push_back(it); } - CMap_dart_iterator_of_involution I1(*this, adart1); - CMap_dart_iterator_of_involution_inv I2(*this, adart2); - while ( I1.cont() ) - { - Dart_handle od1=I1->other_extremity(); - Dart_handle od2=I2->other_extremity(); - /*if (od1!=NULL && od2!=NULL) TODO - group_all_attributes_except(od1, od2, 1);*/ - ++I1; ++I2; - } + int mark = get_new_mark(); + CGAL_assertion( mark!=-1 ); - I1.rewind(); I2.rewind(); - while ( I1.cont() ) + CMap_dart_iterator_basic_of_involution + I1(*this, adart1, mark); + 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) ) - basic_link_beta_0(I1, I2); + Helper::template Foreach_enabled_attributes_except + , 1>:: + run(this, I1, I2); else - basic_link_beta_1(I1, I2); - ++I1; ++I2; + Helper::template Foreach_enabled_attributes_except + , 1>:: + run(this, I1, I2); + + /* TODO check AVANT Dart_handle od1=I1->other_extremity(); + Dart_handle od2=I2->other_extremity(); + if (od1!=NULL && od2!=NULL) + run(this,adart1,adart2); + group_all_attributes_except(od1, od2, 1);*/ } - for (typename std::vector::iterator - it=dartv.begin(); it!=dartv.end(); ++it) + // 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 @@ -1545,44 +1468,61 @@ namespace CGAL { * 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). + * @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)) ); + CGAL_assertion( (is_sewable<1>(adart1,adart2)) ); int m = get_new_mark(); - std::vector dartv; - for (CMap_dart_iterator_basic_of_cell it(*this,adart1,m); - it.cont(); ++it) + std::deque dartv; + for ( CMap_dart_iterator_basic_of_cell it(*this,adart1,m); + it.cont(); ++it ) { mark(it,m); dartv.push_back(it); } - CMap_dart_iterator_of_involution I1(*this, adart1); - CMap_dart_iterator_of_involution_inv I2(*this, adart2); - while ( I1.cont() ) - { - // TODO group_all_attributes_except(I1,I2,1); - ++I1; ++I2; - } + int mark = get_new_mark(); + CGAL_assertion( mark!=-1 ); - I1.rewind(); I2.rewind(); - while ( I1.cont() ) + CMap_dart_iterator_basic_of_involution + I1(*this, adart1, mark); + 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) ) - basic_link_beta_1(I1, I2); + Helper::template Foreach_enabled_attributes_except + , 1>:: + run(this, I1, I2); else - basic_link_beta_0(I1, I2); - ++I1; ++I2; + Helper::template Foreach_enabled_attributes_except + , 1>:: + run(this, I1, I2); + // TODO check avant group_all_attributes_except(I1,I2,1); } - for (typename std::vector::iterator - it=dartv.begin(); it!=dartv.end(); ++it) + // 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 @@ -1597,8 +1537,8 @@ namespace CGAL { template void sew_for_involution(Dart_handle adart1, Dart_handle adart2) { - CGAL_assertion(2<=i && i<=dimension); - CGAL_assertion( (is_sewable_for_involution(adart1,adart2)) ); + CGAL_assertion( 2<=i && i<=dimension ); + CGAL_assertion( (is_sewable(adart1,adart2)) ); int mark = get_new_mark(); CGAL_assertion( mark!=-1 ); @@ -1608,18 +1548,21 @@ namespace CGAL { CMap_dart_iterator_basic_of_involution_inv I2(*this, adart2, mark); - while ( I1.cont() ) + // This first loop do not modify the map, but only the attributes + // (by calling when required the onmerge functors). + for ( ; I1.cont(); ++I1, ++I2 ) { - // TODO group_all_attributes_except(I1,I2,i); - ++I1; ++I2; + Helper::template Foreach_enabled_attributes_except + , i>:: + run(this, I1, I2); + // TODO avant group_all_attributes_except(I1,I2,i); } + // Now we update the beta links. negate_mark( mark ); - I1.rewind(); I2.rewind(); - while ( I1.cont() ) + for ( I1.rewind(), I2.rewind(); I1.cont(); ++I1, ++I2 ) { - basic_link_beta_for_involution(I1, I2, i); - ++I1; ++I2; + basic_link_beta_for_involution(I1, I2); } negate_mark( mark ); @@ -1666,29 +1609,26 @@ namespace CGAL { */ void topo_unsew_1(Dart_handle adart) { - CGAL_assertion( adart!=NULL && !adart->is_free(1) ); + CGAL_assertion( adart!=NULL && !adart->template is_free<1>() ); int m = get_new_mark(); - std::vector dartv; - for (CMap_dart_iterator_basic_of_cell it(*this,adart,m); + std::deque dartv; + for ( CMap_dart_iterator_basic_of_cell it(*this,adart,m); it.cont(); ++it) { mark(*it,m); dartv.push_back(*it); } + for ( CMap_dart_iterator_of_involution it(*this, adart); + it.cont(); ++it ) { - CMap_dart_iterator_of_involution it(*this, adart); - while ( it.cont() ) - { - if ( is_marked(*it,m) ) basic_unlink_beta_1(*it); - else basic_unlink_beta_0(*it); - ++it; - } + if ( is_marked(*it,m) ) unlink_beta_1(*it); + else unlink_beta_0(*it); } - for (typename std::vector::iterator - it=dartv.begin(); it!=dartv.end(); ++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); @@ -1702,8 +1642,8 @@ namespace CGAL { */ void topo_unsew_0(Dart_handle adart) { - CGAL_assertion( adart!=NULL && !adart->is_free(0) ); - topo_unsew_1(adart->beta(0)); + CGAL_assertion( adart!=NULL && !adart->template is_free<0>() ); + topo_unsew_1( adart->template beta<0>() ); } /** Topological unsew by betai the given dart plus all the required darts @@ -1716,15 +1656,12 @@ namespace CGAL { template void topo_unsew_for_involution(Dart_handle adart) { - CGAL_assertion( adart!=NULL && !adart->is_free(i) ); - CGAL_assertion(2<=i && i<=Self::dimension); + CGAL_assertion( adart!=NULL && !adart->template is_free() ); + CGAL_assertion( 2<=i && i<=Self::dimension ); - CMap_dart_iterator_of_involution it(*this, adart); - while ( it.cont() ) - { - unlink_beta(*it, i); - ++it; - } + for ( 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 @@ -1750,49 +1687,50 @@ namespace CGAL { */ void unsew_0(Dart_handle adart) { - CGAL_assertion( adart!=NULL && !adart->is_free(0) ); - Dart_handle d2 = NULL; + CGAL_assertion( adart!=NULL && !adart->template is_free<0>() ); + Dart_handle d2=NULL; - int m = get_new_mark(); - std::vector dartv; - for (CMap_dart_iterator_basic_of_cell it(*this,adart,m); + int m=get_new_mark(); + std::deque dartv; + std::deque modified_darts; + + for ( CMap_dart_iterator_basic_of_cell it(*this, adart, m); it.cont(); ++it) { - mark(it,m); + mark(it, m); dartv.push_back(it); } + for ( CMap_dart_iterator_of_involution it(*this, adart); + it.cont(); ++it ) { - CMap_dart_iterator_of_involution it(*this, adart); - while ( it.cont() ) + if ( is_marked(it, m) ) { - if ( is_marked(it,m) ) - { - d2 = it->beta(0); - unlink_beta_0(it); - } - else - { - d2 = it->beta(1); - unlink_beta_1(it); - } - - // TODO do the degroup after the loop (cf unsew_for_involution) - Dart_handle od1=it->other_extremity(); - Dart_handle od2=d2->other_extremity(); - /* TODO if ( od1!=NULL && od2!=NULL ) - degroup_all_attributes_except(od1,od2,1); */ - - ++it; + modified_darts.push_back(it); + modified_darts.push_back(it->template beta<0>()); + unlink_beta_0(it); + } + else + { + modified_darts.push_back(it); + modified_darts.push_back(it->template beta<1>()); + unlink_beta_1(it); } } - for (typename std::vector::iterator - it=dartv.begin(); it!=dartv.end(); ++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); + + // TODO pass the mark m to know which dart is modified by b0 of b1 + // 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); } /** Unsew by beta1 the given dart plus all the required darts @@ -1808,33 +1746,45 @@ namespace CGAL { Dart_handle d2 = NULL; int m = get_new_mark(); - std::vector dartv; - for (CMap_dart_iterator_basic_of_cell it(*this,adart,m); + std::deque dartv; + std::deque modified_darts; + + for ( CMap_dart_iterator_basic_of_cell it(*this,adart,m); it.cont(); ++it) { mark(it,m); dartv.push_back(it); } + for ( CMap_dart_iterator_of_involution it(*this, adart); + it.cont(); ++it ) { - CMap_dart_iterator_of_involution it(*this, adart); - while ( it.cont() ) + if ( is_marked(it, m) ) { - if ( is_marked(it,m) ) - { d2 = it->beta(1); unlink_beta_1(it); } - else - { d2 = it->beta(0); unlink_beta_0(it); } - // TODO do the degroup after the loop (cf unsew_for_involution) - // TODO degroup_all_attributes_except(it,d2,1); - ++it; + modified_darts.push_back(it); + modified_darts.push_back(it->template beta<1>()); + unlink_beta_1(it); + } + else + { + modified_darts.push_back(it); + modified_darts.push_back(it->template beta<0>()); + unlink_beta_0(it); } } - for (typename std::vector::iterator + 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); + + // TODO pass the mark m to know which dart is modified by b0 of b1 + // 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); } /** Unsew by betai the given dart plus all the required darts @@ -1851,23 +1801,22 @@ namespace CGAL { CGAL_assertion(2<=i && i<=Self::dimension); CGAL_assertion( adart!=NULL && !adart->is_free(i) ); - std::stack > todegroup; + std::deque modified_darts; - CMap_dart_iterator_of_involution it(*this, adart); - while ( it.cont() ) + for ( CMap_dart_iterator_of_involution it(*this, adart); + it.cont(); ++it ) { - todegroup.push(internal::Couple_dart_and_dim - (it,it->beta(i),i)); - unlink_beta_for_involution(it,i); + modified_darts.push_back(it); + modified_darts.push_back(it->template beta()); + unlink_beta_for_involution(it); ++it; } - while (!todegroup.empty() ) - { - internal::Couple_dart_and_dim c=todegroup.top(); - todegroup.pop(); - // TODO degroup_all_attributes_except(c.d1,c.d2,c.dim); - } + // 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 @@ -1911,14 +1860,14 @@ namespace CGAL { std::vector marks(dimension+2); // Initialization of the result - for (unsigned int i=0; i tounmark; - for (unsigned int i=0; i 0 ) { - for (typename Dart_range::const_iterator it(darts().begin()), + for ( typename Dart_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) { - for (unsigned int i=0; i dim(dimension+2); - for (unsigned int i=0; itemplate attribute()->dart(),amark) ) return; - for (CMap_dart_iterator_of_cell it(*this, ah); it.cont(); ++it) + for ( CMap_dart_iterator_of_cell it(*this, ah); it.cont(); ++it) { if (!is_marked(it,amark)) { @@ -2095,54 +2044,6 @@ namespace CGAL { >::run(this,ah,amark); } - /** Degroup the i-cell attribute of the two given darts, if required. - * If the two darts are incident to the same attribute and do not belong to - * the same i-cell, we create a new attibute and link each dart - * belonging to the i-cell of adart2 onto this new attribute. - * The new attribute is initialized by copying the old one then by using - * the functor On_split from the original attribute. - * @param adart1 the first dart. - * @param adart2 the second dart. - * @return true iff the attribute is split. - */ - template - bool degroup_enabled_attribute(Dart_handle adart1, Dart_handle adart2) - { - CGAL_static_assertion(i<=dimension); - CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, - "degroup_enabled_attribute but " - "i-attributes are disabled"); - CGAL_assertion(adart1 != NULL && adart2 != NULL); - CGAL_assertion(adart1 != null_dart_handle && adart2 != null_dart_handle); - - typename Attribute_handle::type a1=adart1->template attribute(); - typename Attribute_handle::type a2=NULL; - - // If the two attributes are not equal, nothing to do. - if ( a1 != adart2->template attribute() || a1 == NULL) return false; - - // TODO improve this step: use basic iterator to iterate through cell(adart2) - // If the two darts belong to the same cell, nothing to do. - if ( belong_to_same_cell(*this, adart1, adart2) ) - return false; - - // Here we create a new attribute - a2 = create_attribute(*a1); - - // We call the on_split functor - internal::Apply_cell_functor::run(*a1,*a2); - - // We set the dart of the cell a1 onto adart1. - a1->set_dart(adart1); - - // and reuse the basic iterator here to unmark. - // And we set all the dart of the cell of adart2 to v1. - set_attribute(adart2, a2); - - return true; - } - /** Test the validity of a i-cell-attribute. * ie all the darts belonging to a i-cell are linked to the same attribute. * @param adart a dart. @@ -2164,7 +2065,7 @@ namespace CGAL { a=adart->template attribute(); unsigned int nb = 0; - for (CMap_dart_const_iterator_basic_of_cell + for ( CMap_dart_const_iterator_basic_of_cell it(*this,adart,amark); it.cont(); ++it) { if ( it->template attribute() != a ) @@ -2212,13 +2113,13 @@ namespace CGAL { { unsigned int res = 0, i = 0; Dart_handle d; - for (typename Dart_range::iterator it(darts().begin()), + for ( typename Dart_range::iterator it(darts().begin()), itend(darts().end()); it!=itend; ) { d = it++; if (is_marked(d, amark)) { - for (i = 0; i <= dimension; ++i) + for ( i = 0; i <= dimension; ++i) { if (!d->is_free(i)) unlink_beta(d, i); } erase_dart(d); ++res; } @@ -3066,7 +2967,8 @@ namespace CGAL { "set_attribute_of_dart but " "i-attributes are disabled"); CGAL_assertion( adart!=NULL && adart!=null_dart_handle && ah!=NULL ); - CGAL_assertion( adart->template attribute()!=ah ); + + if ( adart->template attribute()==ah ) return; decrease_attribute_ref_counting(adart); adart->template set_attribute(ah); @@ -3076,7 +2978,7 @@ namespace CGAL { public: - /** Set the i-attribute of all the darts of a given range. + /** Set the i-attribute of all the darts of a given i-cell. * @param adart a starting dart. * @param ah an handle to the i-attribute to set. */ @@ -3088,7 +2990,7 @@ namespace CGAL { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "set_attribute but i-attributes are disabled"); CGAL_assertion( adart!=NULL && adart!=null_dart_handle && ah!=NULL ); - for (typename Dart_of_cell_range::iterator it(*this, adart); + for ( typename Dart_of_cell_range::iterator it(*this, adart); it.cont(); ++it) { if ( it->template attribute()!=ah ) @@ -3099,6 +3001,10 @@ namespace CGAL { } ah->set_dart(adart); } + /** Set the i-attribute of all the darts of a given range. + * @param adart a starting dart. + * @param ah an handle to the i-attribute to set. + */ template void set_attribute(Dart_handle adart, typename Attribute_handle::type ah) @@ -3107,7 +3013,7 @@ namespace CGAL { CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "set_attribute but i-attributes are disabled"); CGAL_assertion( adart!=NULL && adart!=null_dart_handle && ah!=NULL ); - for (typename Range::iterator it(*this, adart); it.cont(); ++it) + for ( typename Range::iterator it(*this, adart); it.cont(); ++it) { if ( it->template attribute()!=ah ) { @@ -3139,7 +3045,7 @@ namespace CGAL { amap.clear(); // We create a copy of all the dart of the map. - for (typename Dart_range::iterator it=darts().begin(); it!=darts().end(); + for ( typename Dart_range::iterator it=darts().begin(); it!=darts().end(); ++it) { dual[it] = amap.create_dart(); @@ -3151,7 +3057,7 @@ namespace CGAL { // 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(); + 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]; @@ -3164,7 +3070,7 @@ namespace CGAL { dual[it->beta(dimension)->beta(dimension-1)]); // and during the loop we use link_beta(d1,d2,i) - for (unsigned int i=dimension-2; i>=1; --i) + for ( unsigned int i=dimension-2; i>=1; --i) { if ( d->is_free(dimension-i) && it->beta(dimension)->beta(i)!=null_dart_handle ) diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map_insertions.h b/Combinatorial_map/include/CGAL/Combinatorial_map_insertions.h new file mode 100644 index 00000000000..2fb52811ac2 --- /dev/null +++ b/Combinatorial_map/include/CGAL/Combinatorial_map_insertions.h @@ -0,0 +1,633 @@ +#ifndef CGAL_COMBINATORIAL_MAP_INSERTIONS_H +#define CGAL_COMBINATORIAL_MAP_INSERTIONS_H + +namespace CGAL { +/** @file Combinatorial_map_insertions.h + * Insertion operations on combinatorial map. + */ + +/** Insert a vertex in a given edge. + * @param amap the used combinatorial map. + * @param adart a dart of the edge (!=NULL && !=null_dart_handle). + * @return a dart of the new vertex. + */ +template +typename CMap::Dart_handle +insert_cell_0_in_cell_1(CMap& amap, typename CMap::Dart_handle adart) +{ + CGAL_assertion(adart != NULL && adart!=CMap::null_dart_handle); + + typename CMap::Dart_handle d1, d2; + int mark = amap.get_new_mark(); + + // 1) We store all the darts of the edge. + std::deque vect; + { + for ( typename CMap::template Dart_of_cell_range<1>::iterator it= + amap.template darts_of_cell<1>(adart).begin(); + it != amap.template darts_of_cell<1>(adart).end(); ++it ) + vect.push_back(it); + } + + // 2) For each dart of the cell, we modify link of neighbors. + typename std::deque::iterator it = vect.begin(); + for (; it != vect.end(); ++it) + { + d1 = amap.create_dart(); + + if (!(*it)->is_free(1)) + { amap.basic_link_beta_1(d1, (*it)->beta(1)); } + + for ( unsigned int dim=2; dim<=CMap::dimension; ++dim ) + { + if (!(*it)->is_free(dim) && amap.is_marked((*it)->beta(dim), mark)) + { + amap.basic_link_beta_for_involution((*it)->beta(dim), d1, dim); + amap.basic_link_beta_for_involution(*it, (*it)->beta(dim)-> + template beta<1>(), dim); + } + } + + amap.template link_beta_1(*it, d1); + // TODO remove this group, and use link_beta instead ? + //amap.group_all_dart_attributes_except(*it, d1, 1); + + amap.mark(*it, mark); + } + + for (it = vect.begin(); it != vect.end(); ++it) + { amap.unmark(*it, mark); } + + amap.free_mark(mark); + + internal::Degroup_attribute_functor_run:: + run(&amap, adart, adart->beta(1)); + + // CGAL_expensive_postcondition( amap.is_valid() ); + + return adart->beta(1); +} + +/** Insert a vertex in the given 2-cell which is splitted in triangles, + * once for each inital edge of the facet. + * @param amap the used combinatorial map. + * @param adart a dart of the facet to triangulate. + * @return A dart incident to the new vertex. + */ +// TODO revoir toute la gestion des attributs +// (utilisation correcte des link avec/sans la maj) +template < class CMap > +typename CMap::Dart_handle +insert_cell_0_in_cell_2(CMap& amap, typename CMap::Dart_handle adart) +{ + CGAL_assertion(adart != NULL && adart!=CMap::null_dart_handle); + + typename CMap::Dart_handle first = adart, prev = NULL, cur = NULL; + typename CMap::Dart_handle n1 = NULL, n2 = NULL; + + typename CMap::Dart_handle nn1 = NULL, nn2 = NULL; + + // If the facet is open, we search the dart 0-free + while (!first->is_free(0) && first->beta(0) != adart) + first = first->beta(0); + + // Stack of couple of dart and dimension for which + // we must call on_split functor + std::deque modified_darts; + + // Mark used to mark darts already treated. + int treated = amap.get_new_mark(); + + // Stack of marked darts + std::stack tounmark; + + // Now we run through the facet + for (CGAL::CMap_dart_iterator_basic_of_orbit it(amap,first); + it.cont();) + { + cur = it; + ++it; + amap.mark(cur, treated); + tounmark.push(cur); + + if ( cur!=first ) + { + // TODO + //if ( amap.template degroup_attribute_of_dart<2>(first, cur) ) + { + // TODO Functor takiing a range, an attrib_handle, and that set + // all the darts of the range to this handle + /* for (typename CMap::template Dart_of_involution_range<1>::iterator + it=template darts_of_involution<1>(dh2).begin(), + itend=template darts_of_involution<1>(dh2).end(); it!=itend; + ++it) + { + } + tosplit.push(internal::Couple_dart_and_dim + + (first,cur,2));*/ + } + } + + if (!cur->is_free(0)) + { + n1 = amap.create_dart(); + amap.link_beta_0(cur, n1); + } + else n1 = NULL; + + if (!cur->is_free(1)) + { + n2 = amap.create_dart(); + amap.link_beta_1(cur, n2); + } + else n2 = NULL; + + if (n1 != NULL && n2 != NULL) + amap.link_beta_0(n1, n2); + + if (n1 != NULL && prev != NULL) + amap.template link_beta_for_involution<2>(prev, n1); + + for (unsigned int dim=3; dim<=CMap::dimension; ++dim) + { + if ( !adart->is_free(dim) ) + { + if ( !amap.is_marked(cur->beta(dim), treated) ) + { + if (n1!=NULL) + { + nn1=amap.create_dart(); + amap.link_beta_1(cur->beta(dim), nn1); + amap.basic_link_beta_for_involution(n1, nn1, dim); + } + else nn1=NULL; + + if (n2!=NULL) + { + nn2=amap.create_dart(); + amap.link_beta_0(cur->beta(dim), nn2); + amap.basic_link_beta_for_involution(n2, nn2, dim); + } + else nn2=NULL; + + if (nn1 != NULL && nn2 != NULL) + amap.basic_link_beta_1(nn1, nn2); + + if (nn1 != NULL && prev != NULL) + amap.basic_link_beta_for_involution(nn1, prev->beta(dim), 2); + + amap.mark(cur->beta(dim), treated); + tounmark.push(cur->beta(dim)); + } + else + { + if ( n1!=NULL ) + amap.basic_link_beta_for_involution(n1, cur->beta(dim)->beta(1), dim); + if ( n2!=NULL ) + amap.basic_link_beta_for_involution(n2, cur->beta(dim)->beta(0), dim); + } + } + } + + prev = n2; + } + + if (n2 != NULL) + { + amap.template link_beta_for_involution<2>(first->beta(0), n2); + for (unsigned int dim=3; dim<=CMap::dimension; ++dim) + { + if ( !adart->is_free(dim) ) + { + amap.basic_link_beta_for_involution(first->beta(0)->beta(dim), + n2->beta(dim), 2); + } + } + } + + // Now we unmark all marked darts + while ( !tounmark.empty() ) + { + amap.unmark(tounmark.top(), treated); + tounmark.pop(); + } + + CGAL_assertion(amap.is_whole_map_unmarked(treated)); + amap.free_mark(treated); + + /* TODO while ( !tosplit.empty() ) + { + internal::Couple_dart_and_dim c=tosplit.top(); + tosplit.pop(); + internal::Call_split_functor::run(c.d1, c.d2); + } */ + + CGAL_expensive_postcondition( amap.is_valid() ); + + return n1; +} +/** Insert a dangling edge in a 2-cell between given by a dart. + * @param amap the used combinatorial map. + * @param adart1 a first dart of the facet (!=NULL && !=null_dart_handle). + * @return a dart of the new edge, not incident to the vertex of adart1. + */ +template +typename CMap::Dart_handle +insert_dangling_cell_1_in_cell_2(CMap& amap, typename CMap::Dart_handle adart1) +{ + CGAL_assertion(adart1!=NULL && adart1!=CMap::null_dart_handle); + + int mark1 = amap.get_new_mark(); + std::deque to_unmark; + { + for ( CMap_dart_iterator_basic_of_cell it(amap,adart1,mark1); + it.cont(); ++it ) + { + to_unmark.push_back(it); + amap.mark(it,mark1); + } + } + + typename CMap::Dart_handle d1 = NULL; + typename CMap::Dart_handle d2 = NULL; + unsigned int s1 = 0; + + int treated = amap.get_new_mark(); + + CGAL::CMap_dart_iterator_of_involution it1(amap,adart1); + + for ( ; it1.cont(); ++it1) + { + d1 = amap.create_dart(); + d2 = amap.create_dart(); + + if ( amap.is_marked(it1, mark1) ) s1 = 0; + else s1 = 1; + + if ( !it1->is_free(s1) ) + { + if ( s1==0 ) amap.template link_beta<1>(it1->template beta<0>(), d2); + else amap.template link_beta<0>(it1->template beta<1>(), d2); + } + + if (s1==0) + { + amap.template link_beta<0>(it1, d1); + amap.template link_beta<0>(d1,d2); + } + else + { + amap.template link_beta<1>(it1, d1); + amap.template link_beta<1>(d1,d2); + } + + amap.template link_beta_for_involution<2>(d1, d2); + + for ( unsigned int dim=3; dim<=CMap::dimension; ++dim) + { + if ( !it1->is_free(dim) && + amap.is_marked(it1->beta(dim), treated) ) + { + amap.basic_link_beta_for_involution(it1->beta(dim)->beta_inv(s1), d1, + dim); + amap.basic_link_beta_for_involution + (it1->beta(dim)->beta_inv(s1)->beta(2), d2, dim); + } + } + + amap.mark(it1,treated); + } + + for ( it1.rewind(); it1.cont(); ++it1 ) + { amap.unmark(it1,treated); } + CGAL_assertion( amap.is_whole_map_unmarked(treated) ); + amap.free_mark(treated); + + typename std::deque::iterator it = + to_unmark.begin(); + for (; it != to_unmark.end(); ++it) + { amap.unmark(*it, mark1); } + CGAL_assertion( amap.is_whole_map_unmarked(mark1) ); + amap.free_mark(mark1); + + // CGAL_expensive_postcondition( amap.is_valid() ); + + return adart1->beta(0); +} + +/** Test if an edge can be inserted onto a 2-cell between two given darts. + * @param amap the used combinatorial map. + * @param adart1 a first dart. + * @param adart2 a second dart. + * @return true iff an edge can be inserted between adart1 and adart2. + */ +template < class CMap > +bool is_insertable_cell_1_in_cell_2(const CMap& amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2) +{ + CGAL_assertion(adart1 != NULL && adart2 != NULL); + if ( adart1==adart2 ) return false; + for ( CMap_dart_const_iterator_of_orbit it(amap,adart1); + it.cont(); ++it ) + { + if ( it==adart2 ) return true; + } + return false; +} + +/** Insert an edge in a 2-cell between two given darts. + * @param amap the used combinatorial map. + * @param adart1 a first dart of the facet (!=NULL && !=null_dart_handle). + * @param adart2 a second dart of the facet. If NULL insert a dangling edge. + * @return a dart of the new edge, and not incident to the + * same vertex than adart1. + */ +template +typename CMap::Dart_handle +insert_cell_1_in_cell_2(CMap& amap, + typename CMap::Dart_handle adart1, + typename CMap::Dart_handle adart2) +{ + if ( adart2==NULL ) return insert_dangling_cell_1_in_cell_2(amap,adart1); + + CGAL_assertion(is_insertable_cell_1_in_cell_2(amap, adart1, adart2)); + + int m1 = amap.get_new_mark(); + CMap_dart_iterator_basic_of_involution + it1 = CMap_dart_iterator_basic_of_involution(amap, adart1, m1); + int m2 = amap.get_new_mark(); + CMap_dart_iterator_basic_of_involution + it2 = CMap_dart_iterator_basic_of_involution(amap, adart2, m2); + + int mark1 = amap.get_new_mark(); + std::deque to_unmark; + { + for ( CMap_dart_iterator_basic_of_cell it(amap,adart1,mark1); + it.cont(); ++it ) + { + to_unmark.push_back(it); + amap.mark(it,mark1); + } + } + + typename CMap::Dart_handle d1 = NULL; + typename CMap::Dart_handle d2 = NULL; + unsigned int s1 = 0; + + int treated = amap.get_new_mark(); + + for ( ; it1.cont(); ++it1, ++it2) + { + CGAL_assertion (it2.cont() ); + d1 = amap.create_dart(); + d2 = amap.create_dart(); + + if ( amap.is_marked(it1, mark1) ) s1 = 0; + else s1 = 1; + + if ( !it1->is_free(s1) ) + { + if ( s1==0 ) amap.basic_link_beta_1(it1->template beta<0>(), d2); + else amap.link_beta_0(it1->template beta<1>(), d2); + } + + if ( !it2->is_free(s1) ) + { + if ( s1==0 ) amap.basic_link_beta_1(it2->template beta<0>(), d1); + else amap.link_beta_0(it2->template beta<1>(), d1); + } + + if ( s1==0 ) + { + amap.link_beta_0(it1, d1); + amap.link_beta_0(it2, d2); + } + else + { + amap.basic_link_beta_1(it1, d1); + amap.basic_link_beta_1(it2, d2); + } + amap.link_beta_for_involution(d2, d1, 2); + + for ( unsigned int dim=3; dim<=CMap::dimension; ++dim) + { + if ( !it1->is_free(dim) && + amap.is_marked(it1->beta(dim), treated) ) + { + amap.basic_link_beta_for_involution + (it1->beta(dim)->beta_inv(s1), d1, dim); + amap.basic_link_beta_for_involution + (it1->beta(dim)->beta_inv(s1)->beta(2), d2, dim); + } + } + + amap.mark(it1,treated); + } + + internal::Degroup_attribute_functor_run:: + run(&amap, d1, d2); + + amap.negate_mark(m1); + amap.negate_mark(m2); + it1.rewind(); it2.rewind(); + for ( ; it1.cont(); ++it1, ++it2) + { + amap.mark(it1,m1); + amap.unmark(it1,treated); + amap.mark(it2,m2); + } + amap.negate_mark(m1); + amap.negate_mark(m2); + CGAL_assertion( amap.is_whole_map_unmarked(m1) ); + CGAL_assertion( amap.is_whole_map_unmarked(m2) ); + CGAL_assertion( amap.is_whole_map_unmarked(treated) ); + amap.free_mark(m1); + amap.free_mark(m2); + amap.free_mark(treated); + + typename std::deque::iterator it = + to_unmark.begin(); + for (; it != to_unmark.end(); ++it) + { amap.unmark(*it, mark1); } + CGAL_assertion( amap.is_whole_map_unmarked(mark1) ); + amap.free_mark(mark1); + + // CGAL_expensive_postcondition( amap.is_valid() ); + + return adart1->template beta<0>(); +} + +/** Test if a 2-cell can be inserted onto a given 3-cell along + * a path of edges. + * @param amap the used combinatorial map. + * @param afirst iterator on the begining of the path. + * @param alast iterator on the end of the path. + * @return true iff a 2-cell can be inserted along the path. + */ +template +bool is_insertable_cell_2_in_cell_3(const CMap& amap, + InputIterator afirst, + InputIterator alast) +{ + CGAL_static_assertion( CMap::dimension>= 3 ); + + // The path must have at least one dart. + if (afirst==alast) return false; + typename CMap::Dart_const_handle prec = NULL; + typename CMap::Dart_const_handle od = NULL; + + for (InputIterator it(afirst); it!=alast; ++it) + { + // The path must contain only non empty darts. + if (*it == NULL || *it==CMap::null_dart_handle) return false; + + // Two consecutive darts of the path must belong to two edges + // incident to the same vertex of the same volume. + if (prec != NULL) + { + od = prec->other_extremity(); + if ( od==CMap::null_dart_handle ) return false; + + // of and *it must belong to the same vertex of the same volume + if ( !belong_to_same_cell(amap, od, *it) ) + return false; + } + prec = *it; + } + + // The path must be closed. + od = prec->other_extremity(); + if ( od==CMap::null_dart_handle ) return false; + + if (!belong_to_same_cell(amap, od, *afirst)) + return false; + + return true; +} + +/** Insert a 2-cell in a given 3-cell along a path of darts. + * @param amap the used combinatorial map. + * @param afirst iterator on the begining of the path. + * @param alast iterator on the end of the path. + * @return a dart of the new 2-cell. + */ +template +typename CMap::Dart_handle +insert_cell_2_in_cell_3(CMap& amap, InputIterator afirst, InputIterator alast) +{ + CGAL_assertion(is_insertable_cell_2_in_cell_3(amap,afirst,alast)); + + typename CMap::Dart_handle prec = NULL, d = NULL, dd = NULL, first = NULL; + bool withBeta3 = false; + + { + for (InputIterator it(afirst); it!=alast; ++it) + { + if (!(*it)->is_free(2)) withBeta3 = true; + } + } + + { + for (InputIterator it(afirst); it!=alast; ++it) + { + d = amap.create_dart(); + if (withBeta3) + { + dd = amap.create_dart(); + amap.template basic_link_beta_for_involution<3>(d, dd); + } + + if (prec != NULL) + { + amap.template link_beta<0>(prec, d); + if (withBeta3) + amap.template link_beta<1>(prec->template beta<3>(), dd); + } + else first = d; + + if (!(*it)->is_free(2)) + amap.template link_beta_for_involution<2> + ((*it)->template beta<2>(), dd); + + amap.template link_beta_for_involution<2>(*it, d); + + prec = d; + } + } + + amap.template link_beta<0>(prec, first); + if (withBeta3) + { + amap.template link_beta<1>(prec->template beta<3>(), + first->template beta<3>()); + } + + // Make copies of the new facet for dimension >=4 + for ( unsigned int dim=4; dim<=CMap::dimension; ++dim ) + { + if ( !first->is_free(dim) ) + { + typename CMap::Dart_handle first2 = NULL; + prec = NULL; + for ( CMap_dart_iterator_of_orbit it(amap, first); + it.cont(); ++it ) + { + d = amap.create_dart(); + amap.link_beta_for_involution(it->template beta<2>(), d, dim); + if ( withBeta3 ) + { + dd = amap.create_dart(); + amap.link_beta_for_involution + (it->template beta<2>()->template beta<3>(), dd, dim); + amap.template basic_link_beta_for_involution<3>(d, dd); + } + if ( prec!=NULL ) + { + amap.link_beta_0(prec, d); + if ( withBeta3 ) + { + amap.link_beta_1(prec->template beta<3>(), dd); + } + } + else first2 = prec; + + for ( unsigned dim2=2; dim2<=CMap::dimension; ++dim2 ) + { + if ( dim2+1!=dim && dim2!=dim && dim2!=dim+1 ) + { + if ( !it->is_free(dim2) && + it->beta(dim2)->is_free(dim) ) + amap.basic_link_beta_for_involution(it->beta(dim2)->beta(dim), + d, dim2); + if ( withBeta3 && !it->beta(3)->is_free(dim2) && + it->template beta<3>()->beta(dim2)->is_free(dim) ) + amap.basic_link_beta_for_involution + (it->template beta<3>()->beta(dim2)->beta(dim), dd, dim2); + } + } + prec = d; + } + amap.template link_beta<0>( prec, first2 ); + if ( withBeta3 ) + { + amap.template link_beta<1>( prec->template beta<3>(), + first2->template beta<3>() ); + } + } + } + + // Degroup the attributes + if ( withBeta3 ) + internal::Degroup_attribute_functor_run:: + run(&amap, first, first->template beta<3>()); + + // CGAL_expensive_postcondition( amap.is_valid() ); + + return first; +} + +} // namespace CGAL + +#endif // CGAL_COMBINATORIAL_MAP_INSERTIONS_H diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map_iterators_base.h b/Combinatorial_map/include/CGAL/Combinatorial_map_iterators_base.h index 9687d1c59df..9de6b6dc97f 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map_iterators_base.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map_iterators_base.h @@ -365,13 +365,11 @@ namespace CGAL { /// Destructor. ~CMap_non_basic_iterator() { - if ( this->mmark_number!=-1 ) - { - if (this->mmap->get_number_of_times_mark_reserved - (this->mmark_number)==1) - unmark_treated_darts(); - this->mmap->free_mark(this->mmark_number); - } + CGAL_assertion( this->mmark_number!=-1 ); + if (this->mmap->get_number_of_times_mark_reserved + (this->mmark_number)==1) + unmark_treated_darts(); + this->mmap->free_mark(this->mmark_number); } /// Copy constructor. @@ -384,6 +382,11 @@ namespace CGAL { { if (this != &aiterator) { + if (this->mmap->get_number_of_times_mark_reserved + (this->mmark_number)==1) + unmark_treated_darts(); + this->mmap->free_mark(this->mmark_number); + Base::operator=(aiterator); this->mmap->share_a_mark(this->mmark_number); } diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h b/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h index 91aae074a4a..d61669525ed 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h @@ -21,7 +21,8 @@ #define CGAL_COMBINATORIAL_MAP_OPERATIONS_H 1 #include -#include +#include +#include #include namespace CGAL { @@ -30,167 +31,6 @@ namespace CGAL { * Some operations to modify a combinatorial map. */ - /** Insert a vertex in the given 2-cell which is splitted in triangles, - * once for each inital edge of the facet. - * @param amap the used combinatorial map. - * @param adart a dart of the facet to triangulate. - * @return A dart incident to the new vertex. - */ -// TODO revoir toute la gestion des attributs -// (utilisation correcte des link avec/sans la maj) - template < class CMap > - typename CMap::Dart_handle - insert_cell_0_in_cell_2(CMap& amap, typename CMap::Dart_handle adart) - { - CGAL_assertion(adart != NULL && adart!=CMap::null_dart_handle); - - typename CMap::Dart_handle first = adart, prev = NULL, cur = NULL; - typename CMap::Dart_handle n1 = NULL, n2 = NULL; - - typename CMap::Dart_handle nn1 = NULL, nn2 = NULL; - - // If the facet is open, we search the dart 0-free - while (!first->is_free(0) && first->beta(0) != adart) - first = first->beta(0); - - // Stack of couple of dart and dimension for which - // we must call on_split functor - std::stack > - tosplit; - - // Mark used to mark darts already treated. - int treated = amap.get_new_mark(); - - // Stack of marked darts - std::stack tounmark; - - // Now we run through the facet - for (CGAL::CMap_dart_iterator_basic_of_orbit it(amap,first); - it.cont();) - { - cur = it; - ++it; - amap.mark(cur, treated); - tounmark.push(cur); - - if ( cur!=first ) - { - // TODO - //if ( amap.template degroup_attribute_of_dart<2>(first, cur) ) - { - // TODO Functor takiing a range, an attrib_handle, and that set - // all the darts of the range to this handle - /* for (typename CMap::template Dart_of_involution_range<1>::iterator - it=template darts_of_involution<1>(dh2).begin(), - itend=template darts_of_involution<1>(dh2).end(); it!=itend; - ++it) - { - }*/ - tosplit.push(internal::Couple_dart_and_dim - - (first,cur,2)); - } - } - - if (!cur->is_free(0)) - { - n1 = amap.create_dart(); - amap.link_beta_0(cur, n1); - } - else n1 = NULL; - - if (!cur->is_free(1)) - { - n2 = amap.create_dart(); - amap.link_beta_1(cur, n2); - } - else n2 = NULL; - - if (n1 != NULL && n2 != NULL) - amap.link_beta_0(n1, n2); - - if (n1 != NULL && prev != NULL) - amap.template link_beta_for_involution<2>(prev, n1); - - for (unsigned int dim=3; dim<=CMap::dimension; ++dim) - { - if ( !adart->is_free(dim) ) - { - if ( !amap.is_marked(cur->beta(dim), treated) ) - { - if (n1!=NULL) - { - nn1=amap.create_dart(); - amap.link_beta_1(cur->beta(dim), nn1); - amap.basic_link_beta_for_involution(n1, nn1, dim); - } - else nn1=NULL; - - if (n2!=NULL) - { - nn2=amap.create_dart(); - amap.link_beta_0(cur->beta(dim), nn2); - amap.basic_link_beta_for_involution(n2, nn2, dim); - } - else nn2=NULL; - - if (nn1 != NULL && nn2 != NULL) - amap.basic_link_beta_1(nn1, nn2); - - if (nn1 != NULL && prev != NULL) - amap.basic_link_beta_for_involution(nn1, prev->beta(dim), 2); - - amap.mark(cur->beta(dim), treated); - tounmark.push(cur->beta(dim)); - } - else - { - if ( n1!=NULL ) - amap.basic_link_beta_for_involution(n1, cur->beta(dim)->beta(1), dim); - if ( n2!=NULL ) - amap.basic_link_beta_for_involution(n2, cur->beta(dim)->beta(0), dim); - } - } - } - - prev = n2; - } - - if (n2 != NULL) - { - amap.template link_beta_for_involution<2>(first->beta(0), n2); - for (unsigned int dim=3; dim<=CMap::dimension; ++dim) - { - if ( !adart->is_free(dim) ) - { - amap.basic_link_beta_for_involution(first->beta(0)->beta(dim), - n2->beta(dim), 2); - } - } - } - - // Now we unmark all marked darts - while ( !tounmark.empty() ) - { - amap.unmark(tounmark.top(), treated); - tounmark.pop(); - } - - CGAL_assertion(amap.is_whole_map_unmarked(treated)); - amap.free_mark(treated); - - while ( !tosplit.empty() ) - { - internal::Couple_dart_and_dim c=tosplit.top(); - tosplit.pop(); - internal::Call_split_functor::run(c.d1, c.d2); - } - - CGAL_expensive_postcondition( amap.is_valid() ); - - return n1; - } - /** Test if an i-cell can be removed. * An i-cell can be removed if i==CMap::dimension or i==CMap::dimension-1, * or if there are at most two (i+1)-cell incident to it. @@ -244,17 +84,6 @@ namespace CGAL { const int iinv = CGAL_BETAINV(i); - /*int mark_for_incident_cells[CMap::Helper::nb_attribs]; - std::deque > - incident_cells[CMap::Helper::nb_attribs]; - - // Marks used to mark all the incident cells. - for (int j=0; j it(amap,adart,mark); it.cont(); ++it ) @@ -266,106 +95,38 @@ namespace CGAL { ++res; } - // Second we store all the incident cells that can be split by - // the operation. - typename std::deque::iterator it = - to_erase.begin(); - /*for (; it != to_erase.end(); ++it) - { - d1 = (*it)->beta(iinv); - while ( d1!=CMap::null_dart_handle && amap.is_marked(d1, mark) ) - { - d1 = d1->beta(i+1)->beta(iinv); - if (d1 == (*it)->beta(iinv)) d1 = CMap::null_dart_handle; - } - - d2 = (*it)->beta(i+1)->beta(i); - while ( d2!=CMap::null_dart_handle && amap.is_marked(d2, mark) ) - { - d2 = d2->beta(i+1)->beta(i); - if ( d2==(*it)->beta(i+1)->beta(i) ) d2=CMap::null_dart_handle; - } - - if (d1 != CMap::null_dart_handle) - { - if (d2 != CMap::null_dart_handle) - { - if ( dg1==NULL ) { dg1 = d1; dg2=d2; } - CMap::Helper::template Foreach_enabled_attributes - >:: - run(&amap, d1, mark, &mark_for_incident_cells[0], - &incident_cells[0]); - CMap::Helper::template Foreach_enabled_attributes - >:: - run(&amap, d2, mark, &mark_for_incident_cells[0], - &incident_cells[0]); - } - else - { - if ( !d1->is_free(i) ) - { - CMap::Helper::template Foreach_enabled_attributes - >:: - run(&amap, d1->beta(i), mark, &mark_for_incident_cells[0], - &incident_cells[0]); - } - } - } - else if (d2 != CMap::null_dart_handle) - { - if ( !d2->is_free(iinv) ) - { - CMap::Helper::template Foreach_enabled_attributes - >:: - run(&amap, d2, mark, &mark_for_incident_cells[0], - &incident_cells[0]); - } - } - - if ((*it)->is_free(i+1) && !(*it)->is_free(i)) - { - d1 = (*it)->beta(i); - if ( !d1->is_free(iinv) ) - { - CMap::Helper::template Foreach_enabled_attributes - >:: - run(&amap, d1, mark, &mark_for_incident_cells[0], - &incident_cells[0]); - } - } - - // Required to process cells non consider in the cases above. - amap.update_dart_of_all_attributes(*it, mark); - }*/ - - for (; it != to_erase.end(); ++it) - amap.update_dart_of_all_attributes(*it, mark); - // We group the two (i+1)-cells incident if they exist. if ( dg1!=NULL ) internal::Group_attribute_functor_run:: run(&amap, dg1, dg2); + // Second we store all the incident cells that can be split by + // the operation. + typename std::deque::iterator it = + to_erase.begin(); + for (; it != to_erase.end(); ++it) + amap.update_dart_of_all_attributes(*it, mark); + std::deque modified_darts; - // std::deque modified_darts2; // For each dart of the i-cell, we modify i-links of neighbors. for ( it=to_erase.begin(); it != to_erase.end(); ++it) { - d1=(*it)->beta(iinv); + d1=(*it)->template beta(); while ( d1!=CMap::null_dart_handle && amap.is_marked(d1, mark) ) { - d1=d1->beta(i+1)->beta(iinv); - if ( d1==(*it)->beta(iinv) ) d1=CMap::null_dart_handle; + d1=d1->template beta()->template beta(); + if ( d1==(*it)->template beta() ) d1=CMap::null_dart_handle; } if ( !amap.is_marked(d1, mark_modified_darts) ) { - d2=(*it)->beta(i+1)->beta(i); + d2=(*it)->template beta()->template beta(); while ( d2!=CMap::null_dart_handle && amap.is_marked(d2, mark) ) { - d2=d2->beta(i+1)->beta(i); - if ( d2==(*it)->beta(i+1)->beta(i) ) d2=CMap::null_dart_handle; + d2=d2->template beta()->template beta(); + if ( d2==(*it)->template beta()->template beta() ) + d2=CMap::null_dart_handle; } if ( !amap.is_marked(d2, mark_modified_darts) ) @@ -425,12 +186,9 @@ namespace CGAL { // We test the split of all the incident cells for all the non // void attributes. - CMap::Helper::template Foreach_enabled_attributes - >:: - // >:: + CMap::Helper::template Foreach_enabled_attributes_except + , i>:: run(&amap, &modified_darts, mark_modified_darts); - //&modified_darts2); - //&mark_for_incident_cells[0], &incident_cells[0]); // We remove all the darts of the i-cell. for ( it=to_erase.begin(); it!=to_erase.end(); ++it ) @@ -445,25 +203,13 @@ namespace CGAL { iterator it=modified_darts.begin(); it!=modified_darts.end(); ++it ) amap.unmark(*it, mark_modified_darts); - /*for ( typename std::deque:: - iterator it=modified_darts2.begin(); - it!=modified_darts2.end(); ++it ) - amap.unmark(*it, mark_modified_darts);*/ } CGAL_assertion ( amap.is_whole_map_unmarked(mark_modified_darts) ); amap.free_mark(mark_modified_darts); - // We free the marks. - /*for (int j=0; j >:: + CMap::Helper::template Foreach_enabled_attributes_except + , + CMap::dimension>:: run(&amap, &modified_darts, -1); //, modified_darts2); //&mark_for_incident_cells[0], //&incident_cells[0]); @@ -710,8 +457,8 @@ namespace CGAL { // We test the split of all the incident cells for all the non // void attributes. - CMap::Helper::template Foreach_enabled_attributes - >:: + CMap::Helper::template Foreach_enabled_attributes_except + , 1>:: // >:: run(&amap, &modified_darts, -1); //mark_modified_darts); @@ -750,27 +497,6 @@ namespace CGAL { size_t remove_cell(CMap& amap, typename CMap::Dart_handle adart) { return Remove_cell_functor::run(amap,adart); } - /** Test if an edge can be inserted onto a 2-cell between two given darts. - * @param amap the used combinatorial map. - * @param adart1 a first dart. - * @param adart2 a second dart. - * @return true iff an edge can be inserted between adart1 and adart2. - */ - template < class CMap > - bool is_insertable_cell_1_in_cell_2(const CMap& amap, - typename CMap::Dart_const_handle adart1, - typename CMap::Dart_const_handle adart2) - { - CGAL_assertion(adart1 != NULL && adart2 != NULL); - if ( adart1==adart2 ) return false; - for ( CMap_dart_const_iterator_of_orbit it(amap,adart1); - it.cont(); ++it ) - { - if ( it==adart2 ) return true; - } - return false; - } - /** Test if an i-cell can be contracted. * An i-cell can be contracted if i==1 * or if there are at most two (i-1)-cell incident to it. @@ -917,8 +643,8 @@ namespace CGAL { // We test the split of all the incident cells for all the non // void attributes. - CMap::Helper::template Foreach_enabled_attributes - >:: + CMap::Helper::template Foreach_enabled_attributes_except + , i>:: run(&amap, &modified_darts, mark_modified_darts); // We remove all the darts of the i-cell. @@ -1029,8 +755,8 @@ namespace CGAL { // We test the split of all the incident cells for all the non // void attributes. - CMap::Helper::template Foreach_enabled_attributes - >:: + CMap::Helper::template Foreach_enabled_attributes_except + , 1>:: // >:: run(&amap, &modified_darts, -1); //mark_modified_darts); @@ -1060,443 +786,6 @@ namespace CGAL { size_t contract_cell(CMap& amap, typename CMap::Dart_handle adart) { return Contract_cell_functor::run(amap,adart); } - /** Test if a 2-cell can be inserted onto a given 3-cell along - * a path of edges. - * @param amap the used combinatorial map. - * @param afirst iterator on the begining of the path. - * @param alast iterator on the end of the path. - * @return true iff a 2-cell can be inserted along the path. - */ - template - bool is_insertable_cell_2_in_cell_3(const CMap& amap, - InputIterator afirst, - InputIterator alast) - { - CGAL_static_assertion( CMap::dimension>= 3 ); - - // The path must have at least one dart. - if (afirst==alast) return false; - typename CMap::Dart_const_handle prec = NULL; - typename CMap::Dart_const_handle od = NULL; - - for (InputIterator it(afirst); it!=alast; ++it) - { - // The path must contain only non empty darts. - if (*it == NULL || *it==CMap::null_dart_handle) return false; - - // Two consecutive darts of the path must belong to two edges - // incident to the same vertex of the same volume. - if (prec != NULL) - { - od = prec->other_extremity(); - if ( od==CMap::null_dart_handle ) return false; - - // of and *it must belong to the same vertex of the same volume - if ( !belong_to_same_cell(amap, od, *it) ) - return false; - } - prec = *it; - } - - // The path must be closed. - od = prec->other_extremity(); - if ( od==CMap::null_dart_handle ) return false; - - if (!belong_to_same_cell(amap, od, *afirst)) - return false; - - return true; - } - - /** Insert a vertex in a given edge. - * @param amap the used combinatorial map. - * @param adart a dart of the edge (!=NULL && !=null_dart_handle). - * @return a dart of the new vertex. - */ - template - typename CMap::Dart_handle - insert_cell_0_in_cell_1(CMap& amap, typename CMap::Dart_handle adart) - { - CGAL_assertion(adart != NULL && adart!=CMap::null_dart_handle); - - typename CMap::Dart_handle d1, d2; - int mark = amap.get_new_mark(); - - std::vector vect; - { - for (typename CMap::template Dart_of_cell_range<1>::iterator it= - amap.template darts_of_cell<1>(adart).begin(); - it != amap.template darts_of_cell<1>(adart).end(); ++it) - vect.push_back(it); - } - - // 3) For each dart of the cell, we modify link of neighbors. - typename std::vector::iterator it = vect.begin(); - for (; it != vect.end(); ++it) - { - d1 = amap.create_dart(); - - if (!(*it)->is_free(1)) - { amap.template basic_link_beta<1>(d1, (*it)->beta(1)); } - - for ( unsigned int dim = 2; dim<=CMap::dimension; ++dim ) - { - if (!(*it)->is_free(dim) && amap.is_marked((*it)->beta(dim), mark)) - { - amap.basic_link_beta((*it)->beta(dim), d1, dim); - amap.basic_link_beta(*it, (*it)->beta(dim)->beta(1), dim); - } - } - - amap.template basic_link_beta<1>(*it, d1); - // TODO remove this group, and use link_beta instead ? - //amap.group_all_dart_attributes_except(*it, d1, 1); - - amap.mark(*it, mark); - } - - for (it = vect.begin(); it != vect.end(); ++it) - { amap.unmark(*it, mark); } - - amap.free_mark(mark); - - // TODO amap.template degroup_attribute<1>(adart, adart->beta(1)); - - // CGAL_expensive_postcondition( amap.is_valid() ); - - return adart->beta(1); - } - - /** Insert a dangling edge in a 2-cell between given by a dart. - * @param amap the used combinatorial map. - * @param adart1 a first dart of the facet (!=NULL && !=null_dart_handle). - * @return a dart of the new edge, not incident to the vertex of adart1. - */ - template - typename CMap::Dart_handle - insert_dangling_cell_1_in_cell_2(CMap& amap, typename CMap::Dart_handle adart1) - { - CGAL_assertion(adart1!=NULL && adart1!=CMap::null_dart_handle); - - int mark1 = amap.get_new_mark(); - std::vector to_unmark; - { - for ( CMap_dart_iterator_basic_of_cell it(amap,adart1,mark1); - it.cont(); ++it ) - { - to_unmark.push_back(it); - amap.mark(it,mark1); - } - } - - typename CMap::Dart_handle d1 = NULL; - typename CMap::Dart_handle d2 = NULL; - unsigned int s1 = 0; - - int treated = amap.get_new_mark(); - - CGAL::CMap_dart_iterator_of_involution it1(amap,adart1); - - for ( ; it1.cont(); ++it1) - { - d1 = amap.create_dart(); - d2 = amap.create_dart(); - - if ( amap.is_marked(it1, mark1) ) s1 = 0; - else s1 = 1; - - if ( !it1->is_free(s1) ) - { - if ( s1==0 ) amap.template link_beta<1>(it1->beta(0), d2); - else amap.template link_beta<0>(it1->beta(1), d2); - } - - if (s1==0) - { - amap.template link_beta<0>(it1, d1); - amap.template basic_link_beta<0>(d1,d2); - } - else - { - amap.template link_beta<1>(it1, d1); - amap.template basic_link_beta<1>(d1,d2); - } - - amap.template link_beta_for_involution<2>(d1, d2); - - for ( unsigned int dim=3; dim<=CMap::dimension; ++dim) - { - if ( !it1->is_free(dim) && - amap.is_marked(it1->beta(dim), treated) ) - { - amap.basic_link_beta_for_involution(it1->beta(dim)->beta_inv(s1), d1, - dim); - amap.basic_link_beta_for_involution - (it1->beta(dim)->beta_inv(s1)->beta(2), d2, dim); - } - } - - amap.mark(it1,treated); - } - - // amap.template degroup_attribute<1>(adart1, adart1->beta(0)); - // amap.template degroup_attribute<2>(d1, d2); - - for ( it1.rewind(); it1.cont(); ++it1 ) - { - amap.unmark(it1,treated); - } - CGAL_assertion( amap.is_whole_map_unmarked(treated) ); - amap.free_mark(treated); - - typename std::vector::iterator it = - to_unmark.begin(); - for (; it != to_unmark.end(); ++it) - { amap.unmark(*it, mark1); } - CGAL_assertion( amap.is_whole_map_unmarked(mark1) ); - amap.free_mark(mark1); - - // CGAL_expensive_postcondition( amap.is_valid() ); - - return adart1->beta(0); - } - - /** Insert an edge in a 2-cell between two given darts. - * @param amap the used combinatorial map. - * @param adart1 a first dart of the facet (!=NULL && !=null_dart_handle). - * @param adart2 a second dart of the facet. If NULL insert a dangling edge. - * @return a dart of the new edge, and not incident to the - * same vertex than adart1. - */ - template - typename CMap::Dart_handle - insert_cell_1_in_cell_2(CMap& amap, - typename CMap::Dart_handle adart1, - typename CMap::Dart_handle adart2) - { - if ( adart2==NULL ) return insert_dangling_cell_1_in_cell_2(amap,adart1); - - CGAL_assertion(is_insertable_cell_1_in_cell_2(amap, adart1, adart2)); - - int m1 = amap.get_new_mark(); - CMap_dart_iterator_basic_of_involution - it1 = CMap_dart_iterator_basic_of_involution(amap, adart1, m1); - int m2 = amap.get_new_mark(); - CMap_dart_iterator_basic_of_involution - it2 = CMap_dart_iterator_basic_of_involution(amap, adart2, m2); - - int mark1 = amap.get_new_mark(); - std::vector to_unmark; - { - for ( CMap_dart_iterator_basic_of_cell it(amap,adart1,mark1); - it.cont(); ++it ) - { - to_unmark.push_back(it); - amap.mark(it,mark1); - } - } - - typename CMap::Dart_handle d1 = NULL; - typename CMap::Dart_handle d2 = NULL; - unsigned int s1 = 0; - - int treated = amap.get_new_mark(); - - for ( ; it1.cont(); ++it1, ++it2) - { - CGAL_assertion (it2.cont() ); - d1 = amap.create_dart(); - d2 = amap.create_dart(); - - if ( amap.is_marked(it1, mark1) ) s1 = 0; - else s1 = 1; - - if ( !it1->is_free(s1) ) - { - if ( s1==0 ) amap.basic_link_beta_1(it1->beta(0), d2); - else amap.link_beta_0(it1->beta(1), d2); - } - - if ( !it2->is_free(s1) ) - { - if ( s1==0 ) amap.basic_link_beta_1(it2->beta(0), d1); - else amap.link_beta_0(it2->beta(1), d1); - } - - if ( s1==0 ) - { - amap.link_beta_0(it1, d1); - amap.link_beta_0(it2, d2); - } - else - { - amap.basic_link_beta_1(it1, d1); - amap.basic_link_beta_1(it2, d2); - } - amap.link_beta_for_involution(d2, d1, 2); - - for ( unsigned int dim=3; dim<=CMap::dimension; ++dim) - { - if ( !it1->is_free(dim) && - amap.is_marked(it1->beta(dim), treated) ) - { - amap.basic_link_beta_for_involution - (it1->beta(dim)->beta_inv(s1), d1, dim); - amap.basic_link_beta_for_involution - (it1->beta(dim)->beta_inv(s1)->beta(2), d2, dim); - } - } - - amap.mark(it1,treated); - } - - // amap.template degroup_attribute<1>(adart1, adart1->beta(0)); - // TODO amap.template degroup_attribute<2>(d1, d2); - - amap.negate_mark(m1); - amap.negate_mark(m2); - it1.rewind(); it2.rewind(); - for ( ; it1.cont(); ++it1, ++it2) - { - amap.mark(it1,m1); - amap.unmark(it1,treated); - amap.mark(it2,m2); - } - amap.negate_mark(m1); - amap.negate_mark(m2); - CGAL_assertion( amap.is_whole_map_unmarked(m1) ); - CGAL_assertion( amap.is_whole_map_unmarked(m2) ); - CGAL_assertion( amap.is_whole_map_unmarked(treated) ); - amap.free_mark(m1); - amap.free_mark(m2); - amap.free_mark(treated); - - typename std::vector::iterator it = - to_unmark.begin(); - for (; it != to_unmark.end(); ++it) - { amap.unmark(*it, mark1); } - CGAL_assertion( amap.is_whole_map_unmarked(mark1) ); - amap.free_mark(mark1); - - // CGAL_expensive_postcondition( amap.is_valid() ); - - return adart1->beta(0); - } - - /** Insert a 2-cell in a given 3-cell along a path of darts. - * @param amap the used combinatorial map. - * @param afirst iterator on the begining of the path. - * @param alast iterator on the end of the path. - * @return a dart of the new 2-cell. - */ - template - typename CMap::Dart_handle - insert_cell_2_in_cell_3(CMap& amap, InputIterator afirst, InputIterator alast) - { - CGAL_assertion(is_insertable_cell_2_in_cell_3(amap,afirst,alast)); - - typename CMap::Dart_handle prec = NULL, d = NULL, dd = NULL, first = NULL; - bool withBeta3 = false; - - { - for (InputIterator it(afirst); it!=alast; ++it) - { - if (!(*it)->is_free(2)) withBeta3 = true; - } - } - - { - for (InputIterator it(afirst); it!=alast; ++it) - { - d = amap.create_dart(); - if (withBeta3) - { - dd = amap.create_dart(); - amap.basic_link_beta_for_involution(d, dd, 3); - } - - if (prec != NULL) - { - amap.template link_beta<0>(prec, d); - if (withBeta3) amap.template link_beta<1>(prec->beta(3), dd); - } - else first = d; - - if (!(*it)->is_free(2)) - amap.link_beta_for_involution((*it)->beta(2), dd, 2); - - amap.link_beta_for_involution(*it, d, 2); - - prec = d; - } - } - - amap.template link_beta<0>(prec, first); - if (withBeta3) - { - amap.template link_beta<1>(prec->beta(3), first->beta(3)); - } - - // Make copies of the new facet for dimension >=4 - for ( unsigned int dim=4; dim<=CMap::dimension; ++dim ) - { - if ( !first->is_free(dim) ) - { - typename CMap::Dart_handle first2 = NULL; - prec = NULL; - for ( CMap_dart_iterator_of_orbit it(amap, first); - it.cont(); ++it ) - { - d = amap.create_dart(); - amap.link_beta_for_involution(it->beta(2),d,dim); - if ( withBeta3 ) - { - dd = amap.create_dart(); - amap.link_beta_for_involution(it->beta(2)->beta(3),dd,dim); - amap.basic_link_beta_for_involution(d, dd, 3); - } - if ( prec!=NULL ) - { - amap.link_beta_0(prec,d); - if ( withBeta3 ) - { - amap.link_beta_1(prec->beta(3),dd); - } - } - else first2 = prec; - - for ( unsigned dim2=2; dim2<=CMap::dimension; ++dim2 ) - { - if ( dim2+1!=dim && dim2!=dim && dim2!=dim+1 ) - { - if ( !it->is_free(dim2) && - it->beta(dim2)->is_free(dim) ) - amap.basic_link_beta_for_involution(it->beta(dim2)->beta(dim), - d, dim2); - if ( withBeta3 && !it->beta(3)->is_free(dim2) && - it->beta(3)->beta(dim2)->is_free(dim) ) - amap.basic_link_beta_for_involution - (it->beta(3)->beta(dim2)->beta(dim), dd, dim2); - } - } - prec = d; - } - amap.template link_beta<0>( prec, first2 ); - if ( withBeta3 ) - { - amap.template link_beta<1>( prec->beta(3), first2->beta(3) ); - } - } - } - - // Degroup the attributes - /* TODO if ( withBeta3 ) - amap.template degroup_attribute<3>( first, first->beta(3) ); -*/ - // CGAL_expensive_postcondition( amap.is_valid() ); - - return first; - } } // namespace CGAL #endif // CGAL_COMBINATORIAL_MAP_OPERATIONS_H // diff --git a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_functors.h b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_functors.h index 8dd15816214..4095411f046 100644 --- a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_functors.h +++ b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_functors.h @@ -23,12 +23,13 @@ #include #include #include +#include #include -#include /* Definition of functors used to manage attributes (we need functors as * attributes are stored in tuple, thus all the access must be done at - * compiling time. + * compiling time). Some of these functors are used with + * Foreach_enabled_attributes to iterate through all the non void attribs. * * Call_split_functor to call the OnSplit functors on two given * i-attributes. @@ -36,19 +37,46 @@ * Call_merge_functor to call the OnMerge functors on two given * i-attributes. * + * Reserve_mark_functor to reserve one mark for each non void attribute. + * + * Test_is_valid_attribute_functor to test if a given i-cell is valid + * (all its darts are linked to the same attribute, no other dart is linked + * with this attribute). + * + * Count_cell_functor to count the nuber of i-cells. + * + * Count_bytes_one_attribute_functor to count the memory occupied by + * i-attributes. + * + * Decrease_attribute_functor to decrease by one the ref counting of + * a given i-attribute. + * + * Beta_functor to call several beta on the given dart. Indices are + * given as parameter of the run function. + * + * Beta_functor_static to call several beta on the given dart. + * Indices are given as template arguments. + * * Group_attribute_functor_of_dart to group the -attributes of two * given darts (except for j-dim). Only the attributes of the two given * darts are possibly modified. + * * Group_attribute_functor_of_dart_run same than * Group_attribute_functor_of_dart::run, with i template argument * given in the struct to enable specialization. * * Group_attribute_functor to group the -attributes of two - * given i-cells (except forj-adim). If one i-attribute is NULL, we set the + * given i-cells (except for j-adim). If one i-attribute is NULL, we set the * darts of its i-cell to the second attribute. If both i-attributes are * non NULL, we overide all the i-attribute of the second i-cell to the * first i-attribute. * + * Degroup_attribute_functor_run to degroup one i-attributes in two + * (except for j-adim). + * + * Test_split_attribute_functor to test if there is some i-attributes + * that are split after an operation. Modified darts are given in a + * std::deque. */ namespace CGAL @@ -59,7 +87,6 @@ namespace CGAL /** @file Combinatorial_map_functors.h * Definition of functors used for dD Combinatorial map. */ - // ************************************************************************** // Functor which call Functor::operator() on the two given cell_attributes template @@ -77,10 +104,9 @@ namespace CGAL static void run(Cell_attribute&, Cell_attribute&) {} }; - // ************************************************************************** // Functor used to call the On_split functor between the two given darts. - template struct Call_split_functor @@ -118,7 +143,6 @@ namespace CGAL typename CMap::Dart_handle) {} }; - // ************************************************************************** // Functor used to call the On_merge functor between the two given darts. template struct Call_merge_functor @@ -157,7 +180,6 @@ namespace CGAL typename CMap::Dart_handle) {} }; - // ************************************************************************** /// Functor used to reserve one mark for each enabled attribute. template @@ -167,7 +189,6 @@ namespace CGAL static void run(const CMap* amap, std::vector* marks) { (*marks)[i] = amap->get_new_mark(); } }; - // ************************************************************************** /// Functor used to test if a cell is valid template @@ -186,7 +207,6 @@ namespace CGAL } } }; - // ************************************************************************** /// Functor for counting i-cell template @@ -205,7 +225,6 @@ namespace CGAL } } }; - // ************************************************************************** /// Functor for counting the memory occupation of attributes /// Be careful not reentrant !!! TODO a Foreach_enabled_attributes @@ -237,7 +256,6 @@ namespace CGAL return Count_bytes_one_attribute_functor::res; } }; - // ************************************************************************** /// Functor used to call decrease_attribute_ref_counting /// on each i-cell attribute enabled @@ -246,13 +264,13 @@ namespace CGAL { template static void run(CMap* amap, typename CMap::Dart_handle adart) - { amap->template - decrease_attribute_ref_counting(adart/*,Tag_true()*/); } + { amap->template decrease_attribute_ref_counting(adart); } }; - // ************************************************************************** /// Functor used for link_beta to update the i-attributes of /// adart2 on the attributes of this dart, except if i=j. + /// (j is the dimension of the beta modified between adart1 and adart2, + /// so that after the modification we will have beta_j(adart1)==adart2) /// Only attributes of dh1 or dh2 can be modified. template::value>=0, "Group_attribute_functor_of_dart_run but " @@ -286,6 +304,7 @@ namespace CGAL else amap->template set_attribute_of_dart(dh2, a1); } }; + // Specialization for i=0 and 2<=j. template struct Group_attribute_functor_of_dart_run { @@ -331,6 +350,7 @@ namespace CGAL } } }; + // Specialization for i=0 and j=0. template struct Group_attribute_functor_of_dart_run { @@ -360,6 +380,7 @@ namespace CGAL } } }; + // Specialization for i=0 and j=1. template struct Group_attribute_functor_of_dart_run { @@ -389,6 +410,7 @@ namespace CGAL } } }; + // Specialization for void attributes. template struct Group_attribute_functor_of_dart_run { @@ -397,6 +419,7 @@ namespace CGAL typename CMap::Dart_handle) {} }; + // Specialization for i=j. Do nothing as j is the dimension to not consider. template struct Group_attribute_functor_of_dart_run { @@ -405,9 +428,11 @@ namespace CGAL typename CMap::Dart_handle) {} }; - + // ************************************************************************** /// Functor used for link_beta to update the attributes of /// adart2 on the attributes of this dart, except for j-attributes. + /// (j is the dimension of the beta modified between adart1 and adart2, + /// so that after the modification we will have beta_j(adart1)==adart2) /// We define run to allows to use this functor with /// Foreach_enabled_attributes. /// If you know i at compiling time, use directly @@ -423,10 +448,10 @@ namespace CGAL Group_attribute_functor_of_dart_run::run(amap,adart1,adart2); } }; - // ************************************************************************** // Functor used to group the two i-attributes of the two i-cells, except the // attribute of j + // (j is the dimension of the beta modified between adart1 and adart2). template::type> @@ -436,7 +461,7 @@ namespace CGAL typename CMap::Dart_handle adart1, typename CMap::Dart_handle adart2) { - CGAL_static_assertion( i<=CMap::dimension ); + CGAL_static_assertion( 1<=i && i<=CMap::dimension ); CGAL_static_assertion( i!=j ); CGAL_static_assertion_msg ( CMap::Helper::template Dimension_index::value>=0, @@ -470,6 +495,7 @@ namespace CGAL amap->template set_attribute(toSet, a1); } }; + // Specialization for i=0 and 2<=j. template struct Group_attribute_functor_run { @@ -502,7 +528,7 @@ namespace CGAL { toSet=od; if ( a2!=NULL ) - { // TODO REMOVE ? + { Call_merge_functor::run(a1, a2); } } @@ -524,7 +550,7 @@ namespace CGAL { toSet=dh2; if ( a2!=NULL ) - { // TODO REMOVE ? + { Call_merge_functor::run(a1, a2); } } @@ -534,6 +560,7 @@ namespace CGAL } } }; + // Specialization for i=0 and j=0. template struct Group_attribute_functor_run { @@ -564,7 +591,7 @@ namespace CGAL { toSet=od; if ( a2!=NULL ) - { // TODO REMOVE ? + { Call_merge_functor::run(a1, a2); } } @@ -574,6 +601,7 @@ namespace CGAL } } }; + // Specialization for i=0 and j=1. template struct Group_attribute_functor_run { @@ -604,7 +632,7 @@ namespace CGAL { toSet=dh2; if ( a2!=NULL ) - { // TODO REMOVE ? + { Call_merge_functor::run(a1, a2); } } @@ -614,6 +642,7 @@ namespace CGAL } } }; + // Specialization for void attributes. template struct Group_attribute_functor_run { @@ -622,9 +651,20 @@ namespace CGAL typename CMap::Dart_handle ) {} }; - + // Specialization for i=j. Do nothing as j is the dimension to not consider. + template + struct Group_attribute_functor_run + { + static void run(CMap*, + typename CMap::Dart_handle, + typename CMap::Dart_handle) + {} + }; + // ************************************************************************** /// Functor used for sew to update the attributes of /// adart2 on the attributes of this dart, except for j-attributes. + /// (j is the dimension of the beta modified between adart1 and adart2, + /// so that after the modification we will have beta_j(adart1)==adart2) /// We define run to allows to use this functor with /// Foreach_enabled_attributes. /// If you know i at compiling time, use directly @@ -636,491 +676,442 @@ namespace CGAL static void run(CMap* amap, typename CMap::Dart_handle adart1, typename CMap::Dart_handle adart2) - { - Group_attribute_functor_run::run(amap,adart1,adart2); - } + { Group_attribute_functor_run::run(amap,adart1,adart2); } }; // ************************************************************************** - // Functor used to degroup the two n-attributes of the two darts, except the - // attribute of adim - template + // Beta functor, used to combine several beta. +#ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES + template + struct Beta_functor; + template + struct Beta_functor + { + static Dart_handle run(Dart_handle ADart, int B, Betas... betas) + { return Beta_functor::run(ADart->beta(B), + betas...); } + }; + template + struct Beta_functor + { + static Dart_handle run(Dart_handle ADart, int B) + { + CGAL_assertion( ADart!=NULL ); + return ADart->beta(B); + } + }; + // ************************************************************************** + template + struct Beta_functor_static; + template + struct Beta_functor_static + { + static Dart_handle run(Dart_handle ADart) + { return Beta_functor_static:: + run(ADart->beta()); } + }; + template + struct Beta_functor_static + { + static Dart_handle run(Dart_handle ADart) + { + CGAL_assertion( ADart!=NULL ); + return ADart->beta(); + } + }; +#endif //CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES + // ************************************************************************** + /// Functor used to call update_dart_of_attribute + /// on each i-cell attribute enabled + template + struct Update_dart_of_attribute_functor + { + template + static void run(CMap* amap, typename CMap::Dart_handle ah, int amark) + { amap->template update_dart_of_attribute(ah,amark); } + }; + + template::type> + struct Update_dart_of_one_attribute_functor + { + static void run(CMap* amap, typename CMap::Dart_handle ah, int amark) + { amap->template update_dart_of_attribute(ah,amark); } + }; + template + struct Update_dart_of_one_attribute_functor + { + static void run(CMap*, typename CMap::Dart_handle, int) + {} + }; + // ************************************************************************** + // Functor used to degroup one i-attribute of one i-cell in two, except the + // attribute of j. + template::type> struct Degroup_attribute_functor_run { static void run(CMap* amap, typename CMap::Dart_handle adart1, - typename CMap::Dart_handle adart2, int adim) + typename CMap::Dart_handle adart2) { - CGAL_assertion( adim==-1 || - (1<=adim && (unsigned int)adim<=CMap::dimension) ); - if (i!=adim ) + CGAL_static_assertion( i<=CMap::dimension ); + CGAL_static_assertion( i!=j ); + CGAL_static_assertion_msg + ( CMap::Helper::template Dimension_index::value>=0, + "Degroup_attribute_functor_run but i-attributes are disabled" ); + CGAL_assertion( adart1!=NULL && adart2!=NULL ); + CGAL_assertion( adart1!=CMap::null_dart_handle && + adart2!=CMap::null_dart_handle ); + + typename CMap::Helper::template Attribute_handle::type + a1=adart1->template attribute(); + + // If the two attributes are different, nothing to do. + if ( a1!=adart2->template attribute() || a1==NULL ) return; + + CGAL_assertion( (!belong_to_same_cell + (*amap, adart1, adart2)) ); + + typename CMap::Helper::template Attribute_handle::type + a2 = amap->template create_attribute(*a1); + + amap->template set_attribute(adart2, a2); + Call_split_functor::run(a1, a2); + } + }; + // Specialization for void attributes. + template + struct Degroup_attribute_functor_run + { + static void run(CMap*, + typename CMap::Dart_handle, + typename CMap::Dart_handle) + {} + }; + // Specialization for i==j. + template + struct Degroup_attribute_functor_run + { + static void run(CMap*, + typename CMap::Dart_handle, + typename CMap::Dart_handle) + {} + }; + // ************************************************************************** + /// Functor used by Test_split_attribute_functor_run to process one dart. + template + struct Test_split_attribute_functor_one_dart + { + typedef typename CMap::Dart_handle Dart_handle; + + // Test the split of the i-cell containing the given dart adart. + // When we process a dart, we search in the Unique_hash_map if its + // i-attribute was already found. If yes, it means that we already + // found an i-cell with this attribute, thus this attribute is split. + // We mark (with mark) all the darts of the i-cell containing adart to + // process them exactly once. + template + static void run( CMap* amap, + Dart_handle adart, + Unique_hash_map::type, int> & found_attributes, + int mark ) + { + CGAL_assertion( amap!=NULL ); + CGAL_assertion( adart!=NULL ); + CGAL_static_assertion_msg(CMap::Helper::template + Dimension_index::value>=0, + "Test_split_attribute_functor_one_dart but " + "i-attributes are disabled"); + + typedef typename CMap::Helper::template Attribute_handle::type + Attribute_handle_i; + + // If the current dart has no attribute, or if it is aldready marked, + // nothing to do. + if ( adart->template attribute()==NULL || + amap->is_marked(adart, mark) ) + return; + + Attribute_handle_i a1 = adart->template attribute(); + if ( found_attributes.is_defined(a1) ) + { // Here the attribute was already present in the hash_map + Attribute_handle_i a2 = amap->template create_attribute(*a1); + a2->set_dart(adart); + + for ( CMap_dart_iterator_basic_of_cell + itj(*amap, adart, mark); itj.cont(); ++itj ) + { + amap->template set_attribute_of_dart(itj, a2); + amap->mark(itj, mark); + } + Call_split_functor::run(a1, a2); + } + else { - amap->template degroup_enabled_attribute - ::type> - (adart1, adart2); + // Here the attribute was not in the hash_map. + found_attributes[a1]=1; + a1->set_dart(adart); + + for ( CMap_dart_iterator_basic_of_cell + itj(*amap, adart, mark); itj.cont(); ++itj ) + { + CGAL_assertion( itj->template attribute()==a1 ); + amap->mark(itj, mark); + } } } }; - template - struct Degroup_attribute_functor_run + // ************************************************************************** + /// Functor used for unsew to test if i-attributes are split after an + /// operation, except for j-attributes. + /// (j is the dimension of the beta modified for darts in modified_darts, + /// if j==0 modified_darts_2 are the darts modified for beta_1). + template::type> + struct Test_split_attribute_functor_run { - static void run(CMap* amap, - typename CMap::Dart_handle adart1, - typename CMap::Dart_handle adart2, int adim) + static void run( CMap* amap, + std::deque + *modified_darts, + std::deque + */*modified_darts2*/, + int mark_modified_darts=-1) { - CGAL_assertion( adim==-1 || - (1<=adim && (unsigned int)adim<=CMap::dimension) ); - typename CMap::Dart_handle od = adart1->other_extremity(); - if ( od!=NULL ) - amap->template degroup_enabled_attribute - <0, typename CMap::Helper::template Attribute_type<0>::type > - (od, adart2); + CGAL_static_assertion( 1<=i && i<=CMap::dimension ); + CGAL_assertion( i!=j ); + CGAL_assertion( amap!=NULL ); + CGAL_static_assertion_msg(CMap::Helper::template + Dimension_index::value>=0, + "Test_split_attribute_functor_run but " + "i-attributes are disabled"); - if ( adim!=1 ) + typedef typename CMap::Helper::template Attribute_handle::type + Attribute_handle_i; + + Unique_hash_map found_attributes; + + int mark = amap->get_new_mark(); // to mark incident cells. + typename std::deque::iterator + it=modified_darts->begin(); + for ( ; it!=modified_darts->end(); ++it ) { - od = adart2->other_extremity(); + Test_split_attribute_functor_one_dart:: + run(amap, *it, found_attributes, mark); + } + + // Now we unmark all the marked darts. + amap->negate_mark(mark); + for ( it=modified_darts->begin(); it!=modified_darts->end(); ++it ) + { + if ( mark_modified_darts!=-1 ) + amap->unmark(*it, mark_modified_darts); + + if ( !amap->is_marked(*it, mark) ) + mark_cell(*amap, *it, mark); + } + + CGAL_assertion( amap->is_whole_map_marked(mark) ); + amap->free_mark(mark); + } + }; + // Specialization for i=0 and 2<=j. + template + struct Test_split_attribute_functor_run + { + static void run( CMap* amap, + std::deque + *modified_darts, + std::deque + */*modified_darts2*/, + int mark_modified_darts=-1) + { + CGAL_assertion( j!=0 && j!=1 ); + CGAL_assertion( amap!=NULL ); + CGAL_static_assertion_msg(CMap::Helper::template + Dimension_index<0>::value>=0, + "Test_split_attribute_functor_run<0> but " + "0-attributes are disabled"); + + typedef typename CMap::Helper::template Attribute_handle<0>::type + Attribute_handle_0; + + Unique_hash_map found_attributes; + typename CMap::Dart_handle od=NULL; + + int mark = amap->get_new_mark(); // to mark incident cells. + typename std::deque::iterator + it=modified_darts->begin(); + for ( ; it!=modified_darts->end(); ++it ) + { + Test_split_attribute_functor_one_dart:: + run<0>(amap, *it, found_attributes, mark); + + od=(*it)->other_extremity(); if ( od!=NULL ) - { - amap->template degroup_enabled_attribute - <0, typename CMap::Helper::template Attribute_type<0>::type> - (adart1, od); - } + Test_split_attribute_functor_one_dart:: + run<0>(amap, od, found_attributes, mark); } + + // Now we unmark all the marked darts. + amap->negate_mark(mark); + for ( it=modified_darts->begin(); it!=modified_darts->end(); ++it ) + { + if ( mark_modified_darts!=-1 ) + amap->unmark(*it, mark_modified_darts); + + if ( !amap->is_marked(*it, mark) ) + mark_cell<0>(*amap, *it, mark); + + od=(*it)->other_extremity(); + if ( od!=NULL && !amap->is_marked(od, mark) ) + mark_cell<0>(*amap, od, mark); + } + + CGAL_assertion( amap->is_whole_map_marked(mark) ); + amap->free_mark(mark); } }; - template - struct Degroup_attribute_functor + // Specialization for i=0 and j=0. + template + struct Test_split_attribute_functor_run { - template - static void run(CMap* amap,typename CMap::Dart_handle adart1, - typename CMap::Dart_handle adart2, int adim) + }; + // Specialization for i=1 and j=0. + template + struct Test_split_attribute_functor_run + { + // No sense as we use always <0,0> ? + }; + // Specialization for void attributes. + template + struct Test_split_attribute_functor_run + { + }; + /// Functor used for unsew to test if i-attributes are split after an + /// operation, except for j-attributes. + /// We define run to allows to use this functor with + /// Foreach_enabled_attributes. + template + struct Test_split_attribute_functor + { + typedef typename CMap::Dart_handle Dart_handle; + + // Test the split of the i-cell containing dart adart. + template + static void test_one_dart( CMap* amap, + Dart_handle adart, + Unique_hash_map::type, int> & + found_attributes, int mark ) { - Degroup_attribute_functor_run::run(amap,adart1,adart2,adim); + typedef typename CMap::Helper::template Attribute_handle::type + Attribute_handle_i; + + if ( adart->template attribute()!=NULL && + !amap->is_marked(adart, mark) ) + { + Attribute_handle_i a1 = adart->template attribute(); + if ( found_attributes.is_defined(a1) ) + { // Here the attribute was already present in the hash_map + Attribute_handle_i a2 = amap->template create_attribute(*a1); + + for ( CMap_dart_iterator_basic_of_cell + itj(*amap, adart, mark); itj.cont(); ++itj ) + { + amap->template set_attribute_of_dart(itj, a2); + amap->mark(itj, mark); + } + a2->set_dart(adart); + Call_split_functor::run(a1, a2); + } + else + { + // Here the attribute was not in the hash_map. + found_attributes[a1]=1; + a1->set_dart(adart); + + for ( CMap_dart_iterator_basic_of_cell + itj(*amap, adart, mark); itj.cont(); ++itj ) + { + CGAL_assertion( itj->template attribute()==a1 ); + amap->mark(itj, mark); + } + } + } + } + + // Test the split of i-attributes, for all modified darts given in + // modified_darts, and marked with mark_modified_darts. + // For each split attribute, create a new i-attribute, associate + // it with the new i-cell and call onsplit functors. + template + static void run( CMap* amap, + std::deque + *modified_darts, + int mark_modified_darts=-1) + { + CGAL_assertion( i!=j ); + CGAL_assertion( amap!=NULL ); + + typedef typename CMap::Helper::template Attribute_handle::type + Attribute_handle_i; + + Unique_hash_map found_attributes; + + int mark = amap->get_new_mark(); // to mark incident cells. + for ( typename std::deque::iterator + it=modified_darts->begin(); it!=modified_darts->end(); ++it ) + { + test_one_dart(amap, *it, found_attributes, mark); + + if ( /*j!=1 &&*/ i==0 ) // TODO Here we test too many cases, but more works to do + { + typename CMap::Dart_handle od = (*it)->other_extremity(); + if ( od!=NULL ) + test_one_dart(amap, od, found_attributes, mark); + } + } + + // Now we unmark all the marked darts. + amap->negate_mark(mark); + for ( typename std::deque::iterator + it=modified_darts->begin(); it!=modified_darts->end(); ++it ) + { + if ( mark_modified_darts!=-1 ) + amap->unmark(*it, mark_modified_darts); + + if ( !amap->is_marked(*it, mark) ) + for ( CMap_dart_iterator_basic_of_cell + itj(*amap, *it, mark); itj.cont(); ++itj ) + { + amap->mark(itj, mark); + } + + if ( /*j!=1 &&*/ i==0 ) + { + Dart_handle od = (*it)->other_extremity(); + if ( od!=NULL && !amap->is_marked(od, mark) ) + for ( CMap_dart_iterator_basic_of_cell + itj(*amap, od, mark); itj.cont(); ++itj ) + { + amap->mark(itj, mark); + } + } + } + + CGAL_assertion( amap->is_whole_map_marked(mark) ); + amap->free_mark(mark); } }; - - //////////////////////////////////// - template - struct Couple_dart_and_dim - { - Couple_dart_and_dim(Dart_handle ad1,Dart_handle ad2,int adim) : - d1(ad1), d2(ad2), dim(adim) - {} - Dart_handle d1,d2; - int dim; - }; - - // Functor used to degroup one attribute of two given darts - template - struct Degroup_one_attribute_functor - { - static bool run(CMap* amap, - typename CMap::Dart_handle adart1, - typename CMap::Dart_handle adart2) - { - CGAL_assertion(amap!=NULL); - return amap->template degroup_enabled_attribute - (adart1,adart2); - } - }; - - // Specialization for i-attributes disabled. - template - struct Degroup_one_attribute_functor - { - static bool run(CMap*, - typename CMap::Dart_handle, - typename CMap::Dart_handle) - { return false; } - }; - - /// Functor used to call update_dart_of_attribute - /// on each i-cell attribute enabled - template - struct Update_dart_of_attribute_functor - { - template - static void run(CMap* amap, typename CMap::Dart_handle ah, int amark) - { amap->template update_dart_of_attribute(ah,amark); } - }; - - template::type> - struct Update_dart_of_one_attribute_functor - { - static void run(CMap* amap, typename CMap::Dart_handle ah, int amark) - { amap->template update_dart_of_attribute(ah,amark); } - }; - template - struct Update_dart_of_one_attribute_functor - { - static void run(CMap*, typename CMap::Dart_handle, int) - {} - }; - -#ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES - template - struct Beta_functor; - - template - struct Beta_functor - { - static Dart_handle run(Dart_handle ADart, int B, Betas... betas) - { return Beta_functor::run(ADart->beta(B), - betas...); } - }; - - template - struct Beta_functor - { - static Dart_handle run(Dart_handle ADart, int B) - { - CGAL_assertion( ADart!=NULL ); - return ADart->beta(B); - } - }; - - template - struct Beta_functor_static; - - template - struct Beta_functor_static - { - static Dart_handle run(Dart_handle ADart) - { return Beta_functor_static:: - run(ADart->beta()); } - }; - - template - struct Beta_functor_static - { - static Dart_handle run(Dart_handle ADart) - { - CGAL_assertion( ADart!=NULL ); - return ADart->beta(); - } - }; -#endif //CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES - - template - struct Store_incident_cells - { - template - static void run( CMap* amap, typename CMap::Dart_handle adart, - int mark_for_icell, - int* mark_for_incident_cells, - std::deque > - *store ) - { - if ( i==j ) return; - - const int mark_for_jcells = mark_for_incident_cells - [CMap::Helper::template Dimension_index::value]; - - std::deque >& jcells = - store[CMap::Helper::template Dimension_index::value]; - - CGAL_assertion( amap!=NULL ); - CGAL_assertion( adart!=NULL ); - CGAL_assertion( amap->is_reserved(mark_for_icell) ); - CGAL_assertion( amap->is_reserved(mark_for_jcells) ); - - if ( !amap->is_marked(adart, mark_for_jcells) && - adart->template attribute()!=NULL ) - { - jcells.push_back(std::deque()); - for ( CMap_dart_iterator_basic_of_cell - itj(*amap, adart, mark_for_jcells); itj.cont(); ++itj ) - { - if ( !amap->is_marked(itj, mark_for_icell) ) - { - jcells.back().push_back(itj); - } - amap->mark(itj, mark_for_jcells); - } - if ( jcells.back().empty() ) jcells.pop_back(); - } - - if ( i!=1 && j==0 ) - { - typename CMap::Dart_handle od = adart->other_extremity(); - - if ( od!=NULL && !amap->is_marked(od, mark_for_jcells) && - od->template attribute()!=NULL ) - { - jcells.push_back(std::deque()); - for ( CMap_dart_iterator_basic_of_cell - itj(*amap, od, mark_for_jcells); itj.cont(); ++itj ) - { - if ( !amap->is_marked(itj, mark_for_icell) ) - { - jcells.back().push_back(itj); - } - amap->mark(itj, mark_for_jcells); - } - if ( jcells.back().empty() ) jcells.pop_back(); - } - } - } - }; - - template - struct Test_split_with_deque - { - template - static void run( CMap* amap, - int* mark_for_incident_cells, - std::deque > - *store ) - { - const int mark_for_jcells = mark_for_incident_cells - [CMap::Helper::template Dimension_index::value]; - amap->negate_mark( mark_for_jcells ); - - if ( i==j ) return; - - std::deque >& jcells = - store[CMap::Helper::template Dimension_index::value]; - - CGAL_assertion( amap!=NULL ); - CGAL_assertion( amap->is_reserved(mark_for_jcells) ); - - int nbofjcell = 0; - typename CMap::Helper::template Attribute_handle::type - a1 = NULL; - typename CMap::Helper::template Attribute_handle::type - a2=NULL; - - int nb=0; - for ( typename std::deque >:: - iterator it=jcells.begin(); it!=jcells.end(); ++it ) - { - nbofjcell = 0; - for ( typename std::deque::iterator - itj=it->begin(); itj!=it->end(); ++itj ) - { - if ( !amap->is_marked(*itj, mark_for_jcells) ) - { - ++nbofjcell; - if ( nbofjcell>1 ) - { - a2 = amap->template create_attribute(*a1); - // std::cout<<"A2 "<<&*a2<<" "<<&**itj<<": "; - // We call the on_split functor - } - else - { - a1=(*itj)->template attribute(); - a1->set_dart(*itj); - // std::cout<<"A1 "<<&*a1<<" "<<&**itj<<": "; - } - - for ( CMap_dart_iterator_basic_of_cell - itj2(*amap, *itj, mark_for_jcells); - itj2.cont(); ++itj2 ) - { - // std::cout<<&*itj2<<", "; - if ( nbofjcell>1 ) - amap->template set_attribute_of_dart(itj2, a2); - ++nb; - amap->mark(itj2, mark_for_jcells); - } - // std::cout<1 ) - Apply_cell_functor - ::type, - typename CMap::Helper::template Attribute_type::type:: - On_split>::run(*a1, *a2); - } - } - } - //std::cout<<"number of marked darts for <"< : "<number_of_marked_darts(mark_for_jcells)< - struct Test2_split_with_deque - { - template - static void test_one_dart( CMap* amap, - typename CMap::Dart_handle adart, - std::set::type>& found_attributes, - int mark) - { - if ( adart->template attribute()!=NULL && - !amap->is_marked(adart, mark) ) - { - typename CMap::Helper::template Attribute_handle::type - a1 = adart->template attribute(); - if ( !found_attributes.insert(a1).second ) - { // Here the attribute was already present in the set - typename CMap::Helper::template Attribute_handle::type - a2 = amap->template create_attribute(*a1); - // std::cout<<"A2 "<<&*a2<<" "<<&**itj<<": "; - - for ( CMap_dart_iterator_basic_of_cell - itj(*amap, adart, mark); - itj.cont(); ++itj ) - { - // std::cout<<&*itj<<", "; - amap->template set_attribute_of_dart(itj, a2); - amap->mark(itj, mark); - } - - Apply_cell_functor - ::type, - typename CMap::Helper::template Attribute_type::type:: - On_split>::run(*a1, *a2); - } - else - { - // Here the attribute was not in the set as we are able - // to insert it. - a1->set_dart(adart); - // std::cout<<"A1 "<<&*a1<<" "<<&**itj<<": "; - - for ( CMap_dart_iterator_basic_of_cell - itj(*amap, adart, mark); - itj.cont(); ++itj ) - { - // std::cout<<&*itj<<", "; - CGAL_assertion( itj->template attribute()==a1 ); - amap->mark(itj, mark); - } - } - // std::cout< - static void run( CMap* amap, - std::deque - *modified_darts, - int mark_modified_darts - /*, - std::deque - *modified_darts2*/) - { - if ( i==j ) return; - - CGAL_assertion( amap!=NULL ); - - std::set::type> found_attributes; - - int mark = amap->get_new_mark(); - int nb=0; - for ( typename std::deque:: - iterator it=modified_darts->begin(); - it!=modified_darts->end(); ++it ) - { - test_one_dart(amap, *it, found_attributes, mark); - - if ( i!=1 && j==0 ) - { - typename CMap::Dart_handle od = (*it)->other_extremity(); - if ( od!=NULL ) - test_one_dart(amap, od, found_attributes, mark); - } - } - -/* if ( i+1==j ) - { - for ( typename std::deque:: - iterator it=modified_darts2->begin(); - it!=modified_darts2->end(); ++it ) - { - test_one_dart(amap, *it, found_attributes, mark); - - if ( i!=1 && j==0 ) - { - typename CMap::Dart_handle od = (*it)->other_extremity(); - if ( od!=NULL ) - test_one_dart(amap, od, found_attributes, mark); - } - } - }*/ - // std::cout<<"Size of set for dim "<size()<number_of_marked_darts(mark)<negate_mark(mark); - - for ( typename std::deque:: - iterator it=modified_darts->begin(); - it!=modified_darts->end(); ++it ) - { - if ( mark_modified_darts!=-1 ) - amap->unmark(*it, mark_modified_darts); - - if ( !amap->is_marked(*it, mark) ) - for ( CMap_dart_iterator_basic_of_cell - itj(*amap, *it, mark); - itj.cont(); ++itj ) - { - amap->mark(itj, mark); - } - - if ( i!=1 && j==0 ) - { - typename CMap::Dart_handle od = (*it)->other_extremity(); - if ( od!=NULL && !amap->is_marked(od, mark) ) - for ( CMap_dart_iterator_basic_of_cell - itj(*amap, od, mark); - itj.cont(); ++itj ) - { - amap->mark(itj, mark); - } - } - } - - /* if ( i+1==j ) - { - for ( typename std::deque:: - iterator it=modified_darts2->begin(); - it!=modified_darts2->end(); ++it ) - { - if ( mark_modified_darts!=-1 ) - amap->unmark(*it, mark_modified_darts); - - if ( !amap->is_marked(*it, mark) ) - for ( CMap_dart_iterator_basic_of_cell - itj(*amap, *it, mark); - itj.cont(); ++itj ) - { - amap->mark(itj, mark); - } - - if ( i!=1 && j==0 ) - { - typename CMap::Dart_handle od = (*it)->other_extremity(); - if ( od!=NULL && !amap->is_marked(od, mark) ) - for ( CMap_dart_iterator_basic_of_cell - itj(*amap, od, mark); - itj.cont(); ++itj ) - { - amap->mark(itj, mark); - } - } - } - }*/ - - CGAL_assertion( amap->is_whole_map_marked(mark) ); - amap->free_mark(mark); - } - }; - } // namespace internal } // namespace CGAL diff --git a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_sewable.h b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_sewable.h new file mode 100644 index 00000000000..57334ff0d5a --- /dev/null +++ b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_sewable.h @@ -0,0 +1,343 @@ +// 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_SEWABLE_H +#define CGAL_COMBINATORIAL_MAP_SEWABLE_H + +/* Definition of functor used to test if two darts are i-sewable + * (we use functors as there are different specializations). + */ +namespace CGAL +{ +namespace internal +{ +// Generic case for 2<=i<=dimension, and 3 +struct Is_sewable_functor +{ + static bool run( const CMap* amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2 ) + { + CGAL_assertion( 2<=i && i<=CMap::dimension ); + CGAL_assertion( 3template is_free() || + !adart2->template is_free() || adart1==adart2 ) + return false; + + // TODO use a map (of hashtable) to build the isomorphism and to test + // it during the while loop + CMap_dart_const_iterator_of_involution I1(*amap, adart1); + CMap_dart_const_iterator_of_involution_inv I2(*amap, adart2); + bool res = true; + while (res && I1.cont() && I2.cont()) + { + // We can remove this constraint which is not required for + // combinatorial map definition, but which is quite "normal" + if ( I1==adart2 || I2==adart1 ) res=false; + + // Special case to consider beta0 and beta1 + if ( i>2 ) + { + if ( I1->is_free(0)!=I2->is_free(1) ) res = false; + else if ( I1->is_free(1)!=I2->is_free(0) ) res = false; + } + + // General case + for (unsigned int j=2;res && j<=CMap::dimension; ++j) + { + if ( j+1!=i && j!=i && j!=i+1 && + I1->is_free(j)!=I2->is_free(j) ) + { res = false; } + } + ++I1; ++I2; + } + if (I1.cont() != I2.cont()) + res = false; + + return res; + } +}; + +// Specialization for i=0 and 3 +struct Is_sewable_functor +{ + static bool run( const CMap* amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2 ) + { + CGAL_assertion( 3template is_free<0>() || + !adart2->template is_free<1>() ) + return false; + + if ( adart1==adart2 ) return true; + + // TODO use a map (of hashtable) to build the isomorphism and to test + // it during the while loop + CMap_dart_const_iterator_of_involution I1(*amap, adart1); + CMap_dart_const_iterator_of_involution_inv I2(*amap, adart2); + bool res = true; + while (res && I1.cont() && I2.cont()) + { + // We can remove this constraint which is not required for + // combinatorial map definition, but which imposes quite "normal" + // configurations + if ( I1==adart2 || I2==adart1 ) res=false; + + for (unsigned int j=3;res && j<=CMap::dimension; ++j) + { + if ( I1->is_free(j)!=I2->is_free(j) ) + { + res = false; + } + } + ++I1; ++I2; + } + if (I1.cont() != I2.cont()) + res = false; + + return res; + } +}; + +// Specialization for i=0 and dim=1. +template +struct Is_sewable_functor +{ + static bool run( const CMap* amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2 ) + { + CGAL_assertion(adart1!=NULL && adart2!=NULL); + CGAL_assertion(adart1!=CMap::null_dart_handle && + adart2!=CMap::null_dart_handle); + + if ( !adart1->template is_free<0>() || + !adart2->template is_free<1>() ) + return false; + return true; + } +}; +// Specialization for i=1 and dim=1. +template +struct Is_sewable_functor +{ + static bool run( const CMap* amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2 ) + { + CGAL_assertion(adart1!=NULL && adart2!=NULL); + CGAL_assertion(adart1!=CMap::null_dart_handle && + adart2!=CMap::null_dart_handle); + + if ( !adart1->template is_free<1>() || + !adart2->template is_free<0>() ) + return false; + return true; + } +}; + +// Specialization for i=0 and dim=2. +template +struct Is_sewable_functor +{ + static bool run( const CMap* amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2 ) + { + CGAL_assertion(adart1!=NULL && adart2!=NULL); + CGAL_assertion(adart1!=CMap::null_dart_handle && + adart2!=CMap::null_dart_handle); + + if ( !adart1->template is_free<0>() || + !adart2->template is_free<1>() ) + return false; + return true; + } +}; +// Specialization for i=1 and dim=2. +template +struct Is_sewable_functor +{ + static bool run( const CMap* amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2 ) + { + CGAL_assertion(adart1!=NULL && adart2!=NULL); + CGAL_assertion(adart1!=CMap::null_dart_handle && + adart2!=CMap::null_dart_handle); + + if ( !adart1->template is_free<1>() || + !adart2->template is_free<0>() ) + return false; + return true; + } +}; +// Specialization for i=2 and dim=2. +template +struct Is_sewable_functor +{ + static bool run( const CMap* amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2 ) + { + CGAL_assertion(adart1!=NULL && adart2!=NULL); + CGAL_assertion(adart1!=CMap::null_dart_handle && + adart2!=CMap::null_dart_handle); + + if ( !adart1->template is_free<2>() || + !adart2->template is_free<2>() || adart1==adart2 ) + return false; + return true; + } +}; + +// Specialization for i=0 and dim=3. +template +struct Is_sewable_functor +{ + static bool run( const CMap* amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2 ) + { + CGAL_assertion(adart1!=NULL && adart2!=NULL); + CGAL_assertion(adart1!=CMap::null_dart_handle && + adart2!=CMap::null_dart_handle); + + if ( !adart1->template is_free<0>() || + !adart2->template is_free<1>() ) + return false; + + if ( adart1->template is_free<3>() ) + { + if ( !adart2->template is_free<3>() ) return false; + return true; + } + + // Here adart1 is not 3-free + if ( adart2->template is_free<3>() ) return false; + + CGAL_assertion( adart1->template beta<3>()->template is_free<1>() && + adart2->template beta<3>()->template is_free<0>() ); + return true; + } +}; +// Specialization for i=1 and dim=3. +template +struct Is_sewable_functor +{ + static bool run( const CMap* amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2 ) + { + CGAL_assertion(adart1!=NULL && adart2!=NULL); + CGAL_assertion(adart1!=CMap::null_dart_handle && + adart2!=CMap::null_dart_handle); + + if ( !adart1->template is_free<1>() || + !adart2->template is_free<0>() ) + return false; + + if ( adart1->template is_free<3>() ) + { + if ( !adart2->template is_free<3>() ) return false; + return true; + } + + // Here adart1 is not 3-free + if ( adart2->template is_free<3>() ) return false; + + CGAL_assertion( adart1->template beta<3>()->template is_free<0>() && + adart2->template beta<3>()->template is_free<1>() ); + return true; + } +}; +// Specialization for i=2 and dim=3. +template +struct Is_sewable_functor +{ + static bool run( const CMap* amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2 ) + { + CGAL_assertion(adart1!=NULL && adart2!=NULL); + CGAL_assertion(adart1!=CMap::null_dart_handle && + adart2!=CMap::null_dart_handle); + + if ( !adart1->template is_free<2>() || + !adart2->template is_free<2>() || adart1==adart2 ) + return false; + return true; + } +}; +// Specialization for i=3 and dim=3. +template +struct Is_sewable_functor +{ + static bool run( const CMap* amap, + typename CMap::Dart_const_handle adart1, + typename CMap::Dart_const_handle adart2 ) + { + CGAL_assertion(adart1!=NULL && adart2!=NULL); + CGAL_assertion(adart1!=CMap::null_dart_handle && + adart2!=CMap::null_dart_handle); + + if ( !adart1->template is_free<3>() || + !adart2->template is_free<3>() ) + return false; + + CMap_dart_const_iterator_basic_of_orbit I1(*amap, adart1); + CMap_dart_const_iterator_basic_of_orbit I2(*amap, adart2); + bool res=true; + while (res && I1.cont() && I2.cont()) + { + CGAL_assertion( I1->template is_free<3>() || + I2->template is_free<3>() ); + + // We can remove this constraint which is not required for + // combinatorial map definition, but which is quite "normal" as it avoid + // fold cells. + if ( I1==adart2 || I2==adart1 ) res=false; + else if ( I1.prev_operation()!=I2.prev_operation() ) res=false; + + ++I1; ++I2; + } + if ( I1.cont()!=I2.cont() ) + res=false; + + return res; + } +}; + +} //namespace internal + +} //namespace CGAL + +#endif // CGAL_COMBINATORIAL_MAP_SEWABLE_H +//****************************************************************************** diff --git a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_utility.h b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_utility.h index e5ff2591721..6051a9717b1 100644 --- a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_utility.h +++ b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_utility.h @@ -26,6 +26,13 @@ #include +/** Some utilities allowing to manage attributes. Indeed, as they as stores + * in tuples, we need to define functors with variadic templated arguments + * to deal with these attributes. + * + * The class Combinatorial_map_helper defines: + * + */ namespace CGAL { namespace internal @@ -659,6 +666,6 @@ namespace CGAL } //namespace internal - } //namespace CGAL +} //namespace CGAL #endif //CGAL_INTERNAL_COMBINATORIAL_MAP_UTILITY_H