diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map_functionalities.h b/Combinatorial_map/include/CGAL/Combinatorial_map_functionalities.h index 38a6f3d5884..ff1a8e6f506 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map_functionalities.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map_functionalities.h @@ -1080,11 +1080,34 @@ namespace CGAL { } // Simplify the path by removing all spurs + // @return true iff at least one spur was removed bool remove_spurs(Path_on_surface& path) const { + /* TODO TEMPO POUR TEST */ + Path_on_surface_with_rle prle(path); + prle.remove_spurs(); + /* TODO FIN TEMPO POUR TEST */ + bool res=false; while(remove_spurs_one_step(path)) { res=true; } + + /* TODO TEMPO POUR TEST */ + Path_on_surface p2(prle); + if (p2!=path) + { + std::cout<<"Error: p2!=path: "<(get_ith_dart(i)); Dart_const_handle d2=m_map.template beta<2>(get_next_dart(i)); @@ -402,7 +398,6 @@ public: return res; } - std::vector compute_positive_turns() const { std::vector res; @@ -410,17 +405,9 @@ public: std::size_t i; for (i=0; i(m_path[i+1])) - { res.push_back(0); } - else { res.push_back(next_positive_turn(i)); } - } + { res.push_back(next_positive_turn(i)); } if (is_closed()) - { - if (m_path[i]==m_map.template beta<2>(m_path[0])) - { res.push_back(0); } - else { res.push_back(next_positive_turn(i)); } - } + { res.push_back(next_positive_turn(i)); } return res; } @@ -431,17 +418,9 @@ public: std::size_t i; for (i=0; i(m_path[i+1])) - { res.push_back(0); } - else { res.push_back(next_negative_turn(i)); } - } + { res.push_back(next_negative_turn(i)); } if (is_closed()) - { - if (m_path[i]==m_map.template beta<2>(m_path[0])) - { res.push_back(0); } - else { res.push_back(next_negative_turn(i)); } - } + { res.push_back(next_negative_turn(i)); } return res; } diff --git a/Combinatorial_map/include/CGAL/Path_on_surface_with_rle.h b/Combinatorial_map/include/CGAL/Path_on_surface_with_rle.h index e8c8392f57c..24ddc1e0d8c 100644 --- a/Combinatorial_map/include/CGAL/Path_on_surface_with_rle.h +++ b/Combinatorial_map/include/CGAL/Path_on_surface_with_rle.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace CGAL { @@ -40,6 +41,9 @@ public: typedef Map_ Map; typedef typename Map::Dart_handle Dart_handle; typedef typename Map::Dart_const_handle Dart_const_handle; + typedef std::list > List_of_dart_length; + typedef typename List_of_dart_length::iterator List_iterator; + typedef typename List_of_dart_length::const_iterator List_const_iterator; typedef Path_on_surface_with_rle Self; @@ -52,6 +56,8 @@ public: m_is_closed(apath.is_closed()), m_length(apath.length()) { + if (apath.is_empty()) return; + std::size_t i=0, j=0, starti=0, length=0; bool positive_flat=false; bool negative_flat=false; @@ -160,6 +166,276 @@ public: return true; } + void advance_iterator(List_iterator& it) + { + assert(it!=m_path.end()); + it=std::next(it); + if (is_closed() && it==m_path.end()) + { it=m_path.begin(); } // Here the path is closed, and it is the last element of the list + } + + void advance_iterator(List_const_iterator& it) const + { + assert(it!=m_path.end()); + it=std::next(it); + if (is_closed() && it==m_path.end()) + { it=m_path.begin(); } // Here the path is closed, and it is the last element of the list + } + + void retreat_iterator(List_iterator& it) + { + assert(it!=m_path.end()); + assert(it!=m_path.begin() || is_closed()); + if (is_closed() && it==m_path.begin()) + { it=m_path.end(); } + it=std::prev(it); + } + + void retreat_iterator(List_const_iterator& it) const + { + assert(it!=m_path.end()); + assert(it!=m_path.begin() || is_closed()); + if (is_closed() && it==m_path.begin()) + { it=m_path.end(); } + it=std::prev(it); + } + + List_iterator next_iterator(const List_iterator& it) + { + List_iterator res=it; + advance_iterator(res); + return res; + } + + List_const_iterator next_iterator(const List_const_iterator& it) const + { + List_const_iterator res=it; + advance_iterator(res); + return res; + } + + List_iterator prev_iterator(const List_iterator& it) const + { + List_iterator res=it; + retreat_iterator(res); + return res; + } + + List_const_iterator prev_iterator(const List_const_iterator& it) const + { + List_const_iterator res=it; + retreat_iterator(res); + return res; + } + + // @return true iff there is a dart after it + bool next_dart_exist(const List_const_iterator& it) const + { + assert(it!=m_path.end()); + return is_closed() || std::next(it)!=m_path.end(); + } + + // Return true if it is the beginning of a spur. + bool is_spur(const List_const_iterator& it) const + { + assert(it!=m_path.end()); + return it->second==0 && + next_dart_exist(it) && + m_map.template beta<2>(it->first)==next_iterator(it)->first; + } + + // Remove the spur given by it; move it to the element before it + // (m_path.end() if the path becomes empty). + void remove_spur(List_iterator& it) + { + assert(is_spur(it)); + it=m_path.erase(it); // Erase the first dart of the spur + if (is_closed() && it==m_path.end()) + { it=m_path.begin(); } + + if (it->second==0) // a flat part having only one dart + { + it=m_path.erase(it); // Erase the second dart of the spur + if (is_closed() && it==m_path.end()) + { it=m_path.begin(); } + } + else + { // Here we need to reduce the length of the flat part + if (it->second>0) + { + --(it->second); + it->first=m_map.template beta<1, 2, 1>(it->first); + } + else + { + ++(it->second); + it->first=m_map.template beta<2, 0, 2, 0, 2>(it->first); + } + } + + // Now move it to the element before the removed spur + // except if the path has become empty, or if it is not closed + // and we are in its first element. + if (m_path.empty()) + { + assert(it==m_path.end()); + m_is_closed=false; + } + else if (is_closed() || it!=m_path.begin()) + { + retreat_iterator(it); // go to the previous element + // TODO we need to test if the previous flat part should be merged with the next one + if (compute_positive_turns(it, next(it))==2 || compute_negative_turns(it, next(it))==2 ) + { + + } + } + } + + // Move it to the next spur after it. Go to m_path.end() if there is no + // spur in the path. + void move_to_next_spur(List_iterator& it) + { + assert(it!=m_path.end()); + List_iterator itend=(is_closed()?it:m_path.end()); + do + { + advance_iterator(it); + if (is_spur(it)) { return; } + } + while(it!=itend); + it=m_path.end(); // Here there is no spur in the whole path + } + + // Simplify the path by removing all spurs + // @return true iff at least one spur was removed + bool remove_spurs() + { + bool res=false; + List_iterator it=m_path.begin(); + while(it!=m_path.end()) + { + if (is_spur(it)) { remove_spur(it); res=true; } + else { move_to_next_spur(it); } + } + return res; + } + + /// @return the turn between dart it and next dart. + /// (turn is position of the second edge in the cyclic ordering of + /// edges starting from the first edge around the second extremity + /// of the first dart) + std::size_t next_positive_turn(const List_const_iterator& it) const + { + assert(is_valid()); + assert(it!=m_path.end()); + assert(is_closed() || std::next(it)!=m_path.end()); + + Dart_const_handle d1=it->first; + if (it->second!=0) + { + if (it->second<0) { return -(it->second); } + else { return it->second; } + } + + Dart_const_handle d2=next_iterator(it)->first; + assert(d1!=d2); + + if (d2==m_map.template beta<2>(d1)) + { return 0; } + + std::size_t res=1; + while (m_map.template beta<1>(d1)!=d2) + { + ++res; + d1=m_map.template beta<1, 2>(d1); + } + // std::cout<<"next_positive_turn="<(it->first); + if (it->second!=0) + { + if (it->second<0) { return -(it->second); } + else { return it->second; } + } + + Dart_const_handle d2=m_map.template beta<2>(next_iterator(it)->first); + assert(d1!=d2); + + if (d2==m_map.template beta<2>(d1)) + { return 0; } + + std::size_t res=1; + while (m_map.template beta<0>(d1)!=d2) + { + ++res; + d1=m_map.template beta<0, 2>(d1); + } + // std::cout<<"next_negative_turn="< compute_positive_turns() const + { + std::vector res; + if (is_empty()) return res; + for (auto it=m_path.begin(), itend=m_path.end(); it!=itend; ++it) + { + if (is_closed() || std::next(it)!=m_path.end()) + { res.push_back(next_positive_turn(it)); } + } + return res; + } + + std::vector compute_negative_turns() const + { + std::vector res; + if (is_empty()) return res; + for (auto it=m_path.begin(), itend=m_path.end(); it!=itend; ++it) + { + if (is_closed() || std::next(it)!=m_path.end()) + { res.push_back(next_negative_turn(it)); } + } + return res; + } + + std::vector compute_turns(bool positive) const + { return (positive?compute_positive_turns():compute_negative_turns()); } + + void display_positive_turns() const + { + std::cout<<"+("; + std::vector res=compute_positive_turns(); + for (std::size_t i=0; i res=compute_negative_turns(); + for (std::size_t i=0; i > m_path; // The sequence of turning darts, plus the length of the flat part after the dart (a flat part is a sequence of dart with positive turn == 2). If negative value k, -k is the length of the flat part, for negative turns (-2). + List_of_dart_length m_path; // The sequence of turning darts, plus the length of the flat part after the dart (a flat part is a sequence of dart with positive turn == 2). If negative value k, -k is the length of the flat part, for negative turns (-2). bool m_is_closed; // True iff the path is a cycle std::size_t m_length; };