📄 property.hh
字号:
/*===========================================================================*\ * * * OpenMesh * * Copyright (C) 2001-2003 by Computer Graphics Group, RWTH Aachen * * www.openmesh.org * * * *---------------------------------------------------------------------------* * * * License * * * * This library is free software; you can redistribute it and/or modify it * * under the terms of the GNU Library General Public License as published * * by the Free Software Foundation, version 2. * * * * This library is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * *\*===========================================================================*/#ifndef OPENMESH_PROPERTY_HH#define OPENMESH_PROPERTY_HH//== INCLUDES =================================================================#include <OpenMesh/Core/System/config.hh>#include <OpenMesh/Core/System/omstream.hh>#include <OpenMesh/Core/Mesh/Kernels/Common/Handles.hh>#include <OpenMesh/Core/IO/StoreRestore.hh>#include <vector>#include <string>#include <algorithm>//== FORWARDDECLARATIONS ======================================================namespace OpenMesh { class BaseKernel;}//== NAMESPACES ===============================================================namespace OpenMesh {//== CLASS DEFINITION =========================================================/** \class BaseProperty Property.hh <OpenMesh/Core/Utils/PropertyT.hh> Abstract class defining the basic interface of a dynamic property.**/class BaseProperty{public: /// Indicates an error when a size is returned by a member. static const size_t UnknownSize = size_t(-1);public: /// \brief Default constructor. /// /// In %OpenMesh all mesh data is stored in so-called properties. /// We distinuish between standard properties, which can be defined at /// compile time using the Attributes in the traits definition and /// at runtime using the request property functions defined in one of /// the kernels. /// /// If the property should be stored along with the default properties /// in the OM-format one must name the property and enable the persistant /// flag with set_persistent(). /// /// \param _name Optional textual name for the property. /// BaseProperty(const std::string& _name = "<unknown>") : name_(_name), persistent_(false) {} /// \brief Copy constructor BaseProperty(const BaseProperty & _rhs) : name_( _rhs.name_ ), persistent_( _rhs.persistent_ ) {} /// Destructor. virtual ~BaseProperty() {}public: // synchronized array interface /// 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 free_mem() = 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 BaseProperty* clone () const = 0;public: // named property interface /// Return the name of the property const std::string& name() const { return name_; } virtual void stats(std::ostream& _ostr) const;public: // I/O support /// Returns true if the persistent flag is enabled else false. bool persistent(void) const { return persistent_; } /// Enable or disable persistency. Self must be a named property to enable /// persistency. virtual void set_persistent( bool _yn ) = 0; /// Number of elements in property virtual size_t n_elements() const = 0; /// Size of one element in bytes or UnknownSize if not known. virtual size_t element_size() const = 0; /// Return size of property in bytes virtual size_t size_of() const { return size_of( n_elements() ); } /// Estimated size of property if it has _n_elem elements. /// The member returns UnknownSize if the size cannot be estimated. virtual size_t size_of(size_t _n_elem) const { return (element_size()!=UnknownSize) ? (_n_elem*element_size()) : UnknownSize; } /// Store self as one binary block virtual size_t store( std::ostream& _ostr, bool _swap ) const = 0; /** Restore self from a binary block. Uses reserve() to set the size of self before restoring. **/ virtual size_t restore( std::istream& _istr, bool _swap ) = 0;protected: // To be used in a derived class, when overloading set_persistent() template < typename T > void check_and_set_persistent( bool _yn ) { if ( _yn && !IO::is_streamable<T>() ) omerr() << "Warning! Type of property value is not binary storable!\n"; persistent_ = IO::is_streamable<T>() && _yn; }private: std::string name_; bool persistent_;};//-----------------------------------------------------------------------------/** \class PropertyT Property.hh <OpenMesh/Core/Utils/PropertyT.hh> * * \brief Default property class for any type T. * * The default property class for any type T. * * The property supports persistency if T is a "fundamental" type: * - integer fundamental types except bool: * char, short, int, long, long long (__int64 for MS VC++) and * their unsigned companions. * - float fundamentals except <tt>long double</tt>: * float, double * - %OpenMesh vector types * * Persistency of non-fundamental types is supported if and only if a * specialization of struct IO::binary<> exists for the wanted type. */template <class T>class PropertyT : public BaseProperty{public: typedef T Value; typedef std::vector<T> vector_type; typedef T value_type; typedef typename vector_type::reference reference; typedef typename vector_type::const_reference const_reference;public: /// Default constructor PropertyT(const std::string& _name = "<unknown>") : BaseProperty(_name) {} /// Copy constructor PropertyT(const PropertyT & _rhs) : BaseProperty( _rhs ), data_( _rhs.data_ ) {}public: // inherited from BaseProperty virtual void reserve(size_t _n) { data_.reserve(_n); } virtual void resize(size_t _n) { data_.resize(_n); } virtual void push_back() { data_.push_back(T()); } virtual void free_mem() { vector_type(data_).swap(data_); } virtual void swap(size_t _i0, size_t _i1) { std::swap(data_[_i0], data_[_i1]); }public: virtual void set_persistent( bool _yn ) { check_and_set_persistent<T>( _yn ); } virtual size_t n_elements() const { return data_.size(); } virtual size_t element_size() const { return IO::size_of<T>(); }#ifndef DOXY_IGNORE_THIS struct plus { size_t operator () ( size_t _b, const T& _v ) { return _b + IO::size_of<T>(_v); } };#endif virtual size_t size_of(void) const { if (element_size() != IO::UnknownSize) return this->BaseProperty::size_of(n_elements()); return std::accumulate(data_.begin(), data_.end(), 0, plus()); } virtual size_t size_of(size_t _n_elem) const { return this->BaseProperty::size_of(_n_elem); } virtual size_t store( std::ostream& _ostr, bool _swap ) const { if ( IO::is_streamable<vector_type>() ) return IO::store(_ostr, data_, _swap ); size_t bytes = 0; for (size_t i=0; i<n_elements(); ++i) bytes += IO::store( _ostr, data_[i], _swap ); return bytes; } virtual size_t restore( std::istream& _istr, bool _swap ) { if ( IO::is_streamable<vector_type>() ) return IO::restore(_istr, data_, _swap ); size_t bytes = 0; for (size_t i=0; i<n_elements(); ++i) bytes += IO::restore( _istr, data_[i], _swap ); return bytes; }public: // data access interface /// 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) { assert( 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 { assert( size_t(_idx) < data_.size()); return data_[_idx]; } /// Make a copy of self. PropertyT<T>* clone() const { PropertyT<T>* p = new PropertyT<T>( *this ); return p; }private: vector_type data_;};//-----------------------------------------------------------------------------/** \class PropertyT<bool> Property.hh <OpenMesh/Core/Utils/PropertyT.hh> Property specialization for bool type. The data will be stored as a bitset. */template <>class PropertyT<bool> : public BaseProperty{public: typedef std::vector<bool> vector_type; typedef bool value_type; typedef vector_type::reference reference; typedef vector_type::const_reference const_reference;public: PropertyT(const std::string& _name = "<unknown>") : BaseProperty(_name) { } PropertyT(const PropertyT & _rhs) : BaseProperty( _rhs ), data_( _rhs.data_ ) {}public: // inherited from BaseProperty virtual void reserve(size_t _n) { data_.reserve(_n); } virtual void resize(size_t _n) { data_.resize(_n); } virtual void push_back() { data_.push_back(bool()); } virtual void free_mem() { vector_type(data_).swap(data_); } virtual void swap(size_t _i0, size_t _i1) { bool t(data_[_i0]); data_[_i0]=data_[_i1]; data_[_i1]=t; }public: virtual void set_persistent( bool _yn ) { check_and_set_persistent<bool>( _yn ); } virtual size_t n_elements() const { return data_.size(); } virtual size_t element_size() const { return UnknownSize; } virtual size_t size_of() const { return size_of( n_elements() ); } virtual size_t size_of(size_t _n_elem) const { return _n_elem / 8 + ((_n_elem % 8)!=0); } size_t store( std::ostream& _ostr, bool _swap ) const { size_t bytes = 0; size_t N = data_.size() / 8; size_t R = data_.size() % 8; size_t idx; // element index size_t bidx; unsigned char bits; // bitset for (bidx=idx=0; idx < N; ++idx, bidx+=8) { bits = !!data_[bidx] | (!!data_[bidx+1] << 1) | (!!data_[bidx+2] << 2) | (!!data_[bidx+3] << 3) | (!!data_[bidx+4] << 4) | (!!data_[bidx+5] << 5) | (!!data_[bidx+6] << 6) | (!!data_[bidx+7] << 7); _ostr << bits; } bytes = N; if (R) { bits = 0; for (idx=0; idx < R; ++idx) bits |= !!data_[bidx+idx] << idx; _ostr << bits; ++bytes; } std::cout << std::endl; assert( bytes == size_of() ); return bytes; } size_t restore( std::istream& _istr, bool _swap ) { size_t bytes = 0; size_t N = data_.size() / 8; size_t R = data_.size() % 8; size_t idx; // element index size_t bidx; // unsigned char bits; // bitset for (bidx=idx=0; idx < N; ++idx, bidx+=8) { _istr >> bits; data_[bidx+0] = !!(bits & 0x01); data_[bidx+1] = !!(bits & 0x02); data_[bidx+2] = !!(bits & 0x04); data_[bidx+3] = !!(bits & 0x08); data_[bidx+4] = !!(bits & 0x10); data_[bidx+5] = !!(bits & 0x20); data_[bidx+6] = !!(bits & 0x40); data_[bidx+7] = !!(bits & 0x80); } bytes = N; if (R) { _istr >> bits; for (idx=0; idx < R; ++idx) data_[bidx+idx] = !!(bits & (1<<idx)); ++bytes; } std::cout << std::endl; return bytes; }public: /// Access the i'th element. No range check is performed!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -