From 3fb644e56628c4845a256508ab0a2024ed6a3295 Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Fri, 10 Apr 2020 17:40:30 +0200 Subject: [PATCH] Improve basic viewer to draw consistent orientated faces for generalized maps. --- .../include/CGAL/Combinatorial_map.h | 14 ++ .../CGAL/Combinatorial_map_basic_operations.h | 174 ++++++++++++++++-- .../include/CGAL/Generalized_map.h | 26 +++ .../include/CGAL/draw_linear_cell_complex.h | 13 ++ .../include/CGAL/Face_graph_wrapper.h | 31 ++++ .../Functors_for_face_graph_wrapper.h | 6 +- .../include/CGAL/draw_face_graph_with_paths.h | 14 +- 7 files changed, 261 insertions(+), 17 deletions(-) diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map.h b/Combinatorial_map/include/CGAL/Combinatorial_map.h index ee36d7f5147..d439868c3eb 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map.h @@ -76,6 +76,7 @@ namespace CGAL { */ struct Combinatorial_map_tag {}; + struct Generalized_map_tag; /** Generic definition of combinatorial map in dD. * The Combinatorial_map class describes an dD combinatorial map. It allows @@ -1212,6 +1213,19 @@ namespace CGAL { size_type unmark_cell(Dart_const_handle adart, size_type amark) const { return CGAL::unmark_cell(*this, adart, amark); } + template + size_type mark_oriented_cell(Dart_const_handle adart, size_type amark, + size_type amark2=INVALID_MARK) const + { return CGAL::mark_oriented_cell(*this, adart, amark, amark2); } + + template + size_type unmark_oriented_cell(Dart_const_handle adart, size_type amark, + size_type amark2=INVALID_MARK) const + { return CGAL::unmark_oriented_cell(*this, adart, amark, amark2); } + + std::size_t orient(size_type amark) const + { negate_mark(amark); } + /** Test if this map is without boundary for a given dimension. * @param i the dimension. * @return true iff all the darts are not i-free. diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map_basic_operations.h b/Combinatorial_map/include/CGAL/Combinatorial_map_basic_operations.h index 97d925e2198..6edc5e658cb 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map_basic_operations.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map_basic_operations.h @@ -81,7 +81,7 @@ namespace CGAL typename Map::size_type amark) { amap.negate_mark(amark); - bool res=CGAL::is_whole_orbit_marked(amap, adart, amark); + bool res=CGAL::template is_whole_orbit_marked(amap, adart, amark); amap.negate_mark(amark); return res; } @@ -128,7 +128,7 @@ namespace CGAL { amap.negate_mark(amark); typename Map::size_type - res=CGAL::mark_orbit(amap, adart, amark); + res=CGAL::template mark_orbit(amap, adart, amark); amap.negate_mark(amark); return res; } @@ -154,7 +154,7 @@ namespace CGAL typename Map::Dart_const_handle adart1, typename Map::Dart_const_handle adart2) { - return CGAL::belong_to_same_cell(amap,adart1,adart2); + return CGAL::template belong_to_same_cell(amap,adart1,adart2); } @@ -169,7 +169,7 @@ namespace CGAL typename Map::Dart_const_handle adart, typename Map::size_type amark) { - return CGAL::is_whole_orbit_marked::const_iterator> (amap, adart, amark); } @@ -179,7 +179,8 @@ namespace CGAL typename Map::Dart_const_handle adart, typename Map::size_type amark) { - return CGAL::is_whole_cell_marked(amap,adart,amark); + return CGAL::template is_whole_cell_marked + (amap,adart,amark); } /** Test if all the darts of a given cell are unmarked. @@ -193,7 +194,7 @@ namespace CGAL typename Map::Dart_const_handle adart, typename Map::size_type amark) { - return CGAL::is_whole_orbit_unmarked::const_iterator> (amap, adart, amark); } @@ -203,7 +204,7 @@ namespace CGAL typename Map::Dart_const_handle adart, typename Map::size_type amark) { - return CGAL::is_whole_cell_unmarked + return CGAL::template is_whole_cell_unmarked (amap,adart,amark); } @@ -218,7 +219,7 @@ namespace CGAL typename Map::size_type mark_cell(const Map & amap, typename Map::Dart_const_handle adart, typename Map::size_type amark) - { return CGAL::mark_orbit::const_iterator> (amap, adart, amark); } @@ -226,9 +227,9 @@ namespace CGAL typename Map::size_type mark_cell(const Map & amap, typename Map::Dart_const_handle adart, typename Map::size_type amark) - { return CGAL::mark_cell(amap, adart, amark);} + { return CGAL::template mark_cell(amap, adart, amark);} - /** Unmark a given orbit with a given mark. + /** Unmark a given cell with a given mark. * @param amap a combinatorial map. * @param adart a dart of the cell. * @param amark the mark. @@ -239,7 +240,7 @@ namespace CGAL typename Map::size_type unmark_cell(const Map & amap, typename Map::Dart_const_handle adart, typename Map::size_type amark) - { return CGAL::unmark_orbit::const_iterator> (amap, adart, amark);} @@ -247,7 +248,156 @@ namespace CGAL typename Map::size_type unmark_cell(const Map & amap, typename Map::Dart_const_handle adart, typename Map::size_type amark) - { return CGAL::unmark_cell(amap, adart, amark); } + { return CGAL::template unmark_cell(amap, adart, amark); } + + /// Functor to test if the given dart must be marked, when we want + /// to mark an oriented orbit. By default (for CMap), return true. + template + struct Need_to_mark_for_oriented_cell + { + static bool run(const Map & /*amap*/, + typename Map::Dart_const_handle /*adart*/, + typename Map::size_type /*amark*/, + OperationState /*op*/) + { return true; } + }; + + struct Generalized_map_tag; + + /// Specialization for GMap. We mark one out of two darts. + template + struct Need_to_mark_for_oriented_cell + { + static bool run(const Map & amap, + typename Map::Dart_const_handle adart, + typename Map::size_type amark, + OperationState op) + { + CGAL_assertion(op!=OP_END); + + if (op==OP_NONE) return true; + + bool all_darts_unmarked=true; + for (int i=0; all_darts_unmarked && i<=(int)Map::dimension; ++i) + { + if (!amap.is_free(adart, i) && + amap.is_marked(amap.alpha(adart, i), amark)) + { all_darts_unmarked=false; } + } + return all_darts_unmarked; + } + }; + + /** Mark a given oriented orbit with a given mark. For combinatorial map, + * equivalent to mark_orbit. For generalized map, mark one out of two dart + * if the orbit is orientable. If amark2!=INVALID_MARK, mark also all the darts + * of the orbit with amark2. + * @param amap a combinatorial map / generalized. + * @param adart a dart of the orbit. + * @param amark the mark. + * @param amark2 a second mark. + * @return the number of darts of the marked orbit. + * @pre The whole orbit must be unmarked. + */ + template < class Map, class Iterator > + typename Map::size_type mark_oriented_orbit(const Map & amap, + typename Map::Dart_const_handle adart, + typename Map::size_type amark, + typename Map::size_type amark2=Map::INVALID_MARK) + { + CGAL_static_assertion( (boost::is_same::value) ); + CGAL_assertion( (is_whole_orbit_unmarked > + (amap, adart, amark)) ); + typename Map::size_type res=0; + typename Map::size_type amark3=(amark2==Map::INVALID_MARK?amap.get_new_mark():amark2); + for (Iterator it(amap, adart, amark3); it.cont(); ++it) + { + amap.mark(it, amark3); + if (CGAL::template Need_to_mark_for_oriented_cell:: + run(amap, it, amark, it.prev_operation())) + { + amap.mark(it, amark); + ++res; + } + } + + if (amark2==Map::INVALID_MARK) + { + CGAL::template unmark_orbit(amap, adart, amark3); + amap.free_mark(amark3); + } + + return res; + } + + template < class Map, class Iterator > + typename Map::size_type unmark_oriented_orbit(const Map & amap, + typename Map::Dart_const_handle adart, + typename Map::size_type amark, + typename Map::size_type amark2=Map::INVALID_MARK) + { + amap.negate_mark(amark); + if (amark2!=Map::INVALID_MARK) { amap.negate_mark(amark2); } + typename Map::size_type + res=CGAL::template mark_oriented_orbit(amap, adart, amark, amark2); + amap.negate_mark(amark); + if (amark2!=Map::INVALID_MARK) { amap.negate_mark(amark2); } + return res; + } + + /** Mark a given oriented cell with a given mark. For combinatorial map, + * equivalent to mark_cell. For generalized map, mark one out of two dart + * if the cell is orientable. If amark2!=INVALID_MARK, mark also all the darts + * of the cell with amark2. + * @param amap a combinatorial map / generalized. + * @param adart a dart of the cell. + * @param amark the mark. + * @param amark2 a second mark. + * @return the number of darts of the marked cell. + * @pre The whole cell must be unmarked. + */ + template < class Map, unsigned int i, unsigned int d > + typename Map::size_type mark_oriented_cell(const Map & amap, + typename Map::Dart_const_handle adart, + typename Map::size_type amark, + typename Map::size_type amark2=Map::INVALID_MARK) + { return CGAL::template mark_oriented_orbit + ::const_iterator> + (amap, adart, amark, amark2); } + + template < class Map, unsigned int i> + typename Map::size_type mark_oriented_cell(const Map & amap, + typename Map::Dart_const_handle adart, + typename Map::size_type amark, + typename Map::size_type amark2=Map::INVALID_MARK) + { return CGAL::template mark_oriented_cell + (amap, adart, amark, amark2);} + + /** Unmark a given oriented cell with a given mark. + * @param amap a combinatorial map. + * @param adart a dart of the cell. + * @param amark the mark. + * @return the number of darts of the unmarked cell. + * @pre The whole cell must be marked. + */ + template < class Map, unsigned int i, unsigned int d > + typename Map::size_type unmark_oriented_cell(const Map & amap, + typename Map::Dart_const_handle adart, + typename Map::size_type amark, + typename Map::size_type amark2=Map::INVALID_MARK) + { return CGAL::template unmark_oriented_orbit + ::const_iterator> + (amap, adart, amark, amark2);} + + template < class Map, unsigned int i > + typename Map::size_type unmark_oriented_cell(const Map & amap, + typename Map::Dart_const_handle adart, + typename Map::size_type amark, + typename Map::size_type amark2=Map::INVALID_MARK) + { return CGAL::template unmark_oriented_cell + (amap, adart, amark, amark2); } /** Compute the degree of a given i-cell c. * The degree is the number of distinct i+1 cells incident to c. diff --git a/Generalized_map/include/CGAL/Generalized_map.h b/Generalized_map/include/CGAL/Generalized_map.h index 27512a98a1f..fcf7addf65c 100644 --- a/Generalized_map/include/CGAL/Generalized_map.h +++ b/Generalized_map/include/CGAL/Generalized_map.h @@ -52,6 +52,7 @@ namespace CGAL { * Definition of generic dD Generalized map. */ + struct Combinatorial_map_tag; struct Generalized_map_tag {}; /** Generic definition of generalized map in dD. @@ -1035,6 +1036,31 @@ namespace CGAL { size_type unmark_cell(Dart_const_handle adart, size_type amark) const { return CGAL::unmark_cell(*this, adart, amark); } + template + size_type mark_oriented_cell(Dart_const_handle adart, size_type amark, + size_type amark2=INVALID_MARK) const + { return CGAL::mark_oriented_cell(*this, adart, amark, amark2); } + + template + size_type unmark_oriented_cell(Dart_const_handle adart, size_type amark, + size_type amark2=INVALID_MARK) const + { return CGAL::unmark_oriented_cell(*this, adart, amark, amark2); } + + std::size_t orient(size_type amark) const + { + size_type amark2=get_new_mark(); + std::size_t res=0; + for (auto it=darts().begin(), itend=darts().end(); it!=itend; ++it) + { + if (!is_marked(it, amark2)) + { res+=mark_oriented_cell(it, amark, amark2); } // Mark the connected componend + } + CGAL_assertion(is_whole_map_marked(amark2)); + free_mark(amark2); + + return res; + } + /** Test if this map is without boundary for a given dimension. * @param i the dimension. * @return true iff all the darts are not i-free. diff --git a/Linear_cell_complex/include/CGAL/draw_linear_cell_complex.h b/Linear_cell_complex/include/CGAL/draw_linear_cell_complex.h index a212a24386b..6f630b2c0b1 100644 --- a/Linear_cell_complex/include/CGAL/draw_linear_cell_complex.h +++ b/Linear_cell_complex/include/CGAL/draw_linear_cell_complex.h @@ -170,17 +170,28 @@ public: // First draw: vertices; edges, faces; multi-color; inverse normal Base(parent, title, true, true, true, false, false), lcc(alcc), + m_oriented_mark(lcc->get_new_mark()), m_nofaces(anofaces), m_random_face_color(false), m_drawing_functor(drawing_functor) { + lcc->orient(m_oriented_mark); compute_elements(); } + ~SimpleLCCViewerQt() + { lcc->free_mark(m_oriented_mark); } + protected: void set_lcc(const LCC* alcc, bool doredraw=true) { + if (lcc!=nullptr) + { lcc->free_mark(m_oriented_mark); } + lcc=alcc; + m_oriented_mark=lcc->get_new_mark(); + lcc->orient(m_oriented_mark); + compute_elements(); if (doredraw) { redraw(); } } @@ -279,6 +290,7 @@ protected: { lcc->mark(itv, markvolumes); // To be sure that all darts of the basic iterator will be marked if (!lcc->is_marked(itv, markfaces) && + lcc->is_marked(itv, m_oriented_mark) && m_drawing_functor.draw_face(*lcc, itv)) { if (!m_drawing_functor.volume_wireframe(*lcc, itv) && @@ -360,6 +372,7 @@ protected: protected: const LCC* lcc; + typename LCC::size_type m_oriented_mark; bool m_nofaces; bool m_random_face_color; const DrawingFunctorLCC& m_drawing_functor; diff --git a/Surface_mesh_topology/include/CGAL/Face_graph_wrapper.h b/Surface_mesh_topology/include/CGAL/Face_graph_wrapper.h index 9817e94a70c..76441b9c570 100644 --- a/Surface_mesh_topology/include/CGAL/Face_graph_wrapper.h +++ b/Surface_mesh_topology/include/CGAL/Face_graph_wrapper.h @@ -557,6 +557,37 @@ public: return res; } + template + size_type mark_oriented_cell(Dart_const_handle adart, size_type amark, + size_type amark2=INVALID_MARK) const + { + size_type res=0; + for (typename Dart_of_cell_range::iterator it=darts_of_cell(adart).begin(), + itend=darts_of_cell(adart).end(); it!=itend; ++it) + { + mark(*it, amark); ++res; + if (amark2!=INVALID_MARK) { mark(*it, amark2); } + } + return res; + } + + template + size_type unmark_oriented_cell(Dart_const_handle adart, size_type amark, + size_type amark2=INVALID_MARK) const + { + size_type res=0; + for (typename Dart_of_cell_range::iterator it=darts_of_cell(adart).begin(), + itend=darts_of_cell(adart).end(); it!=itend; ++it) + { + unmark(*it, amark); ++res; + if (amark2!=INVALID_MARK) { unmark(*it, amark2); } + } + return res; + } + + std::size_t orient(size_type amark) const + { negate_mark(amark); } + std::vector count_marked_cells(size_type amark, const std::vector& acells) const { diff --git a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Functors_for_face_graph_wrapper.h b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Functors_for_face_graph_wrapper.h index b83e770f109..4f00ee656f2 100644 --- a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Functors_for_face_graph_wrapper.h +++ b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Functors_for_face_graph_wrapper.h @@ -76,7 +76,7 @@ struct Index_from_halfedge_descriptor halfedge_descriptor; static size_type run(const Mesh& m, halfedge_descriptor h) - { std::cout<<"V1"<::halfedge_iterator it=halfedges(m).begin(), itend=halfedges(m).end(); it!=itend; ++it, ++res) @@ -93,7 +93,7 @@ struct Index_from_halfedge_descriptor > halfedge_descriptor; static size_type run(const Mesh& /*m*/, halfedge_descriptor h) - { std::cout<<"V2"< @@ -120,7 +120,7 @@ struct Halfedge_descriptor_from_index > halfedge_descriptor; static halfedge_descriptor run(const Mesh& /*m*/, size_type i) - { std::cout<<"V2"< diff --git a/Surface_mesh_topology/include/CGAL/draw_face_graph_with_paths.h b/Surface_mesh_topology/include/CGAL/draw_face_graph_with_paths.h index 5e2115d5d9c..bcfb2f6bb7b 100644 --- a/Surface_mesh_topology/include/CGAL/draw_face_graph_with_paths.h +++ b/Surface_mesh_topology/include/CGAL/draw_face_graph_with_paths.h @@ -110,6 +110,7 @@ public: Base(parent, title, true, true, true, false, true), mesh(amesh), lcc(amesh), + m_oriented_mark(lcc.get_new_mark()), m_nofaces(anofaces), m_drawing_functor(drawing_functor), m_paths(paths), @@ -118,7 +119,15 @@ public: m_draw_marked_darts(true), m_amark(amark==std::numeric_limits::max()? LCC::INVALID_MARK:amark) - { compute_elements(); } + { + lcc.orient(m_oriented_mark); + compute_elements(); + } + + ~Face_graph_with_path_viewer() + { + lcc.free_mark(m_oriented_mark); + } protected: @@ -167,7 +176,7 @@ protected: itend=lcc.darts().end(); it!=itend; ++it ) { if (!m_nofaces && !lcc.is_marked(it, markfaces) && - !lcc.is_perforated(it)) + !lcc.is_perforated(it) && lcc.is_marked(it, m_oriented_mark)) { compute_face(it); lcc.template mark_cell<2>(it, markfaces); @@ -371,6 +380,7 @@ protected: protected: const Mesh& mesh; const typename Get_map::storage_type lcc; + typename LCC::size_type m_oriented_mark; bool m_nofaces; const DrawingFunctorLCC& m_drawing_functor; const std::vector >* m_paths;