From bb263e009e859b9f6d2f11d24483dbef9bf17021 Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Fri, 25 Nov 2022 13:06:50 +0100 Subject: [PATCH] add insert_cell_1_between_two_cells_2 method in CMap and GMap --- .../include/CGAL/Combinatorial_map.h | 90 +++++++++- .../include/CGAL/Generalized_map.h | 169 +++++++++++++----- 2 files changed, 205 insertions(+), 54 deletions(-) diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map.h b/Combinatorial_map/include/CGAL/Combinatorial_map.h index fa13fbe6d6c..f16a3779cd9 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map.h @@ -1639,11 +1639,14 @@ namespace CGAL { CGAL_static_assertion(i<=dimension); CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "set_attribute but i-attributes are disabled"); - for ( typename Dart_of_cell_range::iterator it(*this, dh); - it.cont(); ++it) + + for (typename Dart_of_cell_range::iterator it(*this, dh); it.cont(); ++it) { this->template set_dart_attribute(it, ah); } + if(ah!=null_descriptor) + // To ensure that the dart of this attribute is dh + { this->template set_dart_of_attribute(ah, dh); } } /// @return a Attributes_range (range through all the @@ -4410,7 +4413,8 @@ namespace CGAL { bool is_insertable_cell_1_in_cell_2(Dart_const_descriptor adart1, Dart_const_descriptor adart2) const { - if ( adart1==adart2 ) return false; + if (adart1==adart2 || adart1==null_descriptor) return false; + if (adart2==null_descriptor) return true; for ( CMap_dart_const_iterator_of_orbit it(*this,adart1); it.cont(); ++it ) { @@ -4427,15 +4431,81 @@ namespace CGAL { * same vertex than adart1. */ Dart_descriptor insert_cell_1_in_cell_2(Dart_descriptor adart1, - Dart_descriptor adart2, - bool update_attributes=true) + Dart_descriptor adart2, + bool update_attributes=true) { + CGAL_assertion(is_insertable_cell_1_in_cell_2(adart1, adart2)); if ( adart2==null_descriptor ) return insert_dangling_cell_1_in_cell_2(adart1, null_descriptor, update_attributes); + return generic_insert_cell_1(adart1, adart2, false, update_attributes); + } - CGAL_assertion(is_insertable_cell_1_in_cell_2(adart1, adart2)); + /** Test if an edge can be inserted between two different 2-cells + * between two given darts. + * @param adart1 a first dart. + * @param adart2 a second dart. + * @return true iff an edge can be inserted between adart1 and adart2. + */ + bool is_insertable_cell_1_between_two_cells_2(Dart_const_descriptor adart1, + Dart_const_descriptor adart2) const + { + if (adart1==adart2 || adart1==null_descriptor || adart2==null_descriptor) + { return false; } + for ( CMap_dart_const_iterator_of_orbit it(*this,adart1); + it.cont(); ++it ) + { + if ( it==adart2 ) return false; + } + return true; + } + /** Insert an edge between two different 2-cells, between two given darts. + * @param adart1 a first dart of the first facet (!=null_descriptor && !=null_dart_descriptor). + * @param adart2 a second dart of the second facet (!=null_descriptor && !=null_dart_descriptor). + * @param update_attributes a boolean to update the enabled attributes + * @return a dart of the new edge, and not incident to the + * same vertex than adart1. + */ + Dart_descriptor insert_cell_1_between_two_cells_2(Dart_descriptor adart1, + Dart_descriptor adart2, + bool update_attributes=true) + { + CGAL_assertion(is_insertable_cell_1_between_two_cells_2(adart1, adart2)); + return generic_insert_cell_1(adart1, adart2, true, update_attributes); + } + + /** Insert an edge between two given darts. If the two darts belong to the same facet, call + * insert_cell_1_in_cell_2, otherwise call insert_cell_1_between_two_cells_2. + * @param adart1 a first dart (!=null_descriptor && !=null_dart_descriptor). + * @param adart2 a second dart. + * @param update_attributes a boolean to update the enabled attributes + * @return a dart of the new edge, and not incident to the + * same vertex than adart1. + */ + Dart_descriptor insert_cell_1(Dart_descriptor adart1, + Dart_descriptor adart2, + bool update_attributes=true) + { + if(is_insertable_cell_1_in_cell_2(adart1, adart2)) + { return insert_cell_1_in_cell_2(adart1, adart2, update_attributes); } + return insert_cell_1_between_two_cells_2(adart1, adart2, update_attributes); + } + + /** Generic method to insert a 1-cell, either in a 2-cell (cf. insert_cell_1_in_cell_2) + * or between two different 2-cells (cf. insert_cell_1_between_two_cells_2). + * Indeed the code is the same, except for the group/degroup attribute. + * merge is true if adart1 and adart2 belongs to two different facets; in this case + * the two facets should be merged (they are now linked by the new edge); + * merge is false it adart1 and adart2 belongs to the same facet; in this case + * the facet is split in two. + * Internal method not supposed to be called by users. + */ + Dart_descriptor generic_insert_cell_1(Dart_descriptor adart1, + Dart_descriptor adart2, + bool merge, + bool update_attributes) + { size_type m1=get_new_mark(); CMap_dart_iterator_basic_of_involution it1(*this, adart1, m1); @@ -4509,7 +4579,13 @@ namespace CGAL { if (are_attributes_automatically_managed() && update_attributes) { - internal::Degroup_attribute_functor_run::run(*this, d1, d2); + if(merge) + { // Here we group all enabled attributes starting from 2 to dimension + Helper::template Foreach_enabled_attributes + , 2>::run(*this, adart1, adart2); + } + else // Here we degroup 2-attributes + { internal::Degroup_attribute_functor_run::run(*this, adart1, adart2); } } negate_mark(m1); diff --git a/Generalized_map/include/CGAL/Generalized_map.h b/Generalized_map/include/CGAL/Generalized_map.h index 6aa6b56045e..273d8b32bf2 100644 --- a/Generalized_map/include/CGAL/Generalized_map.h +++ b/Generalized_map/include/CGAL/Generalized_map.h @@ -1464,11 +1464,14 @@ namespace CGAL { CGAL_static_assertion(i<=dimension); CGAL_static_assertion_msg(Helper::template Dimension_index::value>=0, "set_attribute but i-attributes are disabled"); - for ( typename Dart_of_cell_range::iterator it(*this, dh); - it.cont(); ++it) + for (typename Dart_of_cell_range::iterator it(*this, dh); + it.cont(); ++it) { this->template set_dart_attribute(it, ah); } + if(ah!=null_descriptor) + // To ensure that the dart of this attribute is dh + { this->template set_dart_of_attribute(ah, dh); } } /// @return a Attributes_range (range through all the @@ -3512,7 +3515,9 @@ namespace CGAL { bool is_insertable_cell_1_in_cell_2(Dart_const_descriptor adart1, Dart_const_descriptor adart2) { - if ( adart1==adart2 || adart1==this->template alpha<0>(adart2) ) + if (adart2==null_descriptor) return true; + if (adart1==adart2 || adart1==this->template alpha<0>(adart2) || + adart1==null_descriptor || this->template is_free<1>(adart2)) return false; for ( CGAL::GMap_dart_const_iterator_of_orbit it(*this,adart1); it.cont(); ++it ) @@ -3525,29 +3530,104 @@ namespace CGAL { /** Insert an edge in a 2-cell between two given darts. * @param adart1 a first dart of the facet (!=null_descriptor && !=null_dart_descriptor). * @param adart2 a second dart of the facet. If null_descriptor insert a dangling edge. + * @param update_attributes a boolean to update the enabled attributes * @return a dart of the new edge, and not incident to the * same vertex than adart1. */ Dart_descriptor insert_cell_1_in_cell_2(Dart_descriptor adart1, - Dart_descriptor adart2, - bool update_attributes=true, - typename Attribute_descriptor<0>::type - ah=null_descriptor) + Dart_descriptor adart2, + typename Attribute_descriptor<0>:: + type ah=null_descriptor, + bool update_attributes=true) { - if ( adart2!=null_descriptor) - { - CGAL_assertion(is_insertable_cell_1_in_cell_2(adart1, adart2)); - } + CGAL_assertion(is_insertable_cell_1_in_cell_2(adart1, adart2)); + return generic_insert_cell_1(adart1, adart2, false, update_attributes, ah); + } + /** Test if an edge can be inserted between two different 2-cells + * between two given darts. + * @param adart1 a first dart. + * @param adart2 a second dart. + * @return true iff an edge can be inserted between adart1 and adart2. + */ + bool is_insertable_cell_1_between_two_cells_2(Dart_const_descriptor adart1, + Dart_const_descriptor adart2) const + { + if (adart1==adart2 || adart1==null_descriptor || adart2==null_descriptor) + { return false; } + for ( CGAL::GMap_dart_const_iterator_of_orbit it(*this,adart1); + it.cont(); ++it ) + { + if ( it==adart2 ) return false; + } + for(unsigned int d=3; d<=dimension; ++d) + { if(is_free(adart1, d)!=is_free(adart2, d)) { return false; }} + + return true; + } + + /** Insert an edge between two different 2-cells, between two given darts. + * @param adart1 a first dart of the first facet (!=null_descriptor && !=null_dart_descriptor). + * @param adart2 a second dart of the second facet (!=null_descriptor && !=null_dart_descriptor). + * @param update_attributes a boolean to update the enabled attributes + * @return a dart of the new edge, and not incident to the + * same vertex than adart1. + */ + Dart_descriptor insert_cell_1_between_two_cells_2(Dart_descriptor adart1, + Dart_descriptor adart2, + bool update_attributes=true) + { + CGAL_assertion(is_insertable_cell_1_between_two_cells_2(adart1, adart2)); + return generic_insert_cell_1(adart1, adart2, true, update_attributes); + } + + /** Insert an edge between two given darts. If the two darts belong to the same facet, call + * insert_cell_1_in_cell_2, otherwise call insert_cell_1_between_two_cells_2. + * @param adart1 a first dart (!=null_descriptor && !=null_dart_descriptor). + * @param adart2 a second dart. + * @param update_attributes a boolean to update the enabled attributes + * @return a dart of the new edge, and not incident to the + * same vertex than adart1. + */ + Dart_descriptor insert_cell_1(Dart_descriptor adart1, + Dart_descriptor adart2, + bool update_attributes=true, + typename Attribute_descriptor<0>::type + ah=null_descriptor) + { + CGAL_assertion(adart1!=null_descriptor); + if(is_insertable_cell_1_in_cell_2(adart1, adart2)) + { return insert_cell_1_in_cell_2(adart1, adart2, update_attributes, ah); } + return insert_cell_1_between_two_cells_2(adart1, adart2, update_attributes); + } + + /** Generic method to insert a 1-cell, either in a 2-cell (cf. insert_cell_1_in_cell_2) + * or between two different 2-cells (cf. insert_cell_1_between_two_cells_2). + * Indeed the code is the same, except for the group/degroup attribute. + * merge is true if adart1 and adart2 belongs to two different facets; in this case + * the two facets should be merged (they are now linked by the new edge); + * merge is false it adart1 and adart2 belongs to the same facet; in this case + * the facet is split in two. + * Internal method not supposed to be called by users. + */ + Dart_descriptor generic_insert_cell_1(Dart_descriptor adart1, + Dart_descriptor adart2, + bool merge, + bool update_attributes=true, + typename Attribute_descriptor<0>::type + ah=null_descriptor) + { /* CGAL::GMap_dart_iterator_basic_of_involution will contain all * alpha_i except alpha_0, alpha_1 and alpha_2, i.e. this is * */ + Dart_descriptor dart2_a1=null_descriptor; + if(adart2!=null_descriptor) { dart2_a1=alpha<1>(adart2); } + size_type m1=get_new_mark(); CGAL::GMap_dart_iterator_basic_of_involution it1(*this, adart1, m1); - size_type m2=get_new_mark(); - CGAL::GMap_dart_iterator_basic_of_involution it2(*this, adart2, m2); + CGAL::GMap_dart_iterator_basic_of_involution it2(*this, dart2_a1, m2); Dart_descriptor d1=null_descriptor; Dart_descriptor d2=null_descriptor; @@ -3563,44 +3643,32 @@ namespace CGAL { d2 = create_dart(); mark(it1,treated); - if (!isfree1) - { - d3 = create_dart(); - d4 = create_dart(); - this->template basic_link_alpha<2>(d1, d3); - this->template basic_link_alpha<2>(d2, d4); - } + d3 = create_dart(); + d4 = create_dart(); + this->template basic_link_alpha<2>(d1, d3); + this->template basic_link_alpha<2>(d2, d4); - for ( unsigned int dim=3; dim<=dimension; ++dim) + for (unsigned int dim=3; dim<=dimension; ++dim) { if ( !is_free(it1, dim) && is_marked(alpha(it1, dim), treated) ) { basic_link_alpha(alpha(it1, dim, 1), d1, dim); - basic_link_alpha(alpha(d1, dim, 0), d2, dim); + basic_link_alpha(alpha(it1, dim, 1, 0), d2, dim); - if (!isfree1) - { - basic_link_alpha(alpha(it1, 1, dim, 1), d3, dim); - basic_link_alpha(alpha(d3, dim, 0), d4, dim); - } + basic_link_alpha(alpha(it1, dim, 1, 2), d3, dim); + basic_link_alpha(alpha(it1, dim, 1, 2, 0), d4, dim); } } if (!isfree1) - { - this->template link_alpha<1>(this->template alpha<1>(it1), d3); - if ( adart2!=null_descriptor ) - { - CGAL_assertion (it2.cont()); - this->template link_alpha<1>(this->template alpha<1>(it2), d4); - } - } - + { this->template link_alpha<1>(this->template alpha<1>(it1), d3); } this->template link_alpha<1>(it1, d1); - if ( adart2!=null_descriptor ) + + if (adart2!=null_descriptor) { CGAL_assertion (it2.cont()); + this->template link_alpha<1>(this->template alpha<1>(it2), d4); this->template link_alpha<1>(it2, d2); ++it2; } @@ -3610,25 +3678,31 @@ namespace CGAL { update_attributes && ah!=null_descriptor) { internal::Set_i_attribute_of_dart_functor::run(*this, d2, ah); - if (!isfree1) - { - internal::Set_i_attribute_of_dart_functor::run(*this, d4, ah); - } + internal::Set_i_attribute_of_dart_functor::run(*this, d4, ah); } } // We do the link_alpha<0> after the link_alpha<1> to update the // possible attributes of d2. this->template link_alpha<0>(d1, d2); - if (!isfree1) - { this->template link_alpha<0>(d3, d4); } + this->template link_alpha<0>(d3, d4); } if (are_attributes_automatically_managed() && update_attributes) { - if ( !this->template is_free<2>(d1) && d2!=null_descriptor ) - CGAL::internal::GMap_degroup_attribute_functor_run:: - run(*this, d1, this->template alpha<2>(d1)); + if(merge) + { // Here we group all enabled attributes starting from 2 to dimension + Helper::template Foreach_enabled_attributes + , 2>:: + run(*this, adart1, adart2); + } + else // Here we degroup 2-attributes + { + // TODO if ( !this->template is_free<2>(d1) && d2!=null_descriptor ) + if (adart2!=null_descriptor) + { CGAL::internal::GMap_degroup_attribute_functor_run:: + run(*this, adart1, adart2); } + } } negate_mark(m1); @@ -3673,7 +3747,8 @@ namespace CGAL { typename Attribute_descriptor<0>:: type ah=null_descriptor, bool update_attributes=true ) - { return insert_cell_1_in_cell_2(adart1, null_descriptor, update_attributes, ah); } + { return insert_cell_1_in_cell_2(adart1, null_descriptor, ah, + update_attributes); } /** Test if a 2-cell can be inserted onto a given 3-cell along * a path of edges.