diff --git a/src/OpenMesh/Core/Mesh/ArrayKernel.hh b/src/OpenMesh/Core/Mesh/ArrayKernel.hh index 5726252d..736d4a4b 100644 --- a/src/OpenMesh/Core/Mesh/ArrayKernel.hh +++ b/src/OpenMesh/Core/Mesh/ArrayKernel.hh @@ -571,6 +571,199 @@ public: remove_property(face_status_); } + /// --- StatusSet API --- + + /*! + Implements a set of connectivity entities (vertex, edge, face, halfedge) + using the available bits in the corresponding mesh status field. + + Status-based sets are much faster than std::set<> and equivalent + in performance to std::vector, but much more convenient. + */ + template + class StatusSetT + { + public: + typedef HandleT Handle; + + protected: + ArrayKernel& kernel_; + + public: + const unsigned int bit_mask_; + + public: + StatusSetT(ArrayKernel& _kernel, const unsigned int _bit_mask) + : kernel_(_kernel), bit_mask_(_bit_mask) + {} + + ~StatusSetT() + {} + + inline bool is_in(Handle _hnd) const + { return kernel_.status(_hnd).is_bit_set(bit_mask_); } + + inline void insert(Handle _hnd) + { kernel_.status(_hnd).set_bit(bit_mask_); } + + inline void erase(Handle _hnd) + { kernel_.status(_hnd).unset_bit(bit_mask_); } + + //! Note: 0(n) complexity + size_t size() const + { + const int n = kernel_.status_pph(Handle()).is_valid() ? + (int)kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0; + + size_t sz = 0; + for (int i = 0; i < n; ++i) + sz += (size_t)is_in(Handle(i)); + return sz; + } + + //! Note: O(n) complexity + void clear() + { + const int n = kernel_.status_pph(Handle()).is_valid() ? + (int)kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0; + + for (int i = 0; i < n; ++i) + erase(Handle(i)); + } + }; + + friend class StatusSetT; + friend class StatusSetT; + friend class StatusSetT; + friend class StatusSetT; + + //! AutoStatusSetT: A status set that automatically picks a status bit + template + class AutoStatusSetT : public StatusSetT + { + private: + typedef StatusSetT Base; + typedef HandleT Handle; + + public: + AutoStatusSetT(ArrayKernel& _kernel) + : StatusSetT(_kernel, _kernel.pop_bit_mask(Handle())) + { /*assert(size() == 0);*/ } //the set should be empty on creation + + ~AutoStatusSetT() + { + //assert(size() == 0);//the set should be empty on leave? + Base::kernel_.push_bit_mask(Handle(), Base::bit_mask_); + } + }; + + friend class AutoStatusSetT; + friend class AutoStatusSetT; + friend class AutoStatusSetT; + friend class AutoStatusSetT; + + typedef AutoStatusSetT VertexStatusSet; + typedef AutoStatusSetT EdgeStatusSet; + typedef AutoStatusSetT FaceStatusSet; + typedef AutoStatusSetT HalfedgeStatusSet; + + //! ExtStatusSet: A status set augmented with an array + template + class ExtStatusSetT : public AutoStatusSetT + { + public: + typedef HandleT Handle; + typedef AutoStatusSetT Base; + + protected: + typedef std::vector HandleContainer; + HandleContainer handles_; + + public: + typedef typename HandleContainer::iterator + iterator; + typedef typename HandleContainer::const_iterator + const_iterator; + public: + ExtStatusSetT(ArrayKernel& _kernel, size_t _capacity_hint = 0) + : Base(_kernel) + { handles_.reserve(_capacity_hint); } + + ~ExtStatusSetT() + { clear(); } + + // Complexity: O(1) + inline void insert(Handle _hnd) + { + if (!is_in(_hnd)) + { + Base::insert(_hnd); + handles_.push_back(_hnd); + } + } + + //! Complexity: O(k), (k - number of the elements in the set) + inline void erase(Handle _hnd) + { + if (is_in(_hnd)) + { + iterator it = std::find(begin(), end(), _hnd); + erase(it); + } + } + + //! Complexity: O(1) + inline void erase(iterator _it) + { + assert(_it != end() && is_in(*_it)); + Base::erase(*_it); + *_it = handles_.back(); + _it.pop_back(); + } + + inline void clear() + { + for (iterator it = begin(); it != end(); ++it) + { + assert(is_in(*it)); + Base::erase(*it); + } + handles_.clear(); + } + + /// Complexity: 0(1) + inline unsigned int size() const + { return handles_.size(); } + inline bool empty() const + { return handles_.empty(); } + + //Vector API + inline iterator begin() + { return handles_.begin(); } + inline const_iterator begin() const + { return handles_.begin(); } + + inline iterator end() + { return handles_.end(); } + inline const_iterator end() const + { return handles_.end(); } + + inline Handle& front() + { return handles_.front(); } + inline const Handle& front() const + { return handles_.front(); } + + inline Handle& back() + { return handles_.back(); } + inline const Handle& back() const + { return handles_.back(); } + }; + + typedef ExtStatusSetT ExtFaceStatusSet; + typedef ExtStatusSetT ExtVertexStatusSet; + typedef ExtStatusSetT ExtEdgeStatusSet; + typedef ExtStatusSetT ExtHalfedgeStatusSet; + private: // iterators typedef std::vector VertexContainer;