diff --git a/Combinatorial_map/include/CGAL/Cell_attribute.h b/Combinatorial_map/include/CGAL/Cell_attribute.h index 269b40cc72b..0186fa44ac0 100644 --- a/Combinatorial_map/include/CGAL/Cell_attribute.h +++ b/Combinatorial_map/include/CGAL/Cell_attribute.h @@ -89,6 +89,12 @@ namespace CGAL { template friend struct internal::Decrease_attribute_functor_run; + template + friend struct internal::Reverse_orientation_of_map_functor; + + template + friend struct internal::Reverse_orientation_of_connected_component_functor; + public: typedef Tag_false Supports_cell_dart; @@ -195,6 +201,12 @@ namespace CGAL { template friend struct internal::Decrease_attribute_functor_run; + template + friend struct internal::Reverse_orientation_of_map_functor; + + template + friend struct internal::Reverse_orientation_of_connected_component_functor; + public: typedef Tag_true Supports_cell_dart; diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map.h b/Combinatorial_map/include/CGAL/Combinatorial_map.h index 6b221f600c4..862435422a0 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map.h @@ -2200,6 +2200,27 @@ namespace CGAL { if ( update_attributes ) unsew(adart); else topo_unsew(adart); } + + /** Reverse the orientation (swap beta 0 & 1 links) of the entire map. + * A valid map after this operation remains valid. + * @param none + * @return none + */ + void reverse_orientation() + { + internal::Reverse_orientation_of_map_functor::run(this); + } + + /** Reverse the orientation (swap beta 0 & 1 links) of the connected + * component containing the given dart. + * A valid map after this operation remains valid. + * @param adart handle to a dart + * @return none + */ + void reverse_orientation_connected_component (Dart_handle adart) + { + internal::Reverse_orientation_of_connected_component_functor::run(this, adart); + } /** Count the marked cells (at least one marked dart). * @param amark the mark to consider. diff --git a/Combinatorial_map/include/CGAL/Dart.h b/Combinatorial_map/include/CGAL/Dart.h index 0af7239ea26..8269c222f78 100644 --- a/Combinatorial_map/include/CGAL/Dart.h +++ b/Combinatorial_map/include/CGAL/Dart.h @@ -72,6 +72,12 @@ namespace CGAL { template friend struct internal::link_beta_functor; + + template + friend struct internal::Reverse_orientation_of_map_functor; + + template + friend struct internal::Reverse_orientation_of_connected_component_functor; public: typedef Dart Self; @@ -272,6 +278,16 @@ namespace CGAL { Helper::template Foreach_enabled_attributes:: run(this); } + + /** Copy constructor: + * @param adart a dart. + */ + Dart(const std::bitset& /*amarks*/, const Dart& adart) : mmarks(adart.mmarks), + mattribute_handles(adart.mattribute_handles) + { + for (unsigned int i = 0; i <= dimension; ++i) + mbeta[i] = adart.mbeta[i]; + } /** Return the mark value of a given mark number. * @param amark the mark number. diff --git a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_internal_functors.h b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_internal_functors.h index 1bd03d8f345..83e576f0556 100644 --- a/Combinatorial_map/include/CGAL/internal/Combinatorial_map_internal_functors.h +++ b/Combinatorial_map/include/CGAL/internal/Combinatorial_map_internal_functors.h @@ -630,6 +630,198 @@ struct Test_is_same_attribute_functor template bool Test_is_same_attribute_functor::value = true; // **************************************************************************** +/// Functor to reverse the orientation of a combinatorial map +template ::type> +struct Reverse_orientation_of_map_functor +{ + static void run(CMap *amap) + { + int mark = amap->get_new_mark(); + CGAL_precondition(amap->is_whole_map_unmarked(mark)); + CGAL_precondition(amap->is_valid()); + for (typename CMap::Dart_range::iterator current_dart=amap->darts().begin(), + last_dart = amap->darts().end(); current_dart!=last_dart; + ++current_dart) + { + if (amap->is_marked(current_dart, mark)) continue; + typename CMap::Dart_handle first_dart_in_cell= current_dart; + typename CMap::Dart_handle current_dart_in_cell= + first_dart_in_cell->beta(1); + typename CMap::Helper::template Attribute_handle<0>::type + attribute_for_first_dart=current_dart_in_cell->template attribute<0>(); + attribute_for_first_dart->inc_nb_refs(); + do { + amap->mark(current_dart_in_cell, mark); + typename CMap::Dart_handle previous_dart_in_cell= + current_dart_in_cell->beta(0); + typename CMap::Dart_handle next_dart_in_cell= + current_dart_in_cell->beta(1); + typename CMap::Helper::template Attribute_handle<0>::type + next_attribute=next_dart_in_cell->template attribute<0>(); + // One line error??? + CGAL::internal::Set_i_attribute_of_dart_functor:: + run(amap, current_dart_in_cell, next_attribute); + current_dart_in_cell->basic_link_beta(previous_dart_in_cell, 1); + current_dart_in_cell->basic_link_beta(next_dart_in_cell, 0); + current_dart_in_cell = current_dart_in_cell->beta(0); + } + while (current_dart_in_cell != first_dart_in_cell); + amap->mark(current_dart_in_cell, mark); + typename CMap::Dart_handle previous_dart_in_cell= + current_dart_in_cell->beta(0); + typename CMap::Dart_handle next_dart_in_cell= + current_dart_in_cell->beta(1); + CGAL::internal::Set_i_attribute_of_dart_functor:: + run(amap, current_dart_in_cell, attribute_for_first_dart); + attribute_for_first_dart->dec_nb_refs(); + current_dart_in_cell->basic_link_beta(previous_dart_in_cell, 1); + current_dart_in_cell->basic_link_beta(next_dart_in_cell, 0); + } + amap->negate_mark(mark); + CGAL_postcondition(amap->is_whole_map_unmarked(mark)); + CGAL_postcondition(amap->is_valid()); + amap->free_mark(mark); + } +}; +// **************************************************************************** +// Specialization for void 0-attributes +template +struct Reverse_orientation_of_map_functor +{ + static void run(CMap *amap) + { + int mark = amap->get_new_mark(); + CGAL_precondition(amap->is_whole_map_unmarked(mark)); + CGAL_precondition(amap->is_valid()); + for (typename CMap::Dart_range::iterator current_dart=amap->darts().begin(), + last_dart = amap->darts().end(); current_dart!=last_dart; + ++current_dart) + { + if (amap->is_marked(current_dart, mark)) continue; + for (typename CMap::template Dart_of_cell_range<2>::iterator + current_dart_in_cell=amap->template darts_of_cell<2>(current_dart). + begin(), last_dart_in_cell=amap->template darts_of_cell<2> + (current_dart).end(); current_dart_in_cell!=last_dart_in_cell; + ++current_dart_in_cell) + { + amap->mark(current_dart_in_cell, mark); + typename CMap::Dart_handle previous_dart_in_cell= + current_dart_in_cell->beta(0); + typename CMap::Dart_handle next_dart_in_cell= + current_dart_in_cell->beta(1); + current_dart_in_cell->basic_link_beta(previous_dart_in_cell, 1); + current_dart_in_cell->basic_link_beta(next_dart_in_cell, 0); + } + } + amap->negate_mark(mark); + CGAL_postcondition(amap->is_whole_map_unmarked(mark)); + CGAL_postcondition(amap->is_valid()); + amap->free_mark(mark); + } +}; +// **************************************************************************** +/// Functor to reverse the orientation of a connected component in a given map +template ::type> +struct Reverse_orientation_of_connected_component_functor +{ + static void run(CMap *amap, typename CMap::Dart_handle adart) + { + int mark = amap->get_new_mark(); + CGAL_precondition(amap->is_whole_map_unmarked(mark)); + for (typename CMap::template Dart_of_cell_range::iterator + current_dart=amap->template darts_of_cell(adart). + begin(), last_dart=amap->template darts_of_cell + (adart).end(); current_dart!=last_dart; ++current_dart) + { + if (amap->is_marked(current_dart, mark)) continue; + typename CMap::Dart_handle first_dart_in_cell=current_dart; + typename CMap::Dart_handle current_dart_in_cell= + first_dart_in_cell->beta(1); + typename CMap::Helper::template Attribute_handle<0>::type + attribute_for_first_dart=current_dart_in_cell->template attribute<0>(); + attribute_for_first_dart->inc_nb_refs(); + do { + amap->mark(current_dart_in_cell, mark); + typename CMap::Dart_handle previous_dart_in_cell= + current_dart_in_cell->beta(0); + typename CMap::Dart_handle next_dart_in_cell= + current_dart_in_cell->beta(1); + typename CMap::Helper::template Attribute_handle<0>::type + next_attribute=next_dart_in_cell->template attribute<0>(); + + CGAL::internal::Set_i_attribute_of_dart_functor:: + run(amap, current_dart_in_cell, next_attribute); + current_dart_in_cell->basic_link_beta(previous_dart_in_cell, 1); + current_dart_in_cell->basic_link_beta(next_dart_in_cell, 0); + current_dart_in_cell = current_dart_in_cell->beta(0); + } + while (current_dart_in_cell != first_dart_in_cell); + amap->mark(current_dart_in_cell, mark); + typename CMap::Dart_handle previous_dart_in_cell= + current_dart_in_cell->beta(0); + typename CMap::Dart_handle next_dart_in_cell= + current_dart_in_cell->beta(1); + CGAL::internal::Set_i_attribute_of_dart_functor:: + run(amap, current_dart_in_cell, attribute_for_first_dart); + attribute_for_first_dart->dec_nb_refs(); + current_dart_in_cell->basic_link_beta(previous_dart_in_cell, 1); + current_dart_in_cell->basic_link_beta(next_dart_in_cell, 0); + } + for (typename CMap::template Dart_of_cell_range::iterator + current_dart=amap->template darts_of_cell(adart). + begin(), last_dart=amap->template darts_of_cell + (adart).end(); current_dart!=last_dart; ++current_dart) + { + amap->unmark(current_dart, mark); + } + CGAL_postcondition(amap->is_whole_map_unmarked(mark)); + amap->free_mark(mark); + } +}; +// **************************************************************************** +// Specialization for void 0-attributes +template +struct Reverse_orientation_of_connected_component_functor +{ + static void run(CMap *amap, typename CMap::Dart_handle adart) + { + int mark = amap->get_new_mark(); + CGAL_precondition(amap->is_whole_map_unmarked(mark)); + for (typename CMap::template Dart_of_cell_range::iterator + current_dart=amap->template darts_of_cell(adart). + begin(), last_dart=amap->template darts_of_cell + (adart).end(); current_dart!=last_dart; ++current_dart) + { + if (amap->is_marked(current_dart, mark)) continue; + for (typename CMap::template Dart_of_cell_range<2>::iterator + current_dart_in_cell=amap->template darts_of_cell<2>(current_dart). + begin(), last_dart_in_cell=amap->template darts_of_cell<2> + (current_dart).end(); current_dart_in_cell!=last_dart_in_cell; + ++current_dart_in_cell) + { + amap->mark(current_dart_in_cell, mark); + typename CMap::Dart_handle previous_dart_in_cell= + current_dart_in_cell->beta(0); + typename CMap::Dart_handle next_dart_in_cell= + current_dart_in_cell->beta(1); + current_dart_in_cell->basic_link_beta(previous_dart_in_cell, 1); + current_dart_in_cell->basic_link_beta(next_dart_in_cell, 0); + } + } + for (typename CMap::template Dart_of_cell_range::iterator + current_dart=amap->template darts_of_cell(adart). + begin(), last_dart=amap->template darts_of_cell + (adart).end(); current_dart!=last_dart; ++current_dart) + { + amap->unmark(current_dart, mark); + } + CGAL_postcondition(amap->is_whole_map_unmarked(mark)); + amap->free_mark(mark); + } +}; +// **************************************************************************** // Beta functor, used to combine several beta. #ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES template diff --git a/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_4_test.h b/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_4_test.h index d19dee3bc22..a21e31ea478 100644 --- a/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_4_test.h +++ b/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_4_test.h @@ -284,6 +284,12 @@ bool test_LCC_4() return false; } + lcc.reverse_orientation(); + lcc.reverse_orientation(); + + lcc.reverse_orientation_connected_component(dh1); + lcc.reverse_orientation_connected_component(dh1); + /* import_from_polyhedron(lcc,ap); lcc.clear();