// Copyright (c) 2010,2011 Tel-Aviv University (Israel). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Arrangement_on_surface_2/include/CGAL/Arr_vertex_index_map.h $ // $Id: Arr_vertex_index_map.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Ron Wein // Efi Fogel #ifndef CGAL_ARR_VERTEX_INDEX_MAP_H #define CGAL_ARR_VERTEX_INDEX_MAP_H #include #include /*! \file * Definition of the Arr_vertex_index_map class. */ #include #include #include #include namespace CGAL { /*! \class * An auxiliary class that automatically maintains a mapping of the * arrangement vertices to the indices 0, ..., (n -1), where n is the number * of vertices in the arrangement. */ template class Arr_vertex_index_map : public Arr_observer { public: typedef Arrangement_ Arrangement_2; typedef typename Arrangement_2::Vertex_handle Vertex_handle; // Boost property type definitions: typedef boost::readable_property_map_tag category; typedef unsigned int value_type; typedef value_type reference; typedef Vertex_handle key_type; private: typedef Arr_vertex_index_map Self; typedef Arr_observer Base; typedef Unique_hash_map Index_map; // Data members: unsigned int n_vertices; // The current number of vertices. Index_map index_map; // Mapping vertices to indices. std::vector rev_map; // Mapping indices to vertices. enum {MIN_REV_MAP_SIZE = 32}; public: /*! Default constructor. */ Arr_vertex_index_map () : Base (), n_vertices (0), rev_map (MIN_REV_MAP_SIZE) {} /*! Constructor with an associated arrangement. */ Arr_vertex_index_map (const Arrangement_2& arr) : Base (const_cast (arr)) { _init(); } /*! Copy constructor. */ Arr_vertex_index_map (const Self& other) : Base (const_cast (*(other.arrangement()))) { _init(); } /*! Assignment operator. */ Self& operator= (const Self& other) { if (this == &other) return (*this); this->detach(); this->attach (const_cast (*(other.arrangement()))); return (*this); } /*! * Get the index of a given vertex. * \param v A handle to the vertex. * \pre v is a valid vertex in the arrangement. */ unsigned int operator[] (Vertex_handle v) const { return index_map[v]; } /*! * Get the vertex given its index. * \param i The index of the vertex. * \pre i is less than the number of vertices in the graph. */ Vertex_handle vertex (const int i) const { CGAL_precondition (i < n_vertices); return rev_map[i]; } /// \name Notification functions, to keep the mapping up-to-date. //@{ /*! * Update the mapping after the arrangement has been assigned with another * arrangement. */ virtual void after_assign () { _init(); } /*! * Update the mapping after the arrangement is cleared. */ virtual void after_clear () { _init(); } /*! * Update the mapping after attaching to a new arrangement. */ virtual void after_attach () { _init(); } /*! * Update the mapping after detaching the arrangement. */ virtual void after_detach () { n_vertices = 0; index_map.clear(); } /*! * Update the mapping after the creation of a new vertex. * \param v A handle to the created vertex. */ virtual void after_create_vertex (Vertex_handle v) { // Update the number of vertices. n_vertices++; // If necessary, allocate memory for the reverse mapping. if (rev_map.size() < n_vertices) rev_map.resize (2 * n_vertices); // Update the mapping of the newly created vertex. index_map[v] = n_vertices - 1; rev_map[n_vertices - 1] = v; } /*! * Update the mapping after the creation of a new boundary vertex. * \param v A handle to the created vertex. */ virtual void after_create_boundary_vertex (Vertex_handle v) { // Update the number of vertices. n_vertices++; // If necessary, allocate memory for the reverse mapping. if (rev_map.size() < n_vertices) rev_map.resize (2 * n_vertices); // Update the mapping of the newly created vertex. index_map[v] = n_vertices - 1; rev_map[n_vertices - 1] = v; } /*! * Update the mapping before the removal of a vertex. * \param v A handle to the vertex to be removed. */ virtual void before_remove_vertex (Vertex_handle v) { // Update the number of vertices. n_vertices--; // Reduce memory consumption in case the number of vertices has // drastically decreased. if (2*n_vertices+1 < rev_map.size() && rev_map.size() / 2 >= MIN_REV_MAP_SIZE) { rev_map.resize (rev_map.size() / 2); } // Get the current vertex index, and assign this index to the vertex // currently indexed (n - 1). unsigned int index = index_map[v]; if (index == n_vertices) return; Vertex_handle last_v = rev_map[n_vertices]; index_map[last_v] = index; rev_map[index] = last_v; // Clear the reverse mapping for the last vertex. rev_map[n_vertices] = Vertex_handle(); } //@} private: /*! Initialize the map for the given arrangement. */ void _init () { // Get the number of vertices and allocate the reverse map accordingly. n_vertices = static_cast(this->arrangement()->number_of_vertices()); if (n_vertices < MIN_REV_MAP_SIZE) rev_map.resize (MIN_REV_MAP_SIZE); else rev_map.resize (n_vertices); // Clear the current mapping. index_map.clear(); // Create the initial mapping. typename Arrangement_2::Vertex_iterator vit; Vertex_handle vh; unsigned int index = 0; for (vit = this->arrangement()->vertices_begin(); vit != this->arrangement()->vertices_end(); ++vit, ++index) { // Map the current vertex to the current index. vh = vit; index_map[vh] = index; rev_map[index] = vh; } } }; /*! * Get the index property-map function. Provided so that boost is able to * access the Arr_vertex_index_map above. * \param index_map The index map. * \param v A vertex handle. * \return The vertex index. */ template unsigned int get (const CGAL::Arr_vertex_index_map& index_map, typename Arrangement::Vertex_handle v) { return index_map[v]; } } //namespace CGAL #include #endif