1:45 PM 11/12/2025 ���� JFIF    �� �        "" $(4,$&1'-=-157:::#+?D?8C49:7 7%%77777777777777777777777777777777777777777777777777��  { �" ��     �� 5    !1AQa"q�2��BR��#b�������  ��  ��   ? ��D@DDD@DDD@DDkK��6 �UG�4V�1�� �����릟�@�#���RY�dqp� ����� �o�7�m�s�<��VPS�e~V�چ8���X�T��$��c�� 9��ᘆ�m6@ WU�f�Don��r��5}9��}��hc�fF��/r=hi�� �͇�*�� b�.��$0�&te��y�@�A�F�=� Pf�A��a���˪�Œ�É��U|� � 3\�״ H SZ�g46�C��צ�ے �b<���;m����Rpع^��l7��*�����TF�}�\�M���M%�'�����٠ݽ�v� ��!-�����?�N!La��A+[`#���M����'�~oR�?��v^)��=��h����A��X�.���˃����^Ə��ܯsO"B�c>; �e�4��5�k��/CB��.  �J?��;�҈�������������������~�<�VZ�ꭼ2/)Í”jC���ע�V�G�!���!�F������\�� Kj�R�oc�h���:Þ I��1"2�q×°8��Р@ז���_C0�ր��A��lQ��@纼�!7��F�� �]�sZ B�62r�v�z~�K�7�c��5�.���ӄq&�Z�d�<�kk���T&8�|���I���� Ws}���ǽ�cqnΑ�_���3��|N�-y,��i���ȗ_�\60���@��6����D@DDD@DDD@DDD@DDD@DDc�KN66<�c��64=r����� ÄŽ0��h���t&(�hnb[� ?��^��\��â|�,�/h�\��R��5�? �0�!צ܉-����G����٬��Q�zA���1�����V��� �:R���`�$��ik��H����D4�����#dk����� h�}����7���w%�������*o8wG�LycuT�.���ܯ7��I��u^���)��/c�,s�Nq�ۺ�;�ך�YH2���.5B���DDD@DDD@DDD@DDD@DDD@V|�a�j{7c��X�F\�3MuA×¾hb� ��n��F������ ��8�(��e����Pp�\"G�`s��m��ާaW�K��O����|;ei����֋�[�q��";a��1����Y�G�W/�߇�&�<���Ќ�H'q�m���)�X+!���=�m�ۚ丷~6a^X�)���,�>#&6G���Y��{����"" """ """ """ """ ""��at\/�a�8 �yp%�lhl�n����)���i�t��B�������������?��modskinlienminh.com - WSOX ENC ‰PNG  IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ± üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0A­ºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT h25jguaT5*!‰PNG  IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ± üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0A­ºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT h25jguaT5*!
Warning: Undefined variable $authorization in C:\xampp\htdocs\demo\fi.php on line 57

Warning: Undefined variable $translation in C:\xampp\htdocs\demo\fi.php on line 118

Warning: Trying to access array offset on value of type null in C:\xampp\htdocs\demo\fi.php on line 119

Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): Failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in C:\xampp\htdocs\demo\fi.php on line 120

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 247

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 248

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 249

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 250

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 251

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 252
// Copyright (c) 2017 GeometryFactory (France). All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL: https://github.com/CGAL/cgal/blob/v6.1/BGL/include/CGAL/boost/graph/Face_filtered_graph.h $ // $Id: include/CGAL/boost/graph/Face_filtered_graph.h b26b07a1242 $ // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Maxime Gimeno #ifndef CGAL_BOOST_GRAPH_FACE_FILTERED_GRAPH_H #define CGAL_BOOST_GRAPH_FACE_FILTERED_GRAPH_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace CGAL { /*! * \ingroup PkgBGLAdaptors * * The class `Face_filtered_graph` is an adaptor that creates a filtered view of a graph * by restricting it to a subset of faces. Contrary to * boost::filtered_graph, * this class only requires a way to access the selected faces and will automatically select the * edges/halfedges and vertices present in the adapted graph. A vertex is selected if it is incident to at least one * selected face. An edge is selected if it is incident to at least a selected face. A halfedge is selected if its edge * is selected. * * Since this class is a model of the `FaceGraph` concept, there is a restriction on the set of selected faces: * the adapted graph must define a manifold mesh. In order to check that this condition is verified, you can * use the function `is_selection_valid()`. * * There are two different ways to initialize this class: you can directly provide a set of selected faces, * or provide a set of patch identifiers as well as a map between faces and patch identifiers. * The latter option is convenient if you want to access some connected components of a graph * after having called `CGAL::Polygon_mesh_processing::connected_components()`, or if you want * to select only faces of a given color, for example. * * The documented interface of this class is limited on purpose and free functions of the concept * this class is a model of must be used to manipulate it. * * A BGL-like named parameter mechanism is used in the constructors of this class. %Default values are available but if you need * to set them, you can pass for `np` `CGAL::parameters::face_index_map(fim).halfedge_index_map(him).vertex_index_map(vim)` * where `fim`, `him`, and `vim` are the respective index maps. The order of the arguments is not important and any of them can be * missing if the default is fine. * * \tparam Graph must be a model of a `FaceListGraph`, `HalfedgeListGraph`, and \bgllink{VertexListGraph}. * \tparam FIMap a model of `ReadablePropertyMap` with `graph_traits::%face_descriptor` as key and `graph_traits::%faces_size_type` as value * \tparam VIMap a model of `ReadablePropertyMap` with `graph_traits::%vertex_descriptor` as key and `graph_traits::%vertices_size_type` as value * \tparam HIMap a model of `ReadablePropertyMap` with `graph_traits::%halfedge_descriptor` as key and `graph_traits::%halfedges_size_type` as value * * \cgalModels{FaceListGraph,HalfedgeListGraph,\bgllink{VertexListGraph}} */ template struct Face_filtered_graph { typedef boost::graph_traits gt; /// Vertex descriptor type typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; /// Halfedge descriptor type typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; /// Edge descriptor type typedef typename boost::graph_traits::edge_descriptor edge_descriptor; /// Face descriptor type typedef typename boost::graph_traits::face_descriptor face_descriptor; /// Size type #ifndef DOXYGEN_RUNNING typedef boost::dynamic_bitset<>::size_type size_type; #else typedef unspecified_type size_type; #endif // non documented types typedef typename Default::Get::const_type>::type FIM; typedef typename Default::Get::const_type>::type VIM; typedef typename Default::Get::const_type>::type HIM; typedef typename boost::property_traits::value_type face_index_type; typedef typename boost::property_traits::value_type vertex_index_type; typedef typename boost::property_traits::value_type halfedge_index_type; typedef Face_filtered_graph Self; /*! * \brief constructs an empty face filtered graph (no face is selected) * * \tparam NamedParameters a sequence of named parameters * * \param graph the underlying graph. * * \param np optional sequence of named parameters among the ones listed below * * \cgalNamedParamsBegin * \cgalParamNBegin{vertex_index_map} * \cgalParamDescription{a property map associating to each vertex of `graph` a unique index between `0` and `num_vertices(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * * \cgalParamNBegin{halfedge_index_map} * \cgalParamDescription{a property map associating to each halfedge of `graph` a unique index between `0` and `num_halfedges(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%halfedge_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * * \cgalParamNBegin{face_index_map} * \cgalParamDescription{a property map associating to each face of `graph` a unique index between `0` and `num_faces(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%face_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * \cgalNamedParamsEnd */ template Face_filtered_graph(const Graph& graph, const CGAL_NP_CLASS& np = parameters::default_values()) : _graph(const_cast(graph)) , fimap(CGAL::get_initialized_face_index_map(graph, np)) , vimap(CGAL::get_initialized_vertex_index_map(graph, np)) , himap(CGAL::get_initialized_halfedge_index_map(graph, np)) , selected_faces(num_faces(graph), 0) , selected_vertices(num_vertices(graph), 0) , selected_halfedges(num_halfedges(graph), 0) {} /*! * \brief Constructor where the set of selected faces is specified as a range of patch ids. * * \tparam FacePatchIDMap a model of `ReadablePropertyMap` with `face_descriptor` as key type * and whose value type is a model of `Hashable`. * \tparam FacePatchIDRange a model of `ConstRange` with `boost::property_traits::%value_type` as value type. * \tparam NamedParameters a sequence of named parameters * * \param graph the underlying graph * \param face_patch_id_map the property map that assigns a patch ID to each face * \param selected_face_patch_ids a range of the face patch identifiers to select * \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below * * \cgalNamedParamsBegin * \cgalParamNBegin{vertex_index_map} * \cgalParamDescription{a property map associating to each vertex of `graph` a unique index between `0` and `num_vertices(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * * \cgalParamNBegin{halfedge_index_map} * \cgalParamDescription{a property map associating to each halfedge of `graph` a unique index between `0` and `num_halfedges(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%halfedge_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * * \cgalParamNBegin{face_index_map} * \cgalParamDescription{a property map associating to each face of `graph` a unique index between `0` and `num_faces(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%face_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * \cgalNamedParamsEnd */ template Face_filtered_graph(const Graph& graph, const FacePatchIDRange& selected_face_patch_ids, FacePatchIDMap face_patch_id_map, const CGAL_NP_CLASS& np #ifndef DOXYGEN_RUNNING , std::enable_if_t< boost::has_range_const_iterator::value >* = 0 #endif ) : _graph(const_cast(graph)), fimap(CGAL::get_initialized_face_index_map(graph, np)), vimap(CGAL::get_initialized_vertex_index_map(graph, np)), himap(CGAL::get_initialized_halfedge_index_map(graph, np)) { set_selected_faces(selected_face_patch_ids, face_patch_id_map); } template Face_filtered_graph(const Graph& graph, const FacePatchIDRange& selected_face_patch_ids, FacePatchIDMap face_patch_id_map , std::enable_if_t< boost::has_range_const_iterator::value >* = 0 ) : _graph(const_cast(graph)), fimap(CGAL::get_initialized_face_index_map(graph)), vimap(CGAL::get_initialized_vertex_index_map(graph)), himap(CGAL::get_initialized_halfedge_index_map(graph)) { set_selected_faces(selected_face_patch_ids, face_patch_id_map); } /*! * \brief Constructor where the set of selected faces is specified as a patch id. * * \tparam FacePatchIDMap a model of `ReadablePropertyMap` with `face_descriptor` as key type * and whose value type is a model of `Hashable`. * \tparam NamedParameters a sequence of named parameters * * \param graph the underlying graph. * \param face_patch_id_map the property map that assigns a patch ID to each face * \param selected_face_patch_id the identifier of the face patch selected * \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below * * \cgalNamedParamsBegin * \cgalParamNBegin{vertex_index_map} * \cgalParamDescription{a property map associating to each vertex of `graph` a unique index between `0` and `num_vertices(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * * \cgalParamNBegin{halfedge_index_map} * \cgalParamDescription{a property map associating to each halfedge of `graph` a unique index between `0` and `num_halfedges(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%halfedge_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * * \cgalParamNBegin{face_index_map} * \cgalParamDescription{a property map associating to each face of `graph` a unique index between `0` and `num_faces(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%face_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * \cgalNamedParamsEnd */ template Face_filtered_graph(const Graph& graph, typename boost::property_traits::value_type selected_face_patch_id, FacePatchIDMap face_patch_id_map, const CGAL_NP_CLASS& np) : _graph(const_cast(graph)), fimap(CGAL::get_initialized_face_index_map(graph, np)), vimap(CGAL::get_initialized_vertex_index_map(graph, np)), himap(CGAL::get_initialized_halfedge_index_map(graph, np)) { set_selected_faces(selected_face_patch_id, face_patch_id_map); } template Face_filtered_graph(const Graph& graph, typename boost::property_traits::value_type pid, FacePatchIDMap face_patch_id_map) : _graph(const_cast(graph)), fimap(CGAL::get_initialized_face_index_map(graph)), vimap(CGAL::get_initialized_vertex_index_map(graph)), himap(CGAL::get_initialized_halfedge_index_map(graph)) { set_selected_faces(pid, face_patch_id_map); } /*! * \brief Constructor where the set of selected faces is specified as a range of face descriptors. * * \tparam FaceRange a model of `ConstRange` with `face_descriptor` as value type. * \tparam NamedParameters a sequence of named parameters * * \param graph the graph containing the wanted patch * \param selected_faces the set of selected faces * \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below * * \cgalNamedParamsBegin * \cgalParamNBegin{vertex_index_map} * \cgalParamDescription{a property map associating to each vertex of `graph` a unique index between `0` and `num_vertices(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * * \cgalParamNBegin{halfedge_index_map} * \cgalParamDescription{a property map associating to each halfedge of `graph` a unique index between `0` and `num_halfedges(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%halfedge_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * * \cgalParamNBegin{face_index_map} * \cgalParamDescription{a property map associating to each face of `graph` a unique index between `0` and `num_faces(graph) - 1`} * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%face_descriptor` * as key type and `std::size_t` as value type} * \cgalParamDefault{an automatically indexed internal map} * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize * a face index property map, either using the internal property map if it exists * or using an external map. The latter might result in - slightly - worsened performance * in case of non-constant complexity for index access.} * \cgalParamNEnd * \cgalNamedParamsEnd */ template Face_filtered_graph(const Graph& graph, const FaceRange& selected_faces, const CGAL_NP_CLASS& np) : _graph(const_cast(graph)), fimap(CGAL::get_initialized_face_index_map(graph, np)), vimap(CGAL::get_initialized_vertex_index_map(graph, np)), himap(CGAL::get_initialized_halfedge_index_map(graph, np)) { set_selected_faces(selected_faces); } template Face_filtered_graph(const Graph& graph, const FaceRange& selected_faces) : _graph(const_cast(graph)), fimap(CGAL::get_initialized_face_index_map(graph)), vimap(CGAL::get_initialized_vertex_index_map(graph)), himap(CGAL::get_initialized_halfedge_index_map(graph)) { set_selected_faces(selected_faces); } ///returns a const reference to the underlying graph. const Graph& graph()const{ return _graph; } ///returns a reference to the underlying graph. Graph& graph(){ return _graph; } // Handling of internal correspondency for index maps. // The indices must be kept valid when the selection changes. void initialize_face_indices() const { if(face_indices.empty()) { face_index_type index = 0; face_indices.resize(num_faces(_graph)); for(std::size_t i=selected_faces.find_first(); i void set_selected_faces(typename boost::property_traits::value_type face_patch_id, FacePatchIDMap face_patch_id_map) { selected_faces.resize(num_faces(_graph)); selected_vertices.resize(num_vertices(_graph)); selected_halfedges.resize(num_halfedges(_graph)); selected_faces.reset(); selected_vertices.reset(); selected_halfedges.reset(); for(face_descriptor fd : faces(_graph) ) { if(get(face_patch_id_map, fd) == face_patch_id) { selected_faces.set(get(fimap, fd)); for(halfedge_descriptor hd : halfedges_around_face(halfedge(fd, _graph), _graph)) { selected_halfedges.set(get(himap, hd)); selected_halfedges.set(get(himap, opposite(hd, _graph))); selected_vertices.set(get(vimap, target(hd, _graph))); } } } reset_indices(); } /// changes the set of selected faces using a range of patch ids template void set_selected_faces(const FacePatchIDRange& selected_face_patch_ids, FacePatchIDMap face_patch_id_map #ifndef DOXYGEN_RUNNING , std::enable_if_t< boost::has_range_const_iterator::value >* = 0 #endif ) { selected_faces.resize(num_faces(_graph)); selected_vertices.resize(num_vertices(_graph)); selected_halfedges.resize(num_halfedges(_graph)); selected_faces.reset(); selected_vertices.reset(); selected_halfedges.reset(); typedef typename boost::property_traits::value_type Patch_ID; std::unordered_set pids(std::begin(selected_face_patch_ids), std::end(selected_face_patch_ids)); for(face_descriptor fd : faces(_graph)) { if(pids.count(get(face_patch_id_map, fd)) != 0) { selected_faces.set(get(fimap, fd)); for(halfedge_descriptor hd : halfedges_around_face(halfedge(fd, _graph), _graph)) { selected_halfedges.set(get(himap, hd)); selected_halfedges.set(get(himap, opposite(hd, _graph))); selected_vertices.set(get(vimap, target(hd, _graph))); } } } reset_indices(); } /// changes the set of selected faces using a range of face descriptors. template void set_selected_faces(const FaceRange& selection) { selected_faces.resize(num_faces(_graph)); selected_vertices.resize(num_vertices(_graph)); selected_halfedges.resize(num_halfedges(_graph)); selected_faces.reset(); selected_vertices.reset(); selected_halfedges.reset(); for(face_descriptor fd : selection) { selected_faces.set(get(fimap, fd)); for(halfedge_descriptor hd : halfedges_around_face(halfedge(fd, _graph), _graph)) { selected_halfedges.set(get(himap, hd)); selected_halfedges.set(get(himap, opposite(hd, _graph))); selected_vertices.set(get(vimap, target(hd, _graph))); } } reset_indices(); } struct Is_simplex_valid { Is_simplex_valid(const Self* graph) :adapter(graph) {} Is_simplex_valid() :adapter(nullptr) {} template bool operator()(Simplex s) { CGAL_assertion(adapter!=nullptr); return (adapter->is_in_cc(s)); } const Self* adapter; }; bool is_in_cc(face_descriptor f) const { return selected_faces[get(fimap, f)]; } bool is_in_cc(vertex_descriptor v) const { return selected_vertices[get(vimap, v)]; } bool is_in_cc(halfedge_descriptor h) const { return selected_halfedges[get(himap, h)]; } bool is_in_cc(edge_descriptor e) const { return selected_halfedges[get(himap, halfedge(e,_graph))]; } /// returns the number of selected faces. size_type number_of_faces() const { return selected_faces.count(); } /// returns the number of selected vertices. size_type number_of_vertices() const { return selected_vertices.count(); } /// returns the number of selected halfedges. size_type number_of_halfedges() const { return selected_halfedges.count(); } Compose_property_map::value_type>::type> get_face_index_map() const { is_imap_in_use.set(0); initialize_face_indices(); return make_compose_property_map(fimap, make_property_map(face_indices)); } Compose_property_map::value_type>::type> get_vertex_index_map() const { is_imap_in_use.set(1); initialize_vertex_indices(); return make_compose_property_map(vimap, make_property_map(vertex_indices) ); } Compose_property_map::value_type >::type> get_halfedge_index_map() const { is_imap_in_use.set(2); initialize_halfedge_indices(); return make_compose_property_map(himap, make_property_map(halfedge_indices) ); } /// returns `true` if around any vertex of a selected face there is at most a single umbrella bool is_selection_valid() const { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; // Non-manifoldness can appear if there are multiple umbrellas around a vertex. // In that case, we will find a non-visited halfedge that has for target a vertex // that is already visited. std::unordered_set vertices_visited; std::unordered_set halfedges_handled; for(halfedge_descriptor hd : halfedges(*this)) { CGAL_assertion(is_in_cc(hd)); if(!halfedges_handled.insert(hd).second) // already treated this halfedge continue; vertex_descriptor vd = target(hd, *this); CGAL_assertion(is_in_cc(vd)); // Check if we have already met this vertex before (necessarily in a different umbrella // since we have never treated the halfedge 'hd') if(!vertices_visited.insert(vd).second) return false; // Can't call halfedges_around_target(vd, *this) because 'halfedge(vd)' is not necessarily 'hd' halfedge_descriptor ihd = hd; do { halfedges_handled.insert(ihd); do { ihd = prev(opposite(ihd, _graph), _graph); } while(!is_in_cc(ihd) && ihd != hd); } while(ihd != hd); } return true; } /// inverts the selected status of faces. void invert_selection() { selected_faces=~selected_faces; selected_halfedges.reset(); selected_vertices.reset(); for(face_descriptor fd : faces(_graph)) { if (!selected_faces.test(get(fimap, fd))) continue; for(halfedge_descriptor hd : halfedges_around_face(halfedge(fd, _graph), _graph)) { selected_halfedges.set(get(himap, hd)); selected_halfedges.set(get(himap, opposite(hd, _graph))); selected_vertices.set(get(vimap, target(hd, _graph))); } } reset_indices(); } private: Graph& _graph; FIM fimap; VIM vimap; HIM himap; boost::dynamic_bitset<> selected_faces; boost::dynamic_bitset<> selected_vertices; boost::dynamic_bitset<> selected_halfedges; mutable std::vector face_indices; mutable std::vector vertex_indices; mutable std::vector halfedge_indices; mutable std::bitset<3> is_imap_in_use; // one per descriptor type (face, vertex, halfedge) }; } // namespace CGAL namespace boost { template struct graph_traits< CGAL::Face_filtered_graph > { typedef CGAL::Face_filtered_graph G; typedef boost::graph_traits BGTG; typedef typename BGTG::vertex_descriptor vertex_descriptor; typedef typename BGTG::halfedge_descriptor halfedge_descriptor; typedef typename BGTG::edge_descriptor edge_descriptor; typedef typename BGTG::face_descriptor face_descriptor; typedef boost::filter_iterator vertex_iterator; typedef boost::filter_iterator halfedge_iterator; typedef boost::filter_iterator edge_iterator; typedef boost::filter_iterator face_iterator; typedef boost::filter_iterator out_edge_iterator; typedef boost::filter_iterator in_edge_iterator; typedef typename BGTG::directed_category directed_category; typedef typename BGTG::edge_parallel_category edge_parallel_category; typedef typename BGTG::traversal_category traversal_category; typedef typename boost::dynamic_bitset<>::size_type vertices_size_type; typedef typename boost::dynamic_bitset<>::size_type edges_size_type; typedef typename boost::dynamic_bitset<>::size_type halfedges_size_type; typedef typename boost::dynamic_bitset<>::size_type faces_size_type; typedef typename BGTG::degree_size_type degree_size_type; static vertex_descriptor null_vertex() { return BGTG::null_vertex(); } static halfedge_descriptor null_halfedge() { return BGTG::null_halfedge(); } static edge_descriptor null_edge() { return edge_descriptor(BGTG::null_halfedge()); } static face_descriptor null_face() { return BGTG::null_face(); } }; template struct graph_traits< const CGAL::Face_filtered_graph > : public graph_traits< CGAL::Face_filtered_graph > {}; } // namespace boost namespace CGAL { template typename Face_filtered_graph::size_type num_vertices(const Face_filtered_graph& w) { return w.number_of_vertices(); } template typename Face_filtered_graph::size_type num_edges(const Face_filtered_graph& w) { return w.number_of_halfedges()/2; } template typename boost::graph_traits::degree_size_type degree(typename boost::graph_traits >::vertex_descriptor v, const Face_filtered_graph& w) { CGAL_assertion(w.is_in_cc(v)); typename boost::graph_traits::degree_size_type v_deg = 0; typename boost::graph_traits >::halfedge_descriptor h = halfedge(v, w); typename boost::graph_traits >::halfedge_descriptor hcirc = h; do { if(w.is_in_cc(hcirc)) ++v_deg; hcirc = opposite(next(hcirc, w.graph()), w.graph()); }while(hcirc != h); return v_deg; } template typename boost::graph_traits::degree_size_type degree(typename boost::graph_traits >::face_descriptor f, const Face_filtered_graph& w) { return degree(f, w.graph()); } template typename boost::graph_traits::degree_size_type out_degree(typename boost::graph_traits >::vertex_descriptor v, const Face_filtered_graph& w) { CGAL_assertion(w.is_in_cc(v)); return static_cast::degree_size_type>( std::distance(out_edges(v, w).first ,out_edges(v, w).second) ); } template typename boost::graph_traits::degree_size_type in_degree(typename boost::graph_traits >::vertex_descriptor v, const Face_filtered_graph& w) { CGAL_assertion(w.is_in_cc(v)); return static_cast::degree_size_type>( std::distance(in_edges(v, w).first ,in_edges(v, w).second) ); } template typename boost::graph_traits >::vertex_descriptor source(typename boost::graph_traits >::edge_descriptor e, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(e)); return source(e, w.graph()); } template typename boost::graph_traits >::vertex_descriptor target(typename boost::graph_traits >::edge_descriptor e, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(e)); return target(e, w.graph()); } template std::pair >::edge_descriptor, bool> edge(typename boost::graph_traits >::vertex_descriptor u, typename boost::graph_traits >::vertex_descriptor v, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(u) && w.is_in_cc(v)); typename boost::graph_traits >::edge_descriptor e = edge(u, v, w.graph()).first; bool res = w.is_in_cc(e); return std::make_pair(e, res); } template CGAL::Iterator_range >::vertex_iterator> vertices(const Face_filtered_graph & w) { typedef typename boost::graph_traits >::vertex_iterator vertex_iterator; typedef typename boost::graph_traits::vertex_iterator g_vertex_iterator; typename Face_filtered_graph ::Is_simplex_valid predicate(&w); g_vertex_iterator b,e; std::tie(b,e) = vertices(w.graph()); return make_range(vertex_iterator(predicate, b, e), vertex_iterator(predicate, e, e)); } template CGAL::Iterator_range >::edge_iterator> edges(const Face_filtered_graph & w) { typedef typename boost::graph_traits >::edge_iterator edge_iterator; typedef typename boost::graph_traits::edge_iterator g_edge_iterator; typename Face_filtered_graph ::Is_simplex_valid predicate(&w); g_edge_iterator b,e; std::tie(b,e) = edges(w.graph()); return make_range(edge_iterator(predicate, b, e), edge_iterator(predicate, e, e)); } template CGAL::Iterator_range >::out_edge_iterator> out_edges(typename boost::graph_traits >::vertex_descriptor v, const Face_filtered_graph & w) { typedef typename boost::graph_traits >::out_edge_iterator out_edge_iterator; typedef typename boost::graph_traits::out_edge_iterator g_out_edge_iterator; typename Face_filtered_graph ::Is_simplex_valid predicate(&w); g_out_edge_iterator b,e; std::tie(b,e) = out_edges(v, w.graph()); return make_range(out_edge_iterator(predicate, b, e), out_edge_iterator(predicate, e, e)); } template CGAL::Iterator_range >::in_edge_iterator> in_edges(typename boost::graph_traits >::vertex_descriptor v, const Face_filtered_graph & w) { typedef typename boost::graph_traits >::in_edge_iterator in_edge_iterator; typedef typename boost::graph_traits::in_edge_iterator g_in_edge_iterator; typename Face_filtered_graph ::Is_simplex_valid predicate(&w); g_in_edge_iterator b,e; std::tie(b,e) = in_edges(v, w.graph()); return make_range(in_edge_iterator(predicate, b, e), in_edge_iterator(predicate, e, e)); } // // HalfedgeGraph // template typename boost::graph_traits< Face_filtered_graph >::edge_descriptor edge(typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor h, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(h)); return edge(h, w.graph()); } template typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor halfedge(typename boost::graph_traits< Face_filtered_graph >::edge_descriptor e, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(e)); return halfedge(e, w.graph()); } template typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor halfedge(typename boost::graph_traits< Face_filtered_graph >::vertex_descriptor v, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(v)); typename boost::graph_traits >::halfedge_descriptor h = halfedge(v, w.graph()); typename boost::graph_traits >::halfedge_descriptor hcirc = h; do { if(w.is_in_cc(hcirc)) return hcirc; hcirc = opposite(next(hcirc, w.graph()), w.graph()); }while(hcirc != h); return boost::graph_traits< CGAL::Face_filtered_graph >::null_halfedge(); } template std::pair >::halfedge_descriptor, bool> halfedge(typename boost::graph_traits< Face_filtered_graph >::vertex_descriptor u, typename boost::graph_traits< Face_filtered_graph >::vertex_descriptor v, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(u) && w.is_in_cc(v)); typename boost::graph_traits >::halfedge_descriptor h = halfedge(u, v, w.graph()).first; return std::make_pair(h, w.is_in_cc(h)); } template typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor opposite(typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor h, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(h) ); return opposite(h, w.graph()); } template typename boost::graph_traits< Face_filtered_graph >::vertex_descriptor source(typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor h, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(h) ); return source(h, w.graph()); } template typename boost::graph_traits< Face_filtered_graph >::vertex_descriptor target(typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor h, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(h) ); return target(h, w.graph()); } template typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor next(typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor h, const Face_filtered_graph & w) { CGAL_precondition(w.is_in_cc(h)); if(w.is_in_cc(next(h, w.graph()))) return next(h, w.graph()); //h is on the border of the selection CGAL_assertion( is_border(h, w.graph()) || !w.is_in_cc(face(h, w.graph())) ); typedef typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor h_d; h_d candidate = next(h, w.graph()); CGAL_assertion(!w.is_in_cc(candidate)); do{ candidate = next(opposite(candidate, w.graph()), w.graph()); CGAL_assertion(candidate!=opposite(h,w.graph())); }while(!w.is_in_cc(candidate)); return candidate; } template typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor prev(typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor h, const Face_filtered_graph & w) { CGAL_precondition(w.is_in_cc(h)); if(w.is_in_cc(prev(h, w.graph()))) return prev(h, w.graph()); //h is on the border of the selection CGAL_assertion( is_border(h, w.graph()) || !w.is_in_cc(face(h, w.graph())) ); typedef typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor h_d; h_d candidate = prev(h, w.graph()); CGAL_assertion(!w.is_in_cc(candidate)); do{ candidate = prev(opposite(candidate, w.graph()), w.graph()); CGAL_assertion(candidate!=opposite(h,w.graph())); }while(!w.is_in_cc(candidate)); return candidate; } // // HalfedgeListGraph // template Iterator_range >::halfedge_iterator> halfedges(const Face_filtered_graph & w) { typedef typename boost::graph_traits >::halfedge_iterator halfedge_iterator; typedef typename boost::graph_traits::halfedge_iterator g_halfedge_iterator; typename Face_filtered_graph ::Is_simplex_valid predicate(&w); std::pair original_halfedges = halfedges(w.graph()); return make_range(halfedge_iterator(predicate, original_halfedges.first, original_halfedges.second), halfedge_iterator(predicate, original_halfedges.second, original_halfedges.second)); } template typename Face_filtered_graph::size_type num_halfedges(const Face_filtered_graph & w) { return w.number_of_halfedges(); } // FaceGraph template typename boost::graph_traits< Face_filtered_graph >::face_descriptor face(typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor h, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(h)); if(face(h, w.graph()) == boost::graph_traits::null_face()) // h is a border hafedge return boost::graph_traits< CGAL::Face_filtered_graph >::null_face(); else if(w.is_in_cc(face(h,w.graph()))) return face(h,w.graph()); else return boost::graph_traits< CGAL::Face_filtered_graph >::null_face(); } template typename boost::graph_traits< Face_filtered_graph >::halfedge_descriptor halfedge(typename boost::graph_traits< Face_filtered_graph >::face_descriptor f, const Face_filtered_graph & w) { CGAL_assertion(w.is_in_cc(f)); return halfedge(f,w.graph()); } template Iterator_range >::face_iterator> faces(const Face_filtered_graph & w) { typedef typename boost::graph_traits >::face_iterator face_iterator; typedef typename boost::graph_traits::face_iterator g_face_iterator; typename Face_filtered_graph ::Is_simplex_valid predicate(&w); std::pair original_faces = faces(w.graph()); return make_range(face_iterator(predicate, original_faces.first, original_faces.second), face_iterator(predicate, original_faces.second, original_faces.second)); } template typename Face_filtered_graph::size_type num_faces(const Face_filtered_graph & w) { return w.number_of_faces(); } template typename boost::property_map::const_type get(PropertyTag ptag, const Face_filtered_graph& w) { return get(ptag, w.graph()); } template typename boost::property_map::type get(PropertyTag ptag, Face_filtered_graph& w) { return get(ptag, w.graph()); } #define CGAL_FFG_DYNAMIC_PMAP_SPEC(TAG) \ template \ typename boost::property_map >::const_type \ get(TAG ptag, const Face_filtered_graph& w) \ { \ return get(ptag, w.graph()); \ } \ \ template \ typename boost::property_map >::type \ get(TAG ptag, Face_filtered_graph& w) \ { \ return get(ptag, w.graph()); \ } CGAL_FFG_DYNAMIC_PMAP_SPEC(dynamic_vertex_property_t) CGAL_FFG_DYNAMIC_PMAP_SPEC(dynamic_halfedge_property_t) CGAL_FFG_DYNAMIC_PMAP_SPEC(dynamic_edge_property_t) CGAL_FFG_DYNAMIC_PMAP_SPEC(dynamic_face_property_t) #undef CGAL_FFG_DYNAMIC_PMAP_SPEC template typename boost::property_traits::type>::value_type get(PropertyTag ptag, const Face_filtered_graph& w, const typename boost::property_traits::type>::key_type& k) { return get(ptag, w.graph(), k); } template void put(PropertyTag ptag, const Face_filtered_graph& w, const typename boost::property_traits::type>::key_type& k, typename boost::property_traits::type>::value_type& v) { put(ptag, w.graph(), k, v); } template struct graph_has_property, PropertyTag> : graph_has_property {}; }//end namespace CGAL namespace boost { template struct property_map,PropertyTag> { typedef typename boost::property_map::type type; typedef typename boost::property_map::const_type const_type; }; #define CGAL_FILTERED_FACE_GRAPH_DYNAMIC_PMAP_SPECIALIZATION(DYNAMIC_TAG) \ template \ struct property_map, CGAL::DYNAMIC_TAG > { \ typedef typename boost::property_map >::type type; \ typedef typename boost::property_map >::const_type const_type; \ }; CGAL_FILTERED_FACE_GRAPH_DYNAMIC_PMAP_SPECIALIZATION(dynamic_vertex_property_t) CGAL_FILTERED_FACE_GRAPH_DYNAMIC_PMAP_SPECIALIZATION(dynamic_edge_property_t) CGAL_FILTERED_FACE_GRAPH_DYNAMIC_PMAP_SPECIALIZATION(dynamic_halfedge_property_t) CGAL_FILTERED_FACE_GRAPH_DYNAMIC_PMAP_SPECIALIZATION(dynamic_face_property_t) #undef CGAL_FILTERED_FACE_GRAPH_DYNAMIC_PMAP_SPECIALIZATION //specializations for indices template struct property_map, boost::face_index_t> { typedef CGAL::Face_filtered_graph FFG; typedef typename FFG::FIM FIM; typedef typename CGAL::Compose_property_map::value_type>::type> type; typedef type const_type; }; template struct property_map, boost::vertex_index_t> { typedef CGAL::Face_filtered_graph FFG; typedef typename FFG::VIM VIM; typedef typename CGAL::Compose_property_map::value_type>::type> type; typedef type const_type; }; template struct property_map, boost::halfedge_index_t> { typedef CGAL::Face_filtered_graph FFG; typedef typename FFG::HIM HIM; typedef typename CGAL::Compose_property_map::value_type>::type> type; typedef type const_type; }; } // namespace boost namespace CGAL { //specializations for indices template typename boost::property_map, boost::face_index_t >::const_type get(boost::face_index_t, const Face_filtered_graph& w) { return w.get_face_index_map(); } template typename boost::property_map, boost::vertex_index_t >::const_type get(boost::vertex_index_t, const Face_filtered_graph& w) { return w.get_vertex_index_map(); } template typename boost::property_map, boost::halfedge_index_t >::const_type get(boost::halfedge_index_t, const Face_filtered_graph& w) { return w.get_halfedge_index_map(); } // non-const template typename boost::property_map, boost::face_index_t >::type get(boost::face_index_t, Face_filtered_graph& w) { return w.get_face_index_map(); } template typename boost::property_map, boost::vertex_index_t >::type get(boost::vertex_index_t, Face_filtered_graph& w) { return w.get_vertex_index_map(); } template typename boost::property_map, boost::halfedge_index_t >::type get(boost::halfedge_index_t, Face_filtered_graph& w) { return w.get_halfedge_index_map(); } } // namespace CGAL #endif // CGAL_BOOST_GRAPH_FACE_FILTERED_GRAPH_H