/*===========================================================================*\ * * * 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 Lesser General Public License as published * * by the Free Software Foundation, version 2.1. * * * * 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 * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser 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 #include #include #include #include #include //== NAMESPACES =============================================================== namespace OpenMesh { //== CLASS DEFINITION ========================================================= /** \class PropertyT Property.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 long double: * 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. */ // TODO: it might be possible to define Property using kind of a runtime info // structure holding the size of T. Then reserve, swap, resize, etc can be written // in pure malloc() style w/o virtual overhead. Template member function proved per // element access to the properties, asserting dynamic_casts in debug template class PropertyT : public BaseProperty { public: typedef T Value; typedef std::vector 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 = "") : 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 swap(size_t _i0, size_t _i1) { std::swap(data_[_i0], data_[_i1]); } public: virtual void set_persistent( bool _yn ) { check_and_set_persistent( _yn ); } virtual size_t n_elements() const { return data_.size(); } virtual size_t element_size() const { return IO::size_of(); } #ifndef DOXY_IGNORE_THIS struct plus { size_t operator () ( size_t _b, const T& _v ) { return _b + IO::size_of(_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() ) return IO::store(_ostr, data_, _swap ); size_t bytes = 0; for (size_t i=0; i() ) return IO::restore(_istr, data_, _swap ); size_t bytes = 0; for (size_t i=0; i* clone() const { PropertyT* p = new PropertyT( *this ); return p; } private: vector_type data_; }; //----------------------------------------------------------------------------- /** \class PropertyT Property.hh Property specialization for bool type. The data will be stored as a bitset. */ template <> class PropertyT : public BaseProperty { public: typedef std::vector vector_type; typedef bool value_type; typedef vector_type::reference reference; typedef vector_type::const_reference const_reference; public: PropertyT(const std::string& _name = "") : BaseProperty(_name) { } 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 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( _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<* clone() const { PropertyT* p = new PropertyT( *this ); return p; } private: vector_type data_; }; //----------------------------------------------------------------------------- /** \class PropertyT Property.hh Property specialization for std::string type. */ template <> class PropertyT : public BaseProperty { public: typedef std::string Value; typedef std::vector vector_type; typedef std::string value_type; typedef vector_type::reference reference; typedef vector_type::const_reference const_reference; public: PropertyT(const std::string& _name = "") : BaseProperty(_name) { } 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(std::string()); } 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( _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 IO::size_of( data_ ); } virtual size_t size_of(size_t /* _n_elem */) const { return UnknownSize; } /// Store self as one binary block. Max. length of a string is 65535 bytes. size_t store( std::ostream& _ostr, bool _swap ) const { return IO::store( _ostr, data_, _swap ); } size_t restore( std::istream& _istr, bool _swap ) { return IO::restore( _istr, data_, _swap ); } public: const value_type* data() const { if( data_.empty() ) return 0; return (value_type*) &data_[0]; } /// Access the i'th element. No range check is performed! reference operator[](int _idx) { assert( size_t(_idx) < data_.size()); return ((value_type*) &data_[0])[_idx]; } /// Const access the i'th element. No range check is performed! const_reference operator[](int _idx) const { assert( size_t(_idx) < data_.size()); return ((value_type*) &data_[0])[_idx]; } PropertyT* clone() const { PropertyT* p = new PropertyT( *this ); return p; } private: vector_type data_; }; /// Base property handle. template struct BasePropHandleT : public BaseHandle { typedef T Value; typedef std::vector vector_type; typedef T value_type; typedef typename vector_type::reference reference; typedef typename vector_type::const_reference const_reference; explicit BasePropHandleT(int _idx=-1) : BaseHandle(_idx) {} }; /** \ingroup mesh_property_handle_group * Handle representing a vertex property */ template struct VPropHandleT : public BasePropHandleT { typedef T Value; typedef T value_type; explicit VPropHandleT(int _idx=-1) : BasePropHandleT(_idx) {} explicit VPropHandleT(const BasePropHandleT& _b) : BasePropHandleT(_b) {} }; /** \ingroup mesh_property_handle_group * Handle representing a halfedge property */ template struct HPropHandleT : public BasePropHandleT { typedef T Value; typedef T value_type; explicit HPropHandleT(int _idx=-1) : BasePropHandleT(_idx) {} explicit HPropHandleT(const BasePropHandleT& _b) : BasePropHandleT(_b) {} }; /** \ingroup mesh_property_handle_group * Handle representing an edge property */ template struct EPropHandleT : public BasePropHandleT { typedef T Value; typedef T value_type; explicit EPropHandleT(int _idx=-1) : BasePropHandleT(_idx) {} explicit EPropHandleT(const BasePropHandleT& _b) : BasePropHandleT(_b) {} }; /** \ingroup mesh_property_handle_group * Handle representing a face property */ template struct FPropHandleT : public BasePropHandleT { typedef T Value; typedef T value_type; explicit FPropHandleT(int _idx=-1) : BasePropHandleT(_idx) {} explicit FPropHandleT(const BasePropHandleT& _b) : BasePropHandleT(_b) {} }; /** \ingroup mesh_property_handle_group * Handle representing a mesh property */ template struct MPropHandleT : public BasePropHandleT { typedef T Value; typedef T value_type; explicit MPropHandleT(int _idx=-1) : BasePropHandleT(_idx) {} explicit MPropHandleT(const BasePropHandleT& _b) : BasePropHandleT(_b) {} }; } // namespace OpenMesh //============================================================================= #endif // OPENMESH_PROPERTY_HH defined //=============================================================================