From a32ecad18c49e0705d34d291dd27e20b89c1926b Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 30 Sep 2014 15:04:59 +0200 Subject: [PATCH] Make Property_map a nested class again. --- .../doc/Surface_mesh/PackageDescription.txt | 1 - .../examples/Surface_mesh/sm_memory.cpp | 2 +- .../examples/Surface_mesh/sm_properties.cpp | 4 +- .../include/CGAL/Surface_mesh/Properties.h | 4 +- .../include/CGAL/Surface_mesh/Surface_mesh.h | 463 +++++++++++++++++- 5 files changed, 468 insertions(+), 6 deletions(-) diff --git a/Surface_mesh/doc/Surface_mesh/PackageDescription.txt b/Surface_mesh/doc/Surface_mesh/PackageDescription.txt index 61027e0f6fc..5b6f978c3b5 100644 --- a/Surface_mesh/doc/Surface_mesh/PackageDescription.txt +++ b/Surface_mesh/doc/Surface_mesh/PackageDescription.txt @@ -30,7 +30,6 @@ and faces is much simpler and can be used at runtime and not at compile time.} ## Classes ## - `CGAL::Surface_mesh

` -- `CGAL::Property_map` */ diff --git a/Surface_mesh/examples/Surface_mesh/sm_memory.cpp b/Surface_mesh/examples/Surface_mesh/sm_memory.cpp index a29c2ca005c..5bbb1108352 100644 --- a/Surface_mesh/examples/Surface_mesh/sm_memory.cpp +++ b/Surface_mesh/examples/Surface_mesh/sm_memory.cpp @@ -33,7 +33,7 @@ int main() } // The status of being used or removed is stored in a property map - CGAL::Property_map removed + Mesh::Property_map removed = m.get_property_map("v:removed"); diff --git a/Surface_mesh/examples/Surface_mesh/sm_properties.cpp b/Surface_mesh/examples/Surface_mesh/sm_properties.cpp index c1907d2b44a..a327587e6f2 100644 --- a/Surface_mesh/examples/Surface_mesh/sm_properties.cpp +++ b/Surface_mesh/examples/Surface_mesh/sm_properties.cpp @@ -27,7 +27,7 @@ int main() m.add_property_map("f:my_property", false); // give each vertex a name, the default is empty - CGAL::Property_map name + Mesh::Property_map name = m.add_property_map("v:name", "noname"); // add some names to the vertices @@ -35,7 +35,7 @@ int main() name[v2] = "world"; // retrieve the point property - CGAL::Property_map location = m.points(); + Mesh::Property_map location = m.points(); BOOST_FOREACH( vertex_descriptor vd, m.vertices()) { std::cout << name[vd] << " @ " << location[vd] << std::endl; } diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Properties.h b/Surface_mesh/include/CGAL/Surface_mesh/Properties.h index 470a4fdd180..4c86dff317e 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Properties.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Properties.h @@ -31,6 +31,8 @@ namespace CGAL { +#ifndef DOXYGEN_RUNNING + /// \addtogroup PkgSurface_mesh /// /// @{ @@ -470,7 +472,7 @@ private: ///@} - +#endif // DOXYGEN_RUNNING } // CGAL //============================================================================= diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index d1dcb4051a9..5025ca6f631 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include #include @@ -33,13 +36,14 @@ #include #include #include +#include #include #include #include #include #include -#include +//#include #include #include @@ -65,6 +69,453 @@ class Surface_mesh template class Handle_iterator; public: + + + +/// \addtogroup PkgSurface_mesh +/// +/// @{ + +/// @cond CGAL_DOCUMENT_INTERNALS +class Base_property_array +{ +public: + + /// Default constructor + Base_property_array(const std::string& name) : name_(name) {} + + /// Destructor. + virtual ~Base_property_array() {} + + /// Reserve memory for n elements. + virtual void reserve(size_t n) = 0; + + /// Resize storage to hold n elements. + virtual void resize(size_t n) = 0; + + /// Free unused memory. + virtual void shrink_to_fit() = 0; + + /// Extend the number of elements by one. + virtual void push_back() = 0; + + /// Let two elements swap their storage place. + virtual void swap(size_t i0, size_t i1) = 0; + + /// Return a deep copy of self. + virtual Base_property_array* clone () const = 0; + + /// Return the type_info of the property + virtual const std::type_info& type() = 0; + + /// Return the name of the property + const std::string& name() const { return name_; } + + +protected: + + std::string name_; +}; + + /// @endcond + + +//== CLASS DEFINITION ========================================================= + +/// @cond CGAL_DOCUMENT_INTERNALS + +template +class Property_array : public Base_property_array +{ +public: + + typedef T value_type; + typedef std::vector vector_type; + typedef typename vector_type::reference reference; + typedef typename vector_type::const_reference const_reference; + + Property_array(const std::string& name, T t=T()) : Base_property_array(name), value_(t) {} + +public: // virtual interface of Base_property_array + + virtual void reserve(size_t n) + { + data_.reserve(n); + } + + virtual void resize(size_t n) + { + data_.resize(n, value_); + } + + virtual void push_back() + { + data_.push_back(value_); + } + + virtual void shrink_to_fit() + { + vector_type(data_).swap(data_); + } + + virtual void swap(size_t i0, size_t i1) + { + T d(data_[i0]); + data_[i0]=data_[i1]; + data_[i1]=d; + } + + virtual Base_property_array* clone() const + { + Property_array* p = new Property_array(name_, value_); + p->data_ = data_; + return p; + } + + virtual const std::type_info& type() { return typeid(T); } + + +public: + + /// Get pointer to array (does not work for T==bool) + const T* data() const + { + return &data_[0]; + } + + /// Access the i'th element. No range check is performed! + reference operator[](int _idx) + { + CGAL_assertion( size_t(_idx) < data_.size() ); + return data_[_idx]; + } + + /// Const access to the i'th element. No range check is performed! + const_reference operator[](int _idx) const + { + CGAL_assertion( size_t(_idx) < data_.size()); + return data_[_idx]; + } + + + +private: + vector_type data_; + value_type value_; +}; + + + +// specialization for bool properties +template <> +inline const bool* +Property_array::data() const +{ + CGAL_assertion(false); + return NULL; +} + + /// @endcond + +//== CLASS DEFINITION ========================================================= + +/// @cond CGAL_DOCUMENT_INTERNALS + +template +class Property_container; +/// @endcond + + + + +//== CLASS DEFINITION ========================================================= +/// @cond CGAL_DOCUMENT_INTERNALS + +template +class Property_map; + +template +class Property_container +{ +public: + + // default constructor + Property_container() : size_(0) {} + + // destructor (deletes all property arrays) + virtual ~Property_container() { clear(); } + + // copy constructor: performs deep copy of property arrays + Property_container(const Property_container& _rhs) { operator=(_rhs); } + + // assignment: performs deep copy of property arrays + Property_container& operator=(const Property_container& _rhs) + { + if (this != &_rhs) + { + clear(); + parrays_.resize(_rhs.n_properties()); + size_ = _rhs.size(); + for (unsigned int i=0; iclone(); + } + return *this; + } + + // returns the current size of the property arrays + size_t size() const { return size_; } + + // returns the number of property arrays + size_t n_properties() const { return parrays_.size(); } + + // returns a vector of all property names + std::vector properties() const + { + std::vector names; + for (unsigned int i=0; iname()); + return names; + } + + // add a property with name \c name and default value \c t + template Property_map add(const std::string& name, const T t=T()) + { + // if a property with this name already exists, return an invalid property + for (unsigned int i=0; iname() == name) + { + return Property_map(); + } + } + + // otherwise add the property + Property_array* p = new Property_array(name, t); + p->resize(size_); + parrays_.push_back(p); + return Property_map(p); + } + + + // get a property by its name. returns invalid property if it does not exist. + template Property_map get(const std::string& name) const + { + for (unsigned int i=0; iname() == name) + return Property_map(dynamic_cast*>(parrays_[i])); + return Property_map(); + } + + + // returns a property if it exists, otherwise it creates it first. + template Property_map get_or_add(const std::string& name, const T t=T()) + { + Property_map p = get(name); + if (!p) p = add(name, t); + return p; + } + + + // get the type of property by its name. returns typeid(void) if it does not exist. + const std::type_info& get_type(const std::string& name) + { + for (unsigned int i=0; iname() == name) + return parrays_[i]->type(); + return typeid(void); + } + + + // delete a property + template void remove(Property_map& h) + { + std::vector::iterator it=parrays_.begin(), end=parrays_.end(); + for (; it!=end; ++it) + { + if (*it == h.parray_) + { + delete *it; + parrays_.erase(it); + h.reset(); + break; + } + } + } + + + // delete all properties + void clear() + { + for (unsigned int i=0; ireserve(n); + } + + // resize all arrays to size n + void resize(size_t n) + { + for (unsigned int i=0; iresize(n); + size_ = n; + } + + // free unused space in all arrays + void shrink_to_fit() const + { + for (unsigned int i=0; ishrink_to_fit(); + } + + // add a new element to each vector + void push_back() + { + for (unsigned int i=0; ipush_back(); + ++size_; + } + + // swap elements i0 and i1 in all arrays + void swap(size_t i0, size_t i1) const + { + for (unsigned int i=0; iswap(i0, i1); + } + + +private: + std::vector parrays_; + size_t size_; +}; + + /// @endcond + +#ifndef DOXYGEN_RUNNING +/// +/// +/// `Property_map` enables to attach properties to the simplices of a +/// surface mesh. +/// +/// @tparam Key The key type of the property map. It must be a model of `Index`. +/// @tparam Value The value type of the property. +/// +/// \cgalModels `LvaluePropertyMap` +/// +template +class Property_map +/// @cond CGAL_DOCUMENT_INTERNALS + : public boost::put_get_helper< + typename Property_array::reference, + Property_map< I, T > > +/// @endcond +{ + typedef void (Property_map::*bool_type)() const; + void this_type_does_not_support_comparisons() const {} +public: + typedef I key_type; + typedef T value_type; + typedef boost::lvalue_property_map_tag category; + +#ifndef DOXYGEN_RUNNING + + typedef typename Property_array::reference reference; + + typedef typename Property_array::const_reference const_reference; +#else + /// A reference to the value type of the property. + typedef unspecified_type reference; + + /// A const reference to the value type of the property. + typedef unspecified_type const_reference; +#endif + +#ifndef DOXYGEN_RUNNING + friend class Property_container; + + template friend class Surface_mesh; +#endif + +public: +/// @cond CGAL_DOCUMENT_INTERNALS + Property_map(Property_array* p=NULL) : parray_(p) {} + + void reset() + { + parray_ = NULL; + } + /// @endcond + +public: + /// \name Accessing Properties + //@{ +#ifdef DOXYGEN_RUNNING + /// Conversion to a Boolean. It is \c true when the property map + /// can be used, and \c false otherwise. + operator bool () const; +#else + operator bool_type() const { + return parray_ != NULL ? + &Property_map::this_type_does_not_support_comparisons : 0; + } +#endif + /// Access the property associated with the key \c i. + reference operator[](const I& i) + { + CGAL_assertion(parray_ != NULL); + return (*parray_)[i.idx()]; + } + + /// Access the property associated with the key \c i. + reference operator[](const I& i) const + { + CGAL_assertion(parray_ != NULL); + return (*parray_)[i.idx()]; + } + + /// Allows access to the underlying storage of the property. This + /// is useful when the key associated with the properties is + /// unimportant and only the properties are of interest + /// (e.g. rendering). + /// + /// \returns a pointer to the underlying storage of the property. + const T* data() const + { + CGAL_assertion(parray_ != NULL); + return parray_->data(); + } + + //@} +private: + + Property_array& array() + { + CGAL_assertion(parray_ != NULL); + return *parray_; + } + + const Property_array& array() const + { + CGAL_assertion(parray_ != NULL); + return *parray_; + } + + Property_array* parray_; +}; + +#endif // DOXYGEN_RUNNING + +///@} + + + /// \name Basic Types /// ///@{ @@ -1425,6 +1876,16 @@ private: //--------------------------------------------------- property handling */ ///@{ + /// Model of `LValuePropertyMap` with `I` as key type and `T` as value type, where `I` + /// is either a vertex, halfedge, edge, or face index type. +#ifdef DOXYGEN_RUNNING + template + using Property_map = unspecified_type; + +#else + + +#endif /// adds a property map named `name` with value type `T` and default `t` /// for index type `I`. Returns an invalid property map if a property