diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map.h b/Combinatorial_map/include/CGAL/Combinatorial_map.h index 93a164fc468..94df0748b38 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map.h @@ -56,6 +56,9 @@ namespace CGAL { template friend struct Remove_cell_functor; + template + friend struct Contract_cell_functor; + template friend typename Map::Dart_handle insert_cell_0_in_cell_1(Map& amap, typename Map::Dart_handle adart); diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map_constructors.h b/Combinatorial_map/include/CGAL/Combinatorial_map_constructors.h index 19d2edba896..fcd9a97836e 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map_constructors.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map_constructors.h @@ -64,6 +64,32 @@ namespace CGAL { return start; } +/** Test if a face is a combinatorial polygon of length alg + * (a cycle of alg darts beta1 links together). + * @param amap the used combinatorial map. + * @param adart an intial dart + * @return true iff the face containing adart is a polygon of length alg. + */ +template < class Map > +bool is_face_combinatorial_polygon(const Map& amap, + typename Map::Dart_const_handle adart, + unsigned int alg) +{ + CGAL_assertion(alg>0); + CGAL_assertion(adart!=NULL); + + unsigned int nb = 0; + typename Map::Dart_const_handle cur = adart; + do + { + ++nb; + if ( cur==Map::null_dart_handle ) return false; // Open face + cur = cur->beta(1); + } + while( cur!=adart ); + return (nb==alg); +} + /** Create a combinatorial tetrahedron from 4 triangles. * @param amap the used combinatorial map. * @param d1 a dart onto a first triangle. @@ -90,6 +116,45 @@ namespace CGAL { return d1; } +/** Test if a volume is a combinatorial tetrahedron. + * @param amap the used combinatorial map. + * @param adart an intial dart + * @return true iff the volume containing adart is a combinatorial tetrahedron. + */ +template < class Map > +bool is_volume_combinatorial_tetrahedron(const Map& amap, + typename Map::Dart_const_handle d1) +{ + CGAL_assertion(d1!=NULL); + + typename Map::Dart_const_handle d2 = d1->beta(2); + typename Map::Dart_const_handle d3 = d2->beta(0)->beta(2); + typename Map::Dart_const_handle d4 = d2->beta(1)->beta(2); + + if ( d1==Map::null_dart_handle || d2==Map::null_dart_handle || + d3==Map::null_dart_handle || d4==Map::null_dart_handle ) return false; + + if ( !is_face_combinatorial_polygon(amap, d1, 3) || + !is_face_combinatorial_polygon(amap, d2, 3) || + !is_face_combinatorial_polygon(amap, d3, 3) || + !is_face_combinatorial_polygon(amap, d4, 3) ) return false; + + // TODO do better with marks (?). + if ( belong_to_same_cell(amap, d1, d2) || + belong_to_same_cell(amap, d1, d3) || + belong_to_same_cell(amap, d1, d4) || + belong_to_same_cell(amap, d2, d3) || + belong_to_same_cell(amap, d2, d4) || + belong_to_same_cell(amap, d3, d4) ) return false; + + if ( amap.beta(d1,1,2)!=amap.beta(d3,0) || + amap.beta(d4,0,2)!=amap.beta(d3,1) || + amap.beta(d4,1,2)!=amap.beta(d1,0) ) return false; + + return true; +} + + /** Create a new combinatorial tetrahedron. * @param amap the used combinatorial map. * @return a new dart. @@ -156,6 +221,63 @@ namespace CGAL { return d1; } +/** Test if a volume is a combinatorial hexahedron. + * @param amap the used combinatorial map. + * @param adart an intial dart + * @return true iff the volume containing adart is a combinatorial hexahedron. + */ +template < class Map > +bool is_volume_combinatorial_hexahedron(const Map& amap, + typename Map::Dart_const_handle d1) +{ + CGAL_assertion(d1!=NULL); + + typename Map::Dart_const_handle d2 = d1->beta(1)->beta(1)->beta(2); + typename Map::Dart_const_handle d3 = d2->beta(1)->beta(1)->beta(2); + typename Map::Dart_const_handle d4 = d3->beta(1)->beta(1)->beta(2); + typename Map::Dart_const_handle d5 = d1->beta(0)->beta(2); + typename Map::Dart_const_handle d6 = d4->beta(1)->beta(2); + + if ( d1==Map::null_dart_handle || d2==Map::null_dart_handle || + d3==Map::null_dart_handle || d4==Map::null_dart_handle || + d5==Map::null_dart_handle || d6==Map::null_dart_handle ) return false; + + if (!is_face_combinatorial_polygon(amap, d1, 4) || + !is_face_combinatorial_polygon(amap, d2, 4) || + !is_face_combinatorial_polygon(amap, d3, 4) || + !is_face_combinatorial_polygon(amap, d4, 4) || + !is_face_combinatorial_polygon(amap, d5, 4) || + !is_face_combinatorial_polygon(amap, d6, 4) ) return false; + + // TODO do better with marks. + if ( belong_to_same_cell(amap, d1, d2) || + belong_to_same_cell(amap, d1, d3) || + belong_to_same_cell(amap, d1, d4) || + belong_to_same_cell(amap, d1, d5) || + belong_to_same_cell(amap, d1, d6) || + belong_to_same_cell(amap, d2, d3) || + belong_to_same_cell(amap, d2, d4) || + belong_to_same_cell(amap, d2, d5) || + belong_to_same_cell(amap, d2, d6) || + belong_to_same_cell(amap, d3, d4) || + belong_to_same_cell(amap, d3, d5) || + belong_to_same_cell(amap, d3, d6) || + belong_to_same_cell(amap, d4, d5) || + belong_to_same_cell(amap, d4, d6) || + belong_to_same_cell(amap, d5, d6) ) + return false; + + if ( amap.beta(d1,2) !=amap.beta(d4,1,1) || + amap.beta(d1,1,2) !=amap.beta(d6,0) || + amap.beta(d3,1,2) !=amap.beta(d6,1) || + amap.beta(d3,0,2) !=amap.beta(d5,1,1) || + amap.beta(d6,1,1,2)!=amap.beta(d2,1) || + amap.beta(d5,0,2) !=amap.beta(d4,0) || + amap.beta(d5,1,2) !=amap.beta(d2,0) ) return false; + + return true; +} + /** Create a new combinatorial hexahedron. * @param amap the used combinatorial map. * @return a new dart. diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h b/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h index 6457c94fa49..2fcc17cb842 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h @@ -37,7 +37,7 @@ namespace CGAL { * @return A dart incident to the new vertex. */ template < class Map > - typename Map::Dart_handle + typename Map::Dart_handle insert_cell_0_in_cell_2(Map& amap, typename Map::Dart_handle adart) { CGAL_assertion(adart != NULL && adart!=Map::null_dart_handle); @@ -51,9 +51,9 @@ namespace CGAL { while (!first->is_free(0) && first->beta(0) != adart) first = first->beta(0); - // Stack of couple of dart and dimension for which + // Stack of couple of dart and dimension for which // we must call on_split functor - std::stack > + std::stack > tosplit; // Mark used to mark darts already treated. @@ -61,7 +61,7 @@ namespace CGAL { // 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();) @@ -75,7 +75,7 @@ namespace CGAL { { if ( amap.template degroup_attribute_of_dart<2, typename Map::template Dart_of_involution_range<1> > - (first, cur) ) + (first, cur) ) tosplit.push(internal::Couple_dart_and_dim (first,cur,2)); @@ -83,14 +83,14 @@ namespace CGAL { if (!cur->is_free(0)) { - n1 = amap.create_dart(); + n1 = amap.create_dart(); amap.link_beta_0(cur, n1); } else n1 = NULL; if (!cur->is_free(1)) { - n2 = amap.create_dart(); + n2 = amap.create_dart(); amap.link_beta_1(cur, n2); } else n2 = NULL; @@ -107,7 +107,7 @@ namespace CGAL { { if ( !amap.is_marked(cur->beta(dim), treated) ) { - if (n1!=NULL) + if (n1!=NULL) { nn1=amap.create_dart(); amap.link_beta_1(cur->beta(dim), nn1); @@ -125,7 +125,7 @@ namespace CGAL { if (nn1 != NULL && nn2 != NULL) amap.basic_link_beta_1(nn1, nn2); - + if (nn1 != NULL && prev != NULL) amap.link_beta_for_involution(nn1, prev->beta(dim), 2); @@ -166,20 +166,20 @@ namespace CGAL { 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); } - + return n1; } - /** Test if a i-cell can be removed. - * An i-cell can be removed if i==Map::dimension, - * or if there are at most two (i+1)-cell incident to it. + /** Test if an i-cell can be removed. + * An i-cell can be removed if i==Map::dimension or i==Map::dimension-1, + * or if there are at most two (i+1)-cell incident to it. * @param adart a dart of the i-cell. * @return true iff the i-cell can be removed. */ @@ -193,7 +193,7 @@ namespace CGAL { if ( i==Map::dimension-1 ) return true; // TODO ? Optimisation for dim-2, and to not test all - // the darts of the cell ? + // the darts of the cell ? bool res = true; for (CMap_dart_const_iterator_of_cell it(amap, adart); res && it.cont(); ++it) @@ -204,11 +204,11 @@ namespace CGAL { return res; } - /** Remove a i-cell, 0 struct Remove_cell_functor @@ -217,42 +217,41 @@ namespace CGAL { { CGAL_static_assertion ( 1<=i && i(amap, adart)) ); - - size_t res = 0; - - // 1) We group the two (i+1)-cells if they exist. - if (!adart->is_free(i+1)) - amap.template group_attribute(adart, adart->beta(i+1)); - + typename Map::Dart_handle d1, d2; int mark = amap.get_new_mark(); - std::vector to_erase; - - // 2) We mark all the darts of the i-cell. + std::deque to_erase; + + const int iinv = CGAL_BETAINV(i); + + int mark_for_incident_cells[Map::Helper::nb_attribs]; + std::deque > + incident_cells[Map::Helper::nb_attribs]; + + for (int j=0; j it(amap,adart,mark); - it.cont(); ++it ) - { - to_erase.push_back(it); - amap.mark(it,mark); - ++res; - } + mark_for_incident_cells [j] = amap.get_new_mark(); + CGAL_assertion( mark_for_incident_cells [j]!=-1 ); } - - // Stack of couple of dart for which we must call degroup_all_attributes + + size_t res = 0; + for ( CMap_dart_iterator_basic_of_cell it(amap,adart,mark); + it.cont(); ++it ) + { + to_erase.push_back(it); + amap.mark(it, mark); + ++res; + } + typedef std::pair Dart_pair; - std::stack todegroup; + std::deque tolink; + std::deque tounlink; + std::deque tounlinkinv; - // 3) We modify the darts of the cells incident to the removed i-cell - // when they are marked to remove. - typename std::vector::iterator it = + typename std::deque::iterator it = to_erase.begin(); for (; it != to_erase.end(); ++it) - { amap.update_dart_of_all_attributes(*it, mark); } - - // 4) For each dart of the cell, we modify i-link of neighbors. - for ( it=to_erase.begin(); it != to_erase.end(); ++it) { d1 = (*it)->beta_inv(i); while ( d1!=Map::null_dart_handle && amap.is_marked(d1, mark) ) @@ -260,81 +259,118 @@ namespace CGAL { d1 = d1->beta(i+1)->beta_inv(i); if (d1 == (*it)->beta_inv(i)) d1 = Map::null_dart_handle; } - + d2 = (*it)->beta(i+1)->beta(i); while ( d2!=Map::null_dart_handle && amap.is_marked(d2, mark) ) { d2 = d2->beta(i+1)->beta(i); if ( d2==(*it)->beta(i+1)->beta(i) ) d2=Map::null_dart_handle; } - + // TODO ? We can optimize by using map.basic_link_beta but we // need to mark the second dart to not process another time... if (d1 != Map::null_dart_handle) { - if (d2 != Map::null_dart_handle) + if (d2 != Map::null_dart_handle) { - d1->basic_link_beta(d2, i); - // Here special case for edge, TODO special method ? - if ( i==1 ) d2->basic_link_beta(d1, 0); + if ( i==1 || d1is_free(i) ) { - if ( !amap.is_marked(d1->beta(i), mark) ) - todegroup.push(Dart_pair(d1, d1->beta(i))); - d1->unlink_beta(i); + tounlink.push_back(d1); + Map::Helper::template Foreach_enabled_attributes + >:: + run(&amap, d1, mark, &mark_for_incident_cells[0], + &incident_cells[0]); } } } - else if (d2 != Map::null_dart_handle) + else if (d2 != Map::null_dart_handle) { - if ( !d2->is_free(CGAL_BETAINV(i)) ) + if ( !d2->is_free(iinv) ) { - if ( !amap.is_marked(d2->beta_inv(i), mark) ) - todegroup.push(Dart_pair(d2, d2->beta_inv(i))); - d2->unlink_beta(CGAL_BETAINV(i)); + tounlinkinv.push_back(d2); + Map::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(CGAL_BETAINV(i)) ) + if ( !d1->is_free(iinv) ) { - if ( !amap.is_marked(d1->beta_inv(i), mark)) - todegroup.push(Dart_pair(d1, d1->beta_inv(i))); - d1->unlink_beta(CGAL_BETAINV(i)); - } + tounlinkinv.push_back(d1); + Map::Helper::template Foreach_enabled_attributes + >:: + run(&amap, d1, mark, &mark_for_incident_cells[0], + &incident_cells[0]); + } } } - - // 5) We degroup all the pair - while ( !todegroup.empty() ) + + // 2) We group the two (i+1)-cells if they exist. + // TODO assert que dans i+1 il y a 0, 1 ou 2 cells; et appeler group + // que dans le cas ou il y en a 2 et que on a deux brins tq .... + if ( !tolink.empty() ) { - Dart_pair p=todegroup.top(); - todegroup.pop(); - amap.degroup_all_attributes(p.first,p.second); + Dart_pair & p=tolink.back(); + amap.template group_attribute(p.first, p.second); } - + + // 4) For each dart of the cell, we modify i-link of neighbors. + for ( typename std::deque::iterator + it=tounlink.begin(); it!=tounlink.end(); ++it ) + { + (*it)->unlink_beta(i); + } + for ( typename std::deque::iterator + it=tounlinkinv.begin(); it!=tounlinkinv.end(); ++it ) + { + (*it)->unlink_beta(iinv); + } + for ( typename std::deque::iterator + it=tolink.begin(); it!=tolink.end(); ++it ) + { + (*it).first->basic_link_beta((*it).second, i); + (*it).second->basic_link_beta((*it).first, iinv); + } + // 6) We remove all the darts of the cell. for ( it=to_erase.begin(); it!=to_erase.end(); ++it ) { amap.erase_dart(*it); } CGAL_assertion( amap.is_whole_map_unmarked(mark) ); amap.free_mark(mark); - + + Map::Helper::template Foreach_enabled_attributes + >:: + run(&amap, &mark_for_incident_cells[0], + &incident_cells[0]); + + for (int j=0; j struct Remove_cell_functor @@ -342,11 +378,11 @@ namespace CGAL { static size_t run(Map& amap, typename Map::Dart_handle adart) { CGAL_assertion( adart!=NULL ); - + std::vector to_erase; int mark = amap.get_new_mark(); size_t res = 0; - + // Stack of couple of dart for which we must call degroup_all_attributes typedef std::pair Dart_pair; @@ -354,7 +390,7 @@ namespace CGAL { // 1) We mark all the darts of the d-cell. { - for (CMap_dart_iterator_basic_of_cell + for (CMap_dart_iterator_basic_of_cell it(amap,adart,mark); it.cont(); ++it) { to_erase.push_back(it); @@ -362,40 +398,40 @@ namespace CGAL { ++res; } } - + // 2) We update the cells incident to the remove volume. typename std::vector::iterator it = to_erase.begin(); for (; it != to_erase.end(); ++it) { amap.update_dart_of_all_attributes(*it, mark); } - + // 3) We unlink all the darts of the volume for beta-d. for ( it = to_erase.begin(); it != to_erase.end(); ++it ) - { + { if ( !(*it)->is_free(Map::dimension) ) { todegroup.push(Dart_pair(*it, (*it)->beta(Map::dimension))); amap.unlink_beta_for_involution(*it,Map::dimension); } - } - + } + // 4) We degroup all the pairs while ( !todegroup.empty() ) { - Dart_pair p=todegroup.top(); - todegroup.pop(); + Dart_pair & p=todegroup.top(); amap.degroup_all_attributes(p.first,p.second); + todegroup.pop(); } // 5) last, we remove all the darts of the d-cell. for ( it = to_erase.begin(); it != to_erase.end(); ++it ) { amap.erase_dart(*it); } - + CGAL_assertion( amap.is_whole_map_unmarked(mark) ); amap.free_mark(mark); //CGAL_postcondition(amap.is_valid()); - + return res; } }; @@ -413,27 +449,27 @@ namespace CGAL { CGAL_assertion( (is_removable(amap,adart)) ); size_t res = 0; - + // Stack of couple of dart for which we must call degroup_all_attributes typedef std::pair Dart_pair; std::stack todegroup; - + // 1) We group the two edges if they exist. - if (!adart->is_free(0)) + if (!adart->is_free(0)) amap.template group_attribute<1>(adart, adart->beta(0)); typename Map::Dart_handle d1, d2; int mark = amap.get_new_mark(); std::vector to_erase; - + // 2) We mark all the darts of the vertex. { for ( CMap_dart_iterator_basic_of_cell it(amap,adart,mark); it.cont(); ++it ) { to_erase.push_back(it); - amap.mark(it,mark); + amap.mark(it,mark); ++res; } } @@ -444,7 +480,7 @@ namespace CGAL { it = to_erase.begin(); for (; it != to_erase.end(); ++it) { amap.update_dart_of_all_attributes(*it, mark); } - + // 4) For each dart of the cell, we modify link of neighbors. for ( it=to_erase.begin(); it!=to_erase.end(); ++it ) { @@ -457,7 +493,7 @@ namespace CGAL { todegroup.push(Dart_pair((*it)->beta(0), *it)); (*it)->beta(0)->unlink_beta(1); } - + for ( unsigned int j=2; j<=Map::dimension; ++j ) { if ( !(*it)->is_free(j) ) @@ -472,7 +508,7 @@ namespace CGAL { todegroup.push(Dart_pair((*it)->beta(1), *it)); (*it)->beta(1)->unlink_beta(0); } - + for ( unsigned int j=2; j<=Map::dimension; ++j ) { if ( !(*it)->is_free(j) ) @@ -480,29 +516,29 @@ namespace CGAL { } } } - + // 5) We degroup all the pairs while ( !todegroup.empty() ) { - Dart_pair p=todegroup.top(); - todegroup.pop(); + Dart_pair & p=todegroup.top(); amap.degroup_all_attributes(p.first,p.second); + todegroup.pop(); } - + // 6) We remove all the darts of the cell. for (it = to_erase.begin(); it != to_erase.end(); ++it) { amap.erase_dart(*it); } - + CGAL_assertion( amap.is_whole_map_unmarked(mark) ); amap.free_mark(mark); - + // CGAL_postcondition( amap.is_valid() ); - + return res; } }; - /** Remove a i-cell, 0<=i<=dimension. + /** Remove an i-cell, 0<=i<=dimension. * @param amap the used combinatorial map. * @param adart a dart of the i-cell to remove. * @return the number of deleted darts. @@ -524,7 +560,7 @@ namespace CGAL { { CGAL_assertion(adart1 != NULL && adart2 != NULL); if ( adart1==adart2 ) return false; - for ( CMap_dart_const_iterator_of_orbit it(amap,adart1); + for ( CMap_dart_const_iterator_of_orbit it(amap,adart1); it.cont(); ++it ) { if ( it==adart2 ) return true; @@ -532,6 +568,152 @@ namespace CGAL { 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. + * @param adart a dart of the i-cell. + * @return true iff the i-cell can be contracted. + */ + template < class Map, unsigned int i > + bool is_contractible(const Map& amap, typename Map::Dart_const_handle adart) + { + CGAL_assertion(adart != NULL); + CGAL_static_assertion(0<=i && i<=Map::dimension); + + if ( i==0 ) return false; + if ( i==1 ) return true; + + // TODO ? Optimisation possible to not test all + // the darts of the cell ? + bool res = true; + for (CMap_dart_const_iterator_of_cell it(amap, adart); + res && it.cont(); ++it) + { + if (it->beta(i-2)->beta(i-1) != it->beta_inv(i-2)->beta(i-1) ) + res = false; + } + return res; + } + + /** Contract an i-cell, 1 + struct Contract_cell_functor + { + static size_t run(Map& amap, typename Map::Dart_handle adart) + { + CGAL_static_assertion ( 2<=i && i<=Map::dimension ); + CGAL_assertion( (is_contractible(amap, adart)) ); + + size_t res = 0; + + return res; + } + }; + + /** Contract an edge, and merge eventually both incident vertices. + * @param amap the used combinatorial map. + * @param adart a dart of the edge to contract. + * @return the number of deleted darts. + */ + template + struct Contract_cell_functor + { + static size_t run(Map& amap, typename Map::Dart_handle adart) + { + CGAL_assertion( (is_contractible(amap,adart)) ); + + size_t res = 0; + + // Stack of couple of dart for which we must call degroup_all_attributes + typedef std::pair + Dart_pair; + std::stack todegroup; + + // 1) We group the two vertices if they exist. + typename Map::Dart_handle dh2 = adart->other_extremity(); + if (dh2!=NULL) + amap.template group_attribute<0>(adart, dh2); + + typename Map::Dart_handle d1, d2; + int mark = amap.get_new_mark(); + std::vector to_erase; + + // 2) We mark all the darts of the edge. + { + for ( CMap_dart_iterator_basic_of_cell it(amap,adart,mark); + it.cont(); ++it ) + { + to_erase.push_back(it); + amap.mark(it,mark); + ++res; + } + } + + // 3) We modify the darts of the cells incident to the edge + // when they are marked to remove. + typename std::vector::iterator + it = to_erase.begin(); + for (; it != to_erase.end(); ++it) + { amap.update_dart_of_all_attributes(*it, mark); } + + // 4) For each dart of the cell, we modify link of neighbors. + for ( it=to_erase.begin(); it!=to_erase.end(); ++it ) + { + if ( !(*it)->is_free(0) ) + { + if ( !(*it)->is_free(1) && (*it)->beta(0)!=(*it) ) + amap.template basic_link_beta<1>((*it)->beta(0), (*it)->beta(1)); + else + { + // TODO todegroup.push(Dart_pair((*it)->beta(0), *it)); + (*it)->beta(0)->unlink_beta(1); + } + } + else + { + if ( !(*it)->is_free(1) ) + { + // TODO todegroup.push(Dart_pair((*it)->beta(1), *it)); + (*it)->beta(1)->unlink_beta(0); + } + } + } + + // 5) We degroup all the pairs + while ( !todegroup.empty() ) + { + Dart_pair p=todegroup.top(); + todegroup.pop(); + amap.degroup_all_attributes(p.first,p.second); + } + + // 6) We remove all the darts of the cell. + for (it = to_erase.begin(); it != to_erase.end(); ++it) + { amap.erase_dart(*it); } + + CGAL_assertion( amap.is_whole_map_unmarked(mark) ); + amap.free_mark(mark); + + // CGAL_postcondition( amap.is_valid() ); + + return res; + } + }; + + /** Contract an i-cell, 1<=i<=dimension. + * @param amap the used combinatorial map. + * @param adart a dart of the i-cell to remove. + * @return the number of deleted darts. + */ + template < class Map, unsigned int i > + size_t contract_cell(Map& amap, typename Map::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. @@ -540,8 +722,8 @@ namespace CGAL { * @return true iff a 2-cell can be inserted along the path. */ template - bool is_insertable_cell_2_in_cell_3(const Map& amap, - InputIterator afirst, + bool is_insertable_cell_2_in_cell_3(const Map& amap, + InputIterator afirst, InputIterator alast) { CGAL_static_assertion( Map::dimension>= 3 ); @@ -586,11 +768,11 @@ namespace CGAL { * @return a dart of the new vertex. */ template - typename Map::Dart_handle + typename Map::Dart_handle insert_cell_0_in_cell_1(Map& amap, typename Map::Dart_handle adart) { CGAL_assertion(adart != NULL && adart!=Map::null_dart_handle); - + typename Map::Dart_handle d1, d2; int mark = amap.get_new_mark(); @@ -607,7 +789,7 @@ namespace CGAL { for (; it != vect.end(); ++it) { d1 = amap.create_dart(); - + if (!(*it)->is_free(1)) { amap.template basic_link_beta<1>(d1, (*it)->beta(1)); } @@ -625,14 +807,14 @@ namespace CGAL { amap.mark(*it, mark); } - + for (it = vect.begin(); it != vect.end(); ++it) { amap.unmark(*it, mark); } - + amap.free_mark(mark); amap.template degroup_attribute<1>(adart, adart->beta(1)); - + return adart->beta(1); } @@ -642,7 +824,7 @@ namespace CGAL { * @return a dart of the new edge, not incident to the vertex of adart1. */ template - typename Map::Dart_handle + typename Map::Dart_handle insert_dangling_cell_1_in_cell_2(Map& amap, typename Map::Dart_handle adart1) { CGAL_assertion(adart1!=NULL && adart1!=Map::null_dart_handle); @@ -661,7 +843,7 @@ namespace CGAL { typename Map::Dart_handle d1 = NULL; typename Map::Dart_handle d2 = NULL; unsigned int s1 = 0; - + int treated = amap.get_new_mark(); CGAL::CMap_dart_iterator_of_involution it1(amap,adart1); @@ -670,8 +852,8 @@ namespace CGAL { { d1 = amap.create_dart(); d2 = amap.create_dart(); - - if ( amap.is_marked(it1, mark1) ) s1 = 0; + + if ( amap.is_marked(it1, mark1) ) s1 = 0; else s1 = 1; if ( !it1->is_free(s1) ) @@ -680,22 +862,22 @@ namespace CGAL { else amap.template link_beta<0>(it1->beta(1), d2); } - if (s1==0) + if (s1==0) { amap.template link_beta<0>(it1, d1); amap.template basic_link_beta<0>(d1,d2); } - else + else { amap.template link_beta<1>(it1, d1); amap.template basic_link_beta<1>(d1,d2); } amap.link_beta_for_involution(d1, d2, 2); - + for ( unsigned int dim=3; dim<=Map::dimension; ++dim) { - if ( !it1->is_free(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, @@ -723,7 +905,7 @@ namespace CGAL { for (; it != to_unmark.end(); ++it) { amap.unmark(*it, mark1); } CGAL_assertion( amap.is_whole_map_unmarked(mark1) ); - amap.free_mark(mark1); + amap.free_mark(mark1); // CGAL_postcondition(amap.is_valid()); return adart1->beta(0); @@ -733,11 +915,11 @@ namespace CGAL { * @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 + * @return a dart of the new edge, and not incident to the * same vertex than adart1. */ template - typename CMap::Dart_handle + typename CMap::Dart_handle insert_cell_1_in_cell_2(CMap& amap, typename CMap::Dart_handle adart1, typename CMap::Dart_handle adart2) @@ -747,10 +929,10 @@ namespace CGAL { CGAL_assertion(is_insertable_cell_1_in_cell_2(amap, adart1, adart2)); int m1 = amap.get_new_mark(); - CMap_dart_iterator_basic_of_involution + 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 + CMap_dart_iterator_basic_of_involution it2 = CMap_dart_iterator_basic_of_involution(amap, adart2, m2); int mark1 = amap.get_new_mark(); @@ -767,7 +949,7 @@ namespace CGAL { 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) @@ -775,8 +957,8 @@ namespace CGAL { CGAL_assertion (it2.cont() ); d1 = amap.create_dart(); d2 = amap.create_dart(); - - if ( amap.is_marked(it1, mark1) ) s1 = 0; + + if ( amap.is_marked(it1, mark1) ) s1 = 0; else s1 = 1; if ( !it1->is_free(s1) ) @@ -805,7 +987,7 @@ namespace CGAL { for ( unsigned int dim=3; dim<=CMap::dimension; ++dim) { - if ( !it1->is_free(dim) && + if ( !it1->is_free(dim) && amap.is_marked(it1->beta(dim), treated) ) { amap.basic_link_beta_for_involution @@ -826,9 +1008,9 @@ namespace CGAL { it1.rewind(); it2.rewind(); for ( ; it1.cont(); ++it1, ++it2) { - amap.mark(it1,m1); - amap.unmark(it1,treated); - amap.mark(it2,m2); + amap.mark(it1,m1); + amap.unmark(it1,treated); + amap.mark(it2,m2); } amap.negate_mark(m1); amap.negate_mark(m2); @@ -844,7 +1026,7 @@ namespace CGAL { for (; it != to_unmark.end(); ++it) { amap.unmark(*it, mark1); } CGAL_assertion( amap.is_whole_map_unmarked(mark1) ); - amap.free_mark(mark1); + amap.free_mark(mark1); // CGAL_postcondition(amap.is_valid()); return adart1->beta(0); @@ -874,32 +1056,32 @@ namespace CGAL { { 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) + if (withBeta3) { amap.template link_beta<1>(prec->beta(3), first->beta(3)); } @@ -911,14 +1093,14 @@ namespace CGAL { { typename Map::Dart_handle first2 = NULL; prec = NULL; - for ( CMap_dart_iterator_of_orbit it(amap, first); + 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(); + 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); } @@ -936,11 +1118,11 @@ namespace CGAL { { if ( dim2+1!=dim && dim2!=dim && dim2!=dim+1 ) { - if ( !it->is_free(dim2) && + 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) && + 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); @@ -949,7 +1131,7 @@ namespace CGAL { prec = d; } amap.template link_beta<0>( prec, first2 ); - if ( withBeta3 ) + if ( withBeta3 ) { amap.template link_beta<1>( prec->beta(3), first2->beta(3) ); } diff --git a/Combinatorial_map/include/CGAL/Dart.h b/Combinatorial_map/include/CGAL/Dart.h index 879a1ed4033..68184d1e336 100644 --- a/Combinatorial_map/include/CGAL/Dart.h +++ b/Combinatorial_map/include/CGAL/Dart.h @@ -67,6 +67,9 @@ namespace CGAL { template friend struct Remove_cell_functor; + template + friend struct Contract_cell_functor; + template friend struct internal::link_beta_functor; diff --git a/Combinatorial_map/include/CGAL/Dart_iterators.h b/Combinatorial_map/include/CGAL/Dart_iterators.h index 29640d516cc..93011a4472b 100644 --- a/Combinatorial_map/include/CGAL/Dart_iterators.h +++ b/Combinatorial_map/include/CGAL/Dart_iterators.h @@ -36,7 +36,7 @@ namespace CGAL { * - CMap_dart_iterator_of_involution * - CMap_dart_iterator_of_involution_inv * but many specializations to optimize specific cases. - * + * */ //**************************************************************************** //**********************BASIC ITERATORS*************************************** @@ -133,12 +133,12 @@ namespace CGAL { -1,-1,-1,-1,-1,-1,-1,-1,-1> { typedef CMap_dart_iterator_basic_of_orbit_generic type; - }; + }; #endif //CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES //**************************************************************************** // Case when Beta... is empty: iterator of self template - class CMap_dart_iterator_basic_of_orbit_generic: + class CMap_dart_iterator_basic_of_orbit_generic: public CMap_dart_iterator { public: @@ -149,13 +149,13 @@ namespace CGAL { typedef typename Base::Map Map; typedef Tag_false Use_mark; - + public: /// Main constructor. CMap_dart_iterator_basic_of_orbit_generic(Map& amap, Dart_handle adart): Base(amap, adart) {} - + /// Main constructor. CMap_dart_iterator_basic_of_orbit_generic(Map& amap, Dart_handle adart, int /*amark*/): @@ -181,7 +181,7 @@ namespace CGAL { * necessary in the second direction by using beta1. */ template - class CMap_dart_iterator_basic_of_orbit_generic: + class CMap_dart_iterator_basic_of_orbit_generic: public CMap_dart_iterator { public: @@ -199,7 +199,7 @@ namespace CGAL { Base(amap, adart), mfirst_dir(true) {} - + /// Main constructor. CMap_dart_iterator_basic_of_orbit_generic(Map& amap, Dart_handle adart, int /*amark*/): @@ -229,7 +229,7 @@ namespace CGAL { Self& operator++() { CGAL_assertion(this->cont()); - + if (mfirst_dir && (*this)->is_free(0)) { this->set_current_dart(this->mfirst_dart); @@ -240,12 +240,12 @@ namespace CGAL { { this->mprev_op = OP_BETAI; } - + if (mfirst_dir) { CGAL_assertion(!(*this)->is_free(0)); this->set_current_dart((*this)->beta(0)); - + if ((*this)==this->mfirst_dart) { this->set_current_dart(NULL); @@ -267,7 +267,7 @@ namespace CGAL { } return *this; } - + /// Postfix ++ operator. Self operator++(int) { Self res=*this; operator ++(); return res; } @@ -282,7 +282,7 @@ namespace CGAL { * necessary in the second direction by using beta0. */ template - class CMap_dart_iterator_basic_of_orbit_generic: + class CMap_dart_iterator_basic_of_orbit_generic: public CMap_dart_iterator { public: @@ -319,7 +319,7 @@ namespace CGAL { Self& operator++() { CGAL_assertion(this->cont()); - + if (mfirst_dir && (*this)->is_free(1)) { this->set_current_dart(this->mfirst_dart); @@ -330,12 +330,12 @@ namespace CGAL { { this->mprev_op = OP_BETAI; } - + if (mfirst_dir) { CGAL_assertion(!(*this)->is_free(1)); this->set_current_dart((*this)->beta(1)); - + if ((*this)==this->mfirst_dart) { this->set_current_dart(NULL); @@ -372,7 +372,7 @@ namespace CGAL { * (not for beta0 and beta1 which are special cases). */ template - class CMap_dart_iterator_basic_of_orbit_generic: + class CMap_dart_iterator_basic_of_orbit_generic: public CMap_dart_iterator { public: @@ -389,7 +389,7 @@ namespace CGAL { CMap_dart_iterator_basic_of_orbit_generic(Map& amap, Dart_handle adart): Base(amap, adart) { CGAL_static_assertion( Bi>=2 && Bi<=Map::dimension ); } - + /// Main constructor. CMap_dart_iterator_basic_of_orbit_generic(Map& amap, Dart_handle adart, int /*amark*/): @@ -439,7 +439,7 @@ namespace CGAL { typedef Tag_false Use_mark; CGAL_static_assertion( Bi>1 && delta>1 && Bi+delta<=Map::dimension ); - + public: /// Main constructor. CMap_dart_iterator_basic_of_two_beta(Map& amap, Dart_handle adart): @@ -448,7 +448,7 @@ namespace CGAL { {} /// Main constructor. - CMap_dart_iterator_basic_of_two_beta(Map& amap, Dart_handle adart, + CMap_dart_iterator_basic_of_two_beta(Map& amap, Dart_handle adart, int /*amark*/): Base(amap, adart), mcurdart(0) @@ -516,7 +516,7 @@ namespace CGAL { this->mprev_op = OP_END; this->set_current_dart(NULL); } - + return *this; } @@ -552,10 +552,10 @@ namespace CGAL { typedef Tag_true Use_mark; CGAL_static_assertion( 2<=Map::dimension ); - + public: /// Main constructor. - CMap_dart_iterator_basic_of_two_beta(Map& amap, Dart_handle adart, + CMap_dart_iterator_basic_of_two_beta(Map& amap, Dart_handle adart, int amark): Base(amap, adart, amark) {} diff --git a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_functors.h b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_functors.h index 8834628ad8e..ad35dd18b99 100644 --- a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_functors.h +++ b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_functors.h @@ -31,7 +31,7 @@ namespace CGAL { /** @file Combinatorial_map_functors.h * Definition of functors used for dD Combinatorial map. */ - + template struct Couple_dart_and_dim { @@ -49,7 +49,7 @@ namespace CGAL { static void run(CMap* amap, typename CMap::Dart_handle adart1, typename CMap::Dart_handle adart2) - { + { CGAL_assertion(amap!=NULL); amap->template group_enabled_attribute(adart1,adart2); } @@ -64,7 +64,7 @@ namespace CGAL { typename CMap::Dart_handle) {} }; - + // Functor used to degroup one attribute of two given darts template struct Degroup_one_attribute_functor @@ -72,13 +72,13 @@ namespace CGAL { 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 @@ -96,13 +96,13 @@ namespace CGAL { 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_of_dart (adart1,adart2); } }; - + // Specialization for i-attributes disabled. template struct Degroup_one_attribute_of_dart_functor @@ -120,11 +120,11 @@ namespace CGAL { { template static void run(Map* amap, typename Map::Dart_handle adart) - { amap->template + { amap->template decrease_attribute_ref_counting(adart/*,Tag_true()*/); } }; - /// Functor used to call update_dart_of_attribute + /// Functor used to call update_dart_of_attribute /// on each i-cell attribute enabled template struct Update_dart_of_attribute_functor @@ -141,17 +141,17 @@ namespace CGAL { template static void run(const Map* amap, std::vector* marks) { (*marks)[i] = amap->get_new_mark(); } - }; + }; /// Functor used to test if a cell is valid template struct Test_is_valid_attribute_functor { template - static void run(const Map* amap, - typename Map::Dart_const_handle adart, + static void run(const Map* amap, + typename Map::Dart_const_handle adart, std::vector* marks, bool *ares) - { + { if (!amap->template is_valid_attribute(adart,(*marks)[i]) ) { (*ares)=false; @@ -159,14 +159,14 @@ namespace CGAL { "associated with an attribute for " << &(*adart)<< std::endl; } } - }; + }; /// Functor for counting i-cell template struct Count_cell_functor { template - static void run( const Map* amap, + static void run( const Map* amap, typename Map::Dart_const_handle adart, std::vector* amarks, std::vector* ares ) @@ -185,7 +185,7 @@ namespace CGAL { struct Group_attribute_functor_run { static void run(Map* amap, - typename Map::Dart_handle adart1, + typename Map::Dart_handle adart1, typename Map::Dart_handle adart2, int adim) { if ( i!=adim ) @@ -193,7 +193,7 @@ namespace CGAL { amap->template group_enabled_attribute ::type> (adart1, adart2); - } + } } }; @@ -201,7 +201,7 @@ namespace CGAL { struct Group_attribute_functor_run { static void run(CMap* amap, - typename CMap::Dart_handle adart1, + typename CMap::Dart_handle adart1, typename CMap::Dart_handle adart2, int adim) { typename CMap::Dart_handle od = adart1->other_extremity(); @@ -211,7 +211,7 @@ namespace CGAL { <0, typename CMap::Helper::template Attribute_type<0>::type> (od, adart2); } - + if ( adim!=1 ) { od = adart2->other_extremity(); @@ -228,10 +228,10 @@ namespace CGAL { { template static void run(Map* amap, - typename Map::Dart_handle adart1, + typename Map::Dart_handle adart1, typename Map::Dart_handle adart2, int adim) { - CGAL_assertion( adim==-1 || + CGAL_assertion( adim==-1 || (1<=adim && (unsigned int)adim<=Map::dimension) ); Group_attribute_functor_run::run(amap,adart1,adart2,adim); } @@ -243,10 +243,10 @@ namespace CGAL { struct Degroup_attribute_functor_run { static void run(CMap* amap, - typename CMap::Dart_handle adart1, + typename CMap::Dart_handle adart1, typename CMap::Dart_handle adart2, int adim) { - CGAL_assertion( adim==-1 || + CGAL_assertion( adim==-1 || (1<=adim && (unsigned int)adim<=CMap::dimension) ); if (i!=adim ) { @@ -260,17 +260,17 @@ namespace CGAL { struct Degroup_attribute_functor_run { static void run(CMap* amap, - typename CMap::Dart_handle adart1, + typename CMap::Dart_handle adart1, typename CMap::Dart_handle adart2, int adim) { - CGAL_assertion( adim==-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); - + if ( adim!=1 ) { od = adart2->other_extremity(); @@ -287,13 +287,13 @@ namespace CGAL { struct Degroup_attribute_functor { template - static void run(Map* amap,typename Map::Dart_handle adart1, + static void run(Map* amap,typename Map::Dart_handle adart1, typename Map::Dart_handle adart2, int adim) { Degroup_attribute_functor_run::run(amap,adart1,adart2,adim); } }; - + // Functor which call operator() on the cell_attribute... template struct Apply_cell_functor @@ -309,9 +309,9 @@ namespace CGAL { { static void run(Cell_attribute&, Cell_attribute&) {} - }; + }; - /// Functor used for link_beta to update the attributes of + /// Functor used for link_beta to update the attributes of /// adart2 on the attributes of this dart, except for adimension-attributes. template struct Group_attribute_functor_of_dart_run @@ -321,9 +321,9 @@ namespace CGAL { typename CMap::Dart_handle dh2, int adim) { - CGAL_assertion( adim==-1 || + CGAL_assertion( adim==-1 || (0<=adim && (unsigned int)adim<=CMap::dimension) ); - if ( adim!=i ) + if ( adim!=i ) { amap->template group_enabled_attribute_of_dart ::type> @@ -339,7 +339,7 @@ namespace CGAL { typename CMap::Dart_handle dh2, int adim) { - CGAL_assertion( adim==-1 || + CGAL_assertion( adim==-1 || (0<=adim && (unsigned int)adim<=CMap::dimension) ); // todo ASSERT (1<=adim && ...) ??? if ( adim!=0 ) @@ -363,20 +363,20 @@ namespace CGAL { a2=od->template attribute<0>(); if ( a2!=NULL ) amap->template set_attribute_of_dart<0>(dh1, a2); - } - } + } + } } }; - + template struct Group_attribute_functor_of_dart { template static void run(CMap* amap, - typename CMap::Dart_handle adart1, + typename CMap::Dart_handle adart1, typename CMap::Dart_handle adart2, int adim) { - CGAL_assertion( adim==-1 || + CGAL_assertion( adim==-1 || (0<=adim && (unsigned int)adim<=CMap::dimension) ); Group_attribute_functor_of_dart_run:: run(amap,adart1,adart2,adim); @@ -393,7 +393,7 @@ namespace CGAL { Attribute_type::type> struct Call_split_functor { - static void run(typename Map::Dart_handle adart1, + static void run(typename Map::Dart_handle adart1, typename Map::Dart_handle adart2) { Apply_cell_functor @@ -408,9 +408,9 @@ namespace CGAL { template struct Call_split_functor { - static void run(typename Map::Dart_handle, + static void run(typename Map::Dart_handle, typename Map::Dart_handle) - {} + {} }; /// Functor for counting the memory occupation of attributes @@ -447,14 +447,14 @@ namespace CGAL { #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 { @@ -465,7 +465,117 @@ namespace CGAL { } }; #endif //CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES - + + template + struct Store_incident_cells + { + template + static void run( Map* amap, typename Map::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 + [Map::Helper::template Dimension_index::value]; + + if ( amap->is_marked(adart, mark_for_jcells) || + adart->template attribute()==NULL ) + return; + + std::deque >& jcells = + store[Map::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) ); + + 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(); + } + }; + + template + struct Test_split_with_deque + { + template + static void run( Map* amap, + int* mark_for_incident_cells, + std::deque > + *store ) + { + if ( i==j ) return; + + const int mark_for_jcells = mark_for_incident_cells + [Map::Helper::template Dimension_index::value]; + std::deque >& jcells = + store[Map::Helper::template Dimension_index::value]; + + CGAL_assertion( amap!=NULL ); + CGAL_assertion( amap->is_reserved(mark_for_jcells) ); + + int nbofjcell = 0; + typename Map::Helper::template Attribute_handle::type + a1 = NULL; + typename Map::Helper::template Attribute_handle::type + a2=NULL; + + amap->negate_mark( mark_for_jcells ); + + 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); + a2->set_dart(*itj); + // We call the on_split functor + Apply_cell_functor + ::type, + typename Map::Helper::template Attribute_type::type::On_split>:: + run(*a1, *a2); + } + else + { + a1=(*itj)->template attribute(); + a1->set_dart(*itj); + } + + for ( CMap_dart_iterator_basic_of_cell + itj2(*amap, *itj, mark_for_jcells); + itj2.cont(); ++itj2 ) + { + if ( nbofjcell>1 ) + amap->template set_attribute_of_dart(itj2, a2); + + amap->mark(itj2, mark_for_jcells); + } + } + } + } + } + }; + } // namespace internal } // namespace CGAL diff --git a/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_3_test.h b/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_3_test.h index 2b0dddd51ff..85048a41306 100644 --- a/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_3_test.h +++ b/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_3_test.h @@ -28,6 +28,37 @@ using namespace std; +template +bool check_number_of_cells_3(CMap& cmap, unsigned int nbv, unsigned int nbe, + unsigned int nbf, unsigned int nbvol, + unsigned int nbcc) +{ + if ( !cmap.is_valid() ) + { + std::cout<<"ERROR: the cmap is not valid."< nbc; + nbc=cmap.count_all_cells(); + + if (nbv!=nbc[0] || nbe!=nbc[1] || nbf!=nbc[2] || nbvol!=nbc[3] || + nbcc!=nbc[4]) + { + std::cout<<"ERROR: the number of cells is not correct. We must have " + <<" ("< void drawCell3(Map& amap, typename Map::Dart_handle adart, int aorbit, int mark) { @@ -286,7 +317,7 @@ private: }; template - void test3D() + bool test3D() { typedef typename Map::Dart_handle Dart_handle; Dart_handle d,dh,dh2,d1,d2,d3,d4; @@ -1016,71 +1047,80 @@ template cout << "***************************** TEST INSERT FACET 3D DONE." << endl; - /* cout << "***************************** TEST EDGE CONTRACTION 3D:" << endl; d1 = map.create_dart(); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; - cout << "contract edge1: " << flush; CGAL::contract_cell(map,d1); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; + CGAL::contract_cell(map,d1); + if ( !check_number_of_cells_3(map, 0, 0, 0, 0, 0) ) + return false; d1 = map.create_dart(); map.template sew<1>(d1, d1); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; - cout << "contract edge2: " << flush; CGAL::contract_cell(map,d1); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; + CGAL::contract_cell(map,d1); + if ( !check_number_of_cells_3(map, 0, 0, 0, 0, 0) ) + return false; - d1 = make_edge(map,, ); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; - cout << "contract edge3: " << flush; CGAL::contract_cell(map,d1); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; + d1 = make_edge(map); + CGAL::contract_cell(map,d1); + if ( !check_number_of_cells_3(map, 0, 0, 0, 0, 0) ) + return false; - d1 = make_edge(map,, ); - map.template sew<1>(d1, d1); map.template sew<1>(d1->beta(2), d1->beta(2)); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; - cout << "contract edge4: " << flush; CGAL::contract_cell(map,d1); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; - - d1 = make_edge(map,, ); + d1 = make_edge(map); map.template sew<1>(d1, d1); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; - cout << "contract edge5: " << flush; CGAL::contract_cell(map,d1); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; + CGAL::contract_cell(map,d1); + if ( !check_number_of_cells_3(map, 0, 0, 0, 0, 0) ) + return false; + + d1 = make_edge(map); + map.template sew<1>(d1, d1); map.template sew<1>(d1->beta(2), d1->beta(2)); + CGAL::contract_cell(map,d1); + if ( !check_number_of_cells_3(map, 0, 0, 0, 0, 0) ) + return false; + + d1 = CGAL::make_combinatorial_polygon(map, 3); - d1 = make_triangle(map,, , ); d2 = d1->beta(0); d3 = d1->beta(1); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; + CGAL::contract_cell(map,d1); + if ( !check_number_of_cells_3(map, 2, 2, 1, 1, 1) || + !CGAL::is_face_combinatorial_polygon(map, d2, 2) ) + return false; - cout << "contract edge6: " << flush; CGAL::contract_cell(map,d1); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; + CGAL::contract_cell(map,d2); + if ( !check_number_of_cells_3(map, 1, 1, 1, 1, 1) || + !CGAL::is_face_combinatorial_polygon(map, d3, 1) ) + return false; - cout << "contract edge7: " << flush; CGAL::contract_cell(map,d2); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; + CGAL::contract_cell(map,d3); + if ( !check_number_of_cells_3(map, 0, 0, 0, 0, 0) ) + return false; - cout << "contract edge8: " << flush; CGAL::contract_cell(map,d3); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; - - d1 = make_triangle(map,, , ); - d2 = make_triangle(map,, , ); + d1 = CGAL::make_combinatorial_polygon(map, 3); + d2 = CGAL::make_combinatorial_polygon(map, 3); map.template sew<3>(d1, d2); d2 = d1->beta(0); d3 = d1->beta(1); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; - cout << "contract edge9: " << flush; CGAL::contract_cell(map,d1); - map.display_characteristics(cout)<(map,d2); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; + CGAL::contract_cell(map,d2); + if ( !check_number_of_cells_3(map, 1, 1, 1, 2, 1) || + !CGAL::is_face_combinatorial_polygon(map, d3, 1) ) + return false; - cout << "contract edge11: " << flush; CGAL::contract_cell(map,d3); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; + CGAL::contract_cell(map,d3); + if ( !check_number_of_cells_3(map, 0, 0, 0, 0, 0) ) + return false; - d1 = make_triangle(map,, , ); - d2 = make_triangle(map,, , ); + d1 = CGAL::make_combinatorial_polygon(map, 3); + d2 = CGAL::make_combinatorial_polygon(map, 3); map.template sew<2>(d1, d2); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; - cout << "contract edge12: " << flush; CGAL::contract_cell(map,d1); - map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; + CGAL::contract_cell(map,d1); + if ( !check_number_of_cells_3(map, 4, 4, 2, 2, 2) ) + return false; + +/* TODO continue tests d1 = make_triangle(map,, , ); d2 = make_triangle(map,, , ); map.template sew<2>(d1, d2); @@ -1308,6 +1348,7 @@ template cout << "***************************** TEST VOLUME CONTRACTION 3D DONE." << endl; */ + return true; } #endif // CGAL_COMBINATORIAL_MAP_3_TEST diff --git a/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_test.cpp b/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_test.cpp index ba9606efe0c..d9f3a81e8d5 100644 --- a/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_test.cpp +++ b/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_test.cpp @@ -84,22 +84,46 @@ int main() typedef CGAL::Combinatorial_map<3, CGAL::Combinatorial_map_min_items<3> > Map4; - test3D(); - + if ( !test3D() ) + { + std::cout<<"ERROR during Test_LCC_4."< Map5; - test3D(); + if ( !test3D() ) + { + std::cout<<"ERROR during test3D."< Map6; - test3D(); + if ( !test3D() ) + { + std::cout<<"ERROR during test3D."< Map7; - test3D(); + if ( !test3D() ) + { + std::cout<<"ERROR during test3D."< Map8; - test3D(); + if ( !test3D() ) + { + std::cout<<"ERROR during test3D."< Map9; - test3D(); + if ( !test3D() ) + { + std::cout<<"ERROR during test3D."<