diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h b/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h index cea15596104..92f40714f85 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h @@ -360,7 +360,7 @@ namespace CGAL { { if (d1 != Map::null_dart_handle) { - if (d2 != Map::null_dart_handle) + if (d2 != Map::null_dart_handle && d1!=d2 ) { //d1->basic_link_beta(d2, i); amap.template basic_link_beta(d1, d2); @@ -396,17 +396,17 @@ namespace CGAL { modified_darts.push_back(d2); } } - if ((*it)->is_free(i+1) && !(*it)->is_free(i)) - { - d1 = (*it)->beta(i); - if ( !d1->is_free(iinv) ) - { - d1->unlink_beta(iinv); - CGAL_assertion( !amap.is_marked(d1, mark_modified_darts) ); - amap.mark(d1, mark_modified_darts); - modified_darts.push_back(d1); - } - } + } + } + if ( (*it)->is_free(i+1) && !(*it)->is_free(i) ) + { + d1 = (*it)->beta(i); + if ( !d1->is_free(iinv) ) + { + d1->unlink_beta(iinv); + CGAL_assertion( !amap.is_marked(d1, mark_modified_darts) ); + amap.mark(d1, mark_modified_darts); + modified_darts.push_back(d1); } } } @@ -801,6 +801,135 @@ namespace CGAL { size_t res = 0; + typename Map::Dart_handle d1, d2; + typename Map::Dart_handle dg1=NULL, dg2=NULL; + + int mark = amap.get_new_mark(); + int mark_modified_darts = amap.get_new_mark(); + + std::deque to_erase; + + const int imuinv = CGAL_BETAINV(i-1); + + // First we store and mark all the darts of the i-cell to contract. + for ( CMap_dart_iterator_basic_of_cell it(amap,adart,mark); + it.cont(); ++it ) + { + to_erase.push_back(it); + if ( !it->is_free(i-1) && dg1==NULL ) + { dg1=it; dg2=it->beta(i-1); } + amap.mark(it, mark); + ++res; + } + + // We group the two (i+1)-cells incident if they exist. + if ( dg1!=NULL ) + amap.template group_attribute(dg1, dg2); + + // Second we update the dart of the cell attributes on non marked darts. + 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; + + // 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(i); + while ( d1!=Map::null_dart_handle && amap.is_marked(d1, mark) ) + { + d1 = d1->beta(imuinv)->beta(i); + if (d1 == (*it)->beta(i)) d1 = Map::null_dart_handle; + } + + if ( !amap.is_marked(d1, mark_modified_darts) ) + { + 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; + } + + if ( !amap.is_marked(d2, mark_modified_darts) ) + { + if (d1 != Map::null_dart_handle) + { + if (d2 != Map::null_dart_handle && d1!=d2 ) + { + amap.template basic_link_beta(d1, d2); + amap.mark(d1, mark_modified_darts); + amap.mark(d2, mark_modified_darts); + modified_darts.push_back(d1); + modified_darts.push_back(d2); + } + else + { + if ( !d1->is_free(i) ) + { + d1->unlink_beta(i); + CGAL_assertion( !amap.is_marked(d1, mark_modified_darts) ); + amap.mark(d1, mark_modified_darts); + modified_darts.push_back(d1); + } + } + } + else if (d2 != Map::null_dart_handle) + { + if ( !d2->is_free(i) ) + { + d2->unlink_beta(i); + CGAL_assertion( !amap.is_marked(d2, mark_modified_darts) ); + amap.mark(d2, mark_modified_darts); + modified_darts.push_back(d2); + } + } + } + } + if ((*it)->is_free(i-1) && !(*it)->is_free(i)) + { + d1 = (*it)->beta(i); + if ( !d1->is_free(i) ) + { + d1->unlink_beta(i); + CGAL_assertion( !amap.is_marked(d1, mark_modified_darts) ); + amap.mark(d1, mark_modified_darts); + modified_darts.push_back(d1); + } + } + } + + // We test the split of all the incident cells for all the non + // void attributes. + Map::Helper::template Foreach_enabled_attributes + >:: + run(&amap, &modified_darts, mark_modified_darts); + + // We remove all the darts of the i-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); + + if ( !amap.is_whole_map_unmarked(mark_modified_darts) ) + { + for ( typename std::deque:: + iterator it=modified_darts.begin(); + it!=modified_darts.end(); ++it ) + amap.unmark(*it, mark_modified_darts); + } + + // amap.display_darts(std::cout); + + CGAL_assertion ( amap.is_whole_map_unmarked(mark_modified_darts) ); + amap.free_mark(mark_modified_darts); + + CGAL_expensive_postcondition( amap.is_valid() ); + assert( amap.is_valid() ); + return res; } }; @@ -903,7 +1032,7 @@ namespace CGAL { amap.free_mark(mark); CGAL_expensive_postcondition( amap.is_valid() ); - assert( amap.is_valid() ); // TO REMOVEE + assert( amap.is_valid() ); // TO REMOVE return res; } 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 07f4020828d..aea19385421 100644 --- a/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_3_test.h +++ b/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_3_test.h @@ -1259,11 +1259,55 @@ template cout << "***************************** TEST EDGE CONTRACTION 3D DONE." << endl; - /* cout << "***************************** TEST FACET CONTRACTION 3D:" << endl; d1 = map.create_dart(); + 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); + CGAL::contract_cell(map,d1); + if ( !check_number_of_cells_3(map, 0, 0, 0, 0, 0) ) + return false; + + d1 = make_edge(map); + CGAL::contract_cell(map,d1); + if ( !check_number_of_cells_3(map, 1, 1, 1, 1, 1) ) + return false; + map.clear(); + + d1 = make_edge(map); + map.template sew<1>(d1, d1); + CGAL::contract_cell(map,d1); + if ( !check_number_of_cells_3(map, 1, 1, 1, 1, 1) ) + return false; + map.clear(); + + 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, 1, 1, 1, 1, 1) ) + return false; + map.clear(); + + d1 = CGAL::make_combinatorial_polygon(map, 3); + d2 = CGAL::make_combinatorial_polygon(map, 3); + d3 = CGAL::make_combinatorial_polygon(map, 3); + map.template sew<2>(d1, d2); + map.template sew<2>(d2->beta(1), d3); + + CGAL::contract_cell(map,d2->beta(0)); + if ( !check_number_of_cells_3(map, 4, 6, 3, 1, 1) ) + return false; + CGAL::contract_cell(map,d2); + if ( !check_number_of_cells_3(map, 4, 5, 2, 1, 1) ) + return false; + map.clear(); + + /* TODO more tests contact 2D and 3D map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; cout << "contract facet1: " << flush; CGAL::contract_cell(map,d1); map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; @@ -1448,10 +1492,11 @@ template cout << "contract volume8: " << flush; CGAL::contract_cell(map,d1); map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl; map.clear(); - + */ + cout << "***************************** TEST VOLUME CONTRACTION 3D DONE." << endl; - */ + return true; }