// Copyright (c) 2019 CNRS and LIRIS' Establishments (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Surface_mesh_topology/include/CGAL/Face_graph_wrapper.h $ // $Id: Face_graph_wrapper.h 52186a0 2020-05-14T11:38:15+02:00 Guillaume Damiand // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Guillaume Damiand // #ifndef CGAL_FACE_GRAPH_WRAPPER_H #define CGAL_FACE_GRAPH_WRAPPER_H 1 #include #include #include #include #include #include #include #include #include #include #include namespace CGAL { //////////////////////////////////////////////////////////////////////////////// /** Class Face_graph_wrapper: to wrap any model of FaceGraph into a * Combinatorial map. For now, only for const models, i.e. does not support * modification operators. */ template class Face_graph_wrapper { public: typedef HEG_ HEG; typedef Face_graph_wrapper Self; typedef boost::uint32_t /*std::size_t*/ size_type; typedef Self Refs; struct Dart_container { typedef typename boost::graph_traits::halfedge_iterator iterator; typedef typename boost::graph_traits::halfedge_iterator const_iterator; // TODO ? // typedef My_halfedge_iterator iterator; // typedef My_halfedge_iterator const_iterator; // TODO ? }; typedef typename boost::graph_traits::halfedge_descriptor Dart_handle; typedef typename boost::graph_traits::halfedge_descriptor Dart_const_handle; typedef Dart_handle Null_handle_type; // typedef CGAL::Void* Null_handle_type; static const Null_handle_type null_handle; //=Dart_handle(); static const Null_handle_type null_dart_handle; //=Dart_handle(); /// Number of marks static const size_type NB_MARKS = 32; static const size_type INVALID_MARK = NB_MARKS; /// The dimension of the combinatorial map. static const unsigned int dimension=2; static const unsigned int ambient_dimension=3; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; typedef boost::undirected_tag directed_category; typedef boost::disallow_parallel_edge_tag edge_parallel_category; struct SM_graph_traversal_category : public virtual boost::bidirectional_graph_tag, public virtual boost::vertex_list_graph_tag, public virtual boost::edge_list_graph_tag {}; typedef SM_graph_traversal_category traversal_category; Face_graph_wrapper(const HEG& f) : m_fg(f), mdarts(*this), m_nb_darts(0), m_marks_initialized(false), mnb_used_marks(0) { // Store locally the number of darts: the HEG must not be modified m_nb_darts=darts().size(); } void initialize_marks() const { if (m_marks_initialized) return; mmask_marks.reset(); for (size_type i=0; i >(), m_fg); for (typename Dart_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) { put(m_all_marks, it, std::bitset()); } m_marks_initialized=true; } const HEG& get_fg() const { return m_fg; } template bool is_free(Dart_const_handle /* dh */) const { return false; } // Not possible to have a free dart with an HEG. bool is_free(Dart_const_handle /*dh*/, unsigned int /*i*/) const { return false; } // Not possible to have a free dart with an HEG. bool is_perforated(Dart_const_handle dh) const { return is_border(dh, m_fg); } Dart_const_handle get_beta(Dart_const_handle ADart, int B1) const { CGAL_assertion(B1>=0 && B1<=static_cast(dimension)); if (B1==1) return internal::Get_beta::value(m_fg, ADart); if (B1==2) return internal::Get_beta::value(m_fg, ADart); return internal::Get_beta::value(m_fg, ADart); } template Dart_const_handle get_beta(Dart_const_handle ADart) const { CGAL_assertion(B1>=0 && B1<=static_cast(dimension)); return internal::Get_beta::value(m_fg, ADart); } bool is_empty() const { return number_of_darts()==0; } /* ?? bool is_dart_used(Dart_const_handle dh) const { return true; ?? } */ int highest_nonfree_dimension(Dart_const_handle /* dh */) const { return 2; } Dart_const_handle previous(Dart_const_handle ADart) const { return get_beta<0>(ADart); } Dart_const_handle next(Dart_const_handle ADart) const { return get_beta<1>(ADart); } Dart_const_handle opposite(Dart_const_handle dh) const { return get_beta<2>(dh); } Dart_const_handle opposite2(Dart_const_handle dh) const { return get_beta<2>(dh); } Dart_const_handle other_extremity(Dart_const_handle dh) const { return get_beta<1>(dh); } template Dart_const_handle opposite(Dart_const_handle ADart) const { return this->template get_beta(ADart); } Dart_const_handle other_orientation(Dart_const_handle ADart) const { return ADart; } bool is_previous_exist(Dart_const_handle) const { return true; } bool is_next_exist(Dart_const_handle) const { return true; } template bool is_opposite_exist(Dart_const_handle /* ADart */) const { return true; } template Dart_handle beta(Dart_handle ADart, Betas... betas) { return CGAL::internal::Beta_functor:: run(*this, ADart, betas...); } template Dart_const_handle beta(Dart_const_handle ADart, Betas... betas) const { return CGAL::internal::Beta_functor:: run(*this, ADart, betas...); } template Dart_handle beta(Dart_handle ADart) { return CGAL::internal::Beta_functor_static:: run(*this, ADart); } template Dart_const_handle beta(Dart_const_handle ADart) const { return CGAL::internal::Beta_functor_static:: run(*this, ADart); } size_type number_of_darts() const { return m_nb_darts; } size_type number_of_halfedges() const { return number_of_darts(); } size_type number_of_used_marks() const { return mnb_used_marks; } bool is_reserved(size_type amark) const { CGAL_assertion(amark& >(get(m_all_marks, ADart)).set(amark, avalue); } void flip_dart_mark(Dart_const_handle ADart, size_type amark) const { set_dart_mark(ADart, amark, !get_dart_mark(ADart, amark)); } bool is_marked(Dart_const_handle adart, size_type amark) const { CGAL_assertion(is_reserved(amark)); return get_dart_mark(adart, amark)!=mmask_marks[amark]; } void set_mark_to(Dart_const_handle adart, size_type amark, bool astate) const { CGAL_assertion(is_reserved(amark)); if (is_marked(adart, amark)!=astate) { if (astate) ++mnb_marked_darts[amark]; else --mnb_marked_darts[amark]; flip_dart_mark(adart, amark); } } void mark(Dart_const_handle adart, size_type amark) const { CGAL_assertion(is_reserved(amark)); if (is_marked(adart, amark)) return; ++mnb_marked_darts[amark]; flip_dart_mark(adart, amark); } void unmark(Dart_const_handle adart, size_type amark) const { CGAL_assertion( adart!=this->null_dart_handle ); CGAL_assertion( is_reserved(amark) ); if (!is_marked(adart, amark)) return; --mnb_marked_darts[amark]; flip_dart_mark(adart, amark); } void unmark_all(size_type amark) const { CGAL_assertion( is_reserved(amark) ); if ( is_whole_map_marked(amark) ) { negate_mark(amark); } else if ( !is_whole_map_unmarked(amark) ) { for (typename Dart_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) unmark(*it, amark); } CGAL_assertion(is_whole_map_unmarked(amark)); } void free_mark(size_type amark) const { CGAL_assertion( is_reserved(amark) ); if ( mnb_times_reserved_marks[amark]>1 ) { --mnb_times_reserved_marks[amark]; return; } unmark_all(amark); // 1) We remove amark from the array mused_marks_stack by // replacing it with the last mark in this array. mused_marks_stack[mindex_marks[amark]] = mused_marks_stack[--mnb_used_marks]; mindex_marks[mused_marks_stack[mnb_used_marks]] = mindex_marks[amark]; // 2) We add amark in the array mfree_marks_stack and update its index. mfree_marks_stack[ mnb_used_marks ]=amark; mindex_marks[amark] = mnb_used_marks; mnb_times_reserved_marks[amark]=0; } bool is_without_boundary(unsigned int i) const { CGAL_assertion(1<=i && i<=dimension); if (i==1) return true; for ( typename Dart_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) { if (is_perforated(it)) return false; } return true; } bool is_without_boundary() const { return is_without_boundary(2); } //************************************************************************** // Dart_of_cell_range template struct Dart_of_cell_range { typedef CGAL::internal::FGW_cell_iterator iterator; typedef CGAL::internal::FGW_cell_iterator const_iterator; Dart_of_cell_range(const Self &amap, Dart_handle adart) : mmap(amap), m_initdart(adart), msize(0) {} const_iterator begin() const { return const_iterator(mmap, m_initdart); } const_iterator end() const { return const_iterator(mmap, m_initdart, mmap.null_handle); } size_type size() const { if (msize==0) { for (const_iterator it=begin(), itend=end(); it!=itend; ++it) { ++msize; } } return msize; } bool empty() const { return mmap.is_empty(); } private: const Self & mmap; Dart_handle m_initdart; mutable typename Self::size_type msize; }; //************************************************************************** // Dart_of_cell_const_range /* template struct Dart_of_cell_const_range // TODO REMOVE ?? {}; */ //-------------------------------------------------------------------------- template Dart_of_cell_range darts_of_cell(Dart_handle adart) { return Dart_of_cell_range(*this,adart); } //-------------------------------------------------------------------------- template Dart_of_cell_range darts_of_cell(Dart_const_handle adart) const { return Dart_of_cell_range(*this,adart); } // Before it was Dart_of_cell_const_range //************************************************************************** // Dart_range struct Dart_range { typedef CGAL::internal::FGW_dart_iterator_basic_of_all iterator; typedef CGAL::internal::FGW_dart_iterator_basic_of_all const_iterator; Dart_range(const Self &amap) : mmap(amap), msize(0) {} iterator begin() { return iterator(mmap); } iterator end() { return iterator(mmap,mmap.null_handle); } const_iterator begin() const { return const_iterator(mmap); } const_iterator end() const { return const_iterator(mmap,mmap.null_handle); } size_type size() const { if (msize==0) { msize=static_cast(halfedges(mmap.get_fg()).size()); } return msize; } bool empty() const { return mmap.is_empty(); } size_type capacity() const { return static_cast(num_halfedges(mmap.get_fg())); } bool is_used(size_type i) const { return internal::Is_index_used::run(mmap.get_fg(), i); } size_type index(const_iterator it) const { return internal::Index_from_halfedge_descriptor:: run(mmap.get_fg(), *it); } size_type index(Dart_const_handle it) const { return internal::Index_from_halfedge_descriptor:: run(mmap.get_fg(), it); } private: const Self & mmap; mutable typename Self::size_type msize; }; //************************************************************************** // Dart_const_range // TODO REMOVE ? /* struct Dart_const_range { typedef CGAL::FGW_dart_iterator_basic_of_all const_iterator; Dart_const_range(const Self &amap) : mmap(amap), msize(0) {} const_iterator begin() const { return const_iterator(mmap); } const_iterator end() const { return const_iterator(mmap,mmap.null_handle); } size_type size() const { if (msize==0) { for (const_iterator it=begin(), itend=end(); it!=itend; ++it) { ++msize; } } return msize; } bool empty() const { return mmap.is_empty(); } private: const Self & mmap; mutable typename Self::size_type msize; };*/ //************************************************************************** Dart_range& darts() { return mdarts; } //-------------------------------------------------------------------------- const Dart_range& darts() const { return mdarts; } // Before it was Dart_const_range(*this) //************************************************************************** Dart_handle dart_handle(size_type i) { CGAL_assertion(darts().is_used(i)); return internal::Halfedge_descriptor_from_index::run(get_fg(), i); } Dart_const_handle dart_handle(size_type i) const { CGAL_assertion(darts().is_used(i)); return internal::Halfedge_descriptor_from_index::run(get_fg(), i); } template bool belong_to_same_cell(Dart_const_handle adart1, Dart_const_handle adart2) const { for (typename Dart_of_cell_range::iterator it=darts_of_cell(adart1).begin(), itend=darts_of_cell(adart1).end(); it!=itend; ++it) { if (*it==adart2) { return true; } } return false; } template bool is_whole_cell_unmarked(Dart_const_handle adart, size_type amark) const { for (typename Dart_of_cell_range::iterator it=darts_of_cell(adart).begin(), itend=darts_of_cell(adart).end(); it!=itend; ++it) { if (is_marked(*it, amark)) { return false; } } return true; } template bool is_whole_cell_marked(Dart_const_handle adart, size_type amark) const { for (typename Dart_of_cell_range::iterator it=darts_of_cell(adart).begin(), itend=darts_of_cell(adart).end(); it!=itend; ++it) { if (!is_marked(*it, amark)) { return false; } } return true; } template size_type mark_cell(Dart_const_handle adart, size_type amark) 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; } return res; } size_type mark_cell(Dart_const_handle adart, unsigned int i, size_type amark) const { if (i==0) { return mark_cell<0>(adart, amark); } else if (i==1) { return mark_cell<1>(adart, amark); } else if (i==2) { return mark_cell<2>(adart, amark); } return mark_cell<3>(adart, amark); } template size_type unmark_cell(Dart_const_handle adart, size_type amark) 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; } 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); return number_of_darts(); } std::vector count_marked_cells(size_type amark, const std::vector& acells) const { std::vector res(dimension+2); std::vector marks(dimension+2); // Initialization of the result for (unsigned int i=0; i tounmark; for (unsigned int i=0; i0) { for (typename Dart_range::const_iterator it(darts().begin()), itend(darts().end()); it!=itend; ++it) { for (unsigned int i=0; i count_cells(const std::vector& acells) const { std::vector res; size_type m=get_new_mark(); negate_mark(m); // We mark all the cells. res=count_marked_cells(m, acells); negate_mark(m); // We unmark the cells free_mark(m); return res; } std::vector count_all_cells() const { std::vector dim(dimension+2); for ( unsigned int i=0; i<=dimension+1; ++i) { dim[i]=i; } return count_cells(dim); } std::ostream& display_characteristics(std::ostream & os) const { std::vector cells(dimension+2); for ( unsigned int i=0; i<=dimension+1; ++i) { cells[i]=i; } std::vector res=count_cells(cells); os<<"#Darts="< > >::const_type MarkPMap; mutable MarkPMap m_all_marks; }; /// null_handle // template // const typename Face_graph_wrapper::Null_handle_type // Face_graph_wrapper::null_handle=nullptr; template const typename Face_graph_wrapper::Null_handle_type Face_graph_wrapper::null_handle=typename Face_graph_wrapper::Dart_handle(); /// null_dart_handle // template // const typename Face_graph_wrapper::Null_handle_type // Face_graph_wrapper::null_dart_handle=nullptr; template const typename Face_graph_wrapper::Null_handle_type Face_graph_wrapper::null_dart_handle=typename Face_graph_wrapper::Dart_handle(); template struct Get_map { typedef Face_graph_wrapper type; typedef const Face_graph_wrapper storage_type; Get_map(const HEG& heg): m_map(heg) {} static const HEG& get_mesh(const storage_type& amap) { return amap.get_fg(); } storage_type m_map; }; template struct Get_map, Map> { typedef Map type; typedef const Map& storage_type; Get_map(const Map& heg): m_map(heg) {} static const Map& get_mesh(storage_type& amap) { return amap; } storage_type m_map; }; template struct Get_map, Map> { typedef Map type; typedef const Map& storage_type; Get_map(const Map& heg): m_map(heg) {} static const Map& get_mesh(storage_type& amap) { return amap; } storage_type m_map; }; template class Map, typename Refs, typename Storage, class LCC> struct Get_map, LCC> { typedef LCC type; typedef const LCC& storage_type; Get_map(const LCC& heg): m_map(heg) {} static const LCC& get_mesh(storage_type& amap) { return amap; } storage_type m_map; }; template struct Get_map, Map> { typedef Map type; typedef const Map& storage_type; Get_map(const Map& heg): m_map(heg) {} static const Map& get_mesh(storage_type& amap) { return amap; } storage_type m_map; }; template struct Get_map, Map> { typedef Map type; typedef const Map& storage_type; Get_map(const Map& heg): m_map(heg) {} static const Map& get_mesh(storage_type& amap) { return amap; } storage_type m_map; }; template struct Get_map, Map> { typedef Map type; typedef const Map& storage_type; Get_map(const Map& heg): m_map(heg) {} static const Map& get_mesh(storage_type& amap) { return amap; } storage_type m_map; }; template struct Get_map, Map> { typedef Map type; typedef const Map& storage_type; Get_map(const Map& heg): m_map(heg) {} static const Map& get_mesh(storage_type& amap) { return amap; } storage_type m_map; }; template class Map, typename Storage, class LCC> struct Get_map, LCC> { typedef LCC type; typedef const LCC& storage_type; Get_map(const LCC& heg): m_map(heg) {} static const LCC& get_mesh(storage_type& amap) { return amap; } storage_type m_map; }; template class Map, typename Storage, class LCC> struct Get_map, LCC> { typedef LCC type; typedef const LCC& storage_type; Get_map(const LCC& heg): m_map(heg) {} static const LCC& get_mesh(storage_type& amap) { return amap; } storage_type m_map; }; template struct Get_traits { typedef Mesh_ Mesh; typedef typename Mesh::Traits Kernel; typedef typename Mesh::Point Point; typedef typename Mesh::Vector Vector; template static const Point& get_point(const Mesh& m, Dart_handle dh) { return m.point(dh); } }; template struct Get_traits > { typedef CGAL::Surface_mesh

Mesh; typedef typename CGAL::Kernel_traits

::Kernel Kernel; typedef typename Kernel::Point_3 Point; typedef typename Kernel::Vector_3 Vector; template static const Point& get_point(const Mesh& m, Dart_handle dh) { return m.point(m.source(dh)); } }; template class T_HDS, class Alloc> struct Get_traits > { typedef CGAL::Polyhedron_3 Mesh; typedef PolyhedronTraits_3 Kernel; typedef typename Kernel::Point_3 Point; typedef typename Kernel::Vector_3 Vector; template static const Point& get_point(const Mesh& /*m*/, Dart_handle dh) { return dh->opposite()->vertex()->point(); } }; } // Namespace CGAL #endif // CGAL_FACE_GRAPH_WRAPPER_H // // EOF //