/* ========================================================================= * * * * OpenMesh * * Copyright (c) 2001-2015, RWTH-Aachen University * * Department of Computer Graphics and Multimedia * * All rights reserved. * * www.openmesh.org * * * *---------------------------------------------------------------------------* * This file is part of OpenMesh. * *---------------------------------------------------------------------------* * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * * * 1. Redistributions of source code must retain the above copyright notice, * * this list of conditions and the following disclaimer. * * * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * * * 3. Neither the name of the copyright holder nor the names of its * * contributors may be used to endorse or promote products derived from * * this software without specific prior written permission. * * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER * * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * * ========================================================================= */ //#ifndef OPENMESH_PROPERTY_HH //#define OPENMESH_PROPERTY_HH #pragma once //== INCLUDES ================================================================= #include #include #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 explicit PropertyT( const std::string& _name = "", const std::string& _internal_type_name = "") : BaseProperty(_name, _internal_type_name) {} /// Copy constructor PropertyT(const PropertyT & _rhs) : BaseProperty( _rhs ), data_( _rhs.data_ ) {} public: // inherited from BaseProperty virtual void reserve(size_t _n) override { data_.reserve(_n); } virtual void resize(size_t _n) override { data_.resize(_n); } virtual void clear() override { data_.clear(); vector_type().swap(data_); } virtual void push_back() override { data_.push_back(T()); } virtual void swap(size_t _i0, size_t _i1) override { std::swap(data_[_i0], data_[_i1]); } virtual void copy(size_t _i0, size_t _i1) override { data_[_i1] = data_[_i0]; } public: virtual void set_persistent( bool _yn ) override { check_and_set_persistent( _yn ); } virtual size_t n_elements() const override { return data_.size(); } virtual size_t element_size() const override { 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 override { if (element_size() != IO::UnknownSize) return this->BaseProperty::size_of(n_elements()); return std::accumulate(data_.begin(), data_.end(), size_t(0), plus()); } virtual size_t size_of(size_t _n_elem) const override { return this->BaseProperty::size_of(_n_elem); } virtual size_t store( std::ostream& _ostr, bool _swap ) const override { if (IO::is_streamable() && element_size() != IO::UnknownSize) return IO::store(_ostr, data_, _swap, false); //does not need to store its length size_t bytes = 0; for (size_t i=0; i() && element_size() != IO::UnknownSize ) return IO::restore(_istr, data_, _swap, false); //does not need to restore its length size_t bytes = 0; for (size_t i=0; i* clone() const override { PropertyT* p = new PropertyT( *this ); return p; } std::string get_storage_name() const override { return OpenMesh::IO::binary::string_for_value_type(); } private: vector_type data_; }; //----------------------------------------------------------------------------- /** 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: explicit PropertyT(const std::string& _name = "", const std::string& _internal_type_name="" ) : BaseProperty(_name, _internal_type_name) { } public: // inherited from BaseProperty virtual void reserve(size_t _n) override { data_.reserve(_n); } virtual void resize(size_t _n) override { data_.resize(_n); } virtual void clear() override { data_.clear(); vector_type().swap(data_); } virtual void push_back() override { data_.push_back(bool()); } virtual void swap(size_t _i0, size_t _i1) override { bool t(data_[_i0]); data_[_i0]=data_[_i1]; data_[_i1]=t; } virtual void copy(size_t _i0, size_t _i1) override { data_[_i1] = data_[_i0]; } public: virtual void set_persistent( bool _yn ) override { check_and_set_persistent( _yn ); } virtual size_t n_elements() const override { return data_.size(); } virtual size_t element_size() const override { return UnknownSize; } virtual size_t size_of() const override { return size_of( n_elements() ); } virtual size_t size_of(size_t _n_elem) const override { return _n_elem / 8 + ((_n_elem % 8)!=0); } size_t store( std::ostream& _ostr, bool /* _swap */ ) const override { 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 = static_cast(data_[bidx]) | (static_cast(data_[bidx+1]) << 1) | (static_cast(data_[bidx+2]) << 2) | (static_cast(data_[bidx+3]) << 3) | (static_cast(data_[bidx+4]) << 4) | (static_cast(data_[bidx+5]) << 5) | (static_cast(data_[bidx+6]) << 6) | (static_cast(data_[bidx+7]) << 7); _ostr << bits; } bytes = N; if (R) { bits = 0; for (idx=0; idx < R; ++idx) bits |= static_cast(data_[bidx+idx]) << idx; _ostr << bits; ++bytes; } assert( bytes == size_of() ); return bytes; } size_t restore( std::istream& _istr, bool /* _swap */ ) override { 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) != 0; data_[bidx+1] = (bits & 0x02) != 0; data_[bidx+2] = (bits & 0x04) != 0; data_[bidx+3] = (bits & 0x08) != 0; data_[bidx+4] = (bits & 0x10) != 0; data_[bidx+5] = (bits & 0x20) != 0; data_[bidx+6] = (bits & 0x40) != 0; data_[bidx+7] = (bits & 0x80) != 0; } bytes = N; if (R) { _istr >> bits; for (idx=0; idx < R; ++idx) data_[bidx+idx] = (bits & (1<* clone() const override { PropertyT* p = new PropertyT( *this ); return p; } std::string get_storage_name() const override { return OpenMesh::IO::binary::string_for_value_type(); } private: vector_type data_; }; //----------------------------------------------------------------------------- /** 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: explicit PropertyT(const std::string& _name = "", const std::string& _internal_type_name="" ) : BaseProperty(_name, _internal_type_name) { } public: // inherited from BaseProperty virtual void reserve(size_t _n) override { data_.reserve(_n); } virtual void resize(size_t _n) override { data_.resize(_n); } virtual void clear() override { data_.clear(); vector_type().swap(data_); } virtual void push_back() override { data_.push_back(std::string()); } virtual void swap(size_t _i0, size_t _i1) override { std::swap(data_[_i0], data_[_i1]); } virtual void copy(size_t _i0, size_t _i1) override { data_[_i1] = data_[_i0]; } public: virtual void set_persistent( bool _yn ) override { check_and_set_persistent( _yn ); } virtual size_t n_elements() const override { return data_.size(); } virtual size_t element_size() const override { return UnknownSize; } virtual size_t size_of() const override { return IO::size_of( data_ ); } virtual size_t size_of(size_t /* _n_elem */) const override { 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 override { return IO::store( _ostr, data_, _swap ); } size_t restore( std::istream& _istr, bool _swap ) override { return IO::restore( _istr, data_, _swap ); } public: const value_type* data() const { if( data_.empty() ) return nullptr; 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 override { PropertyT* p = new PropertyT( *this ); return p; } std::string get_storage_name() const override { return OpenMesh::IO::binary::string_for_value_type(); } 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; typedef VertexHandle Handle; 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; typedef HalfedgeHandle Handle; 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; typedef EdgeHandle Handle; 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; typedef FaceHandle Handle; 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; typedef MeshHandle Handle; explicit MPropHandleT(int _idx=-1) : BasePropHandleT(_idx) {} explicit MPropHandleT(const BasePropHandleT& _b) : BasePropHandleT(_b) {} }; template struct PropHandle; template <> struct PropHandle { template using type = VPropHandleT; }; template <> struct PropHandle { template using type = HPropHandleT; }; template <> struct PropHandle { template using type = EPropHandleT; }; template <> struct PropHandle { template using type = FPropHandleT; }; template <> struct PropHandle { template using type = MPropHandleT; }; } // namespace OpenMesh //============================================================================= //#endif // OPENMESH_PROPERTY_HH defined //=============================================================================