Subversion Repositories gelsvn

Rev

Rev 512 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
* Written by Christian Thode Larsen 2009-2010
* Contact: thode2d@gmail.com
* Based on original work by J. Andreas Baerentzen
* Inspired by OpenMesh (www.openmesh.org)
*/

#ifndef __HMESH_ITEMVECTOR_H__
#define __HMESH_ITEMVECTOR_H__

#include <vector>

#include "ItemID.h"

namespace HMesh
{
        template<typename ITEM>
        class ItemVector
        {
        public:
                /// default constructor
                ItemVector();
                ItemVector(IndexType _size, ITEM i = ITEM()); 

                /// Get a reference to entity i from kernel
                ITEM& get(IndexType i);
                /// Get a const reference to entity i from kernel
                const ITEM& get(IndexType i) const;

                ITEM& operator[](IndexType i);
                const ITEM& operator[](IndexType i) const;

                /// Add an entity to the kernel
                IndexType add(const ITEM& i);

                /// remove an entity from kernel - entity is NOT erased!
                void remove(IndexType i);

                /// erase unused entities from the kernel
                void cleanup();

                /// size of vector (default: only active items)
                IndexType size(bool active = true) const;

                /// Resize the kernel NOTE: Sets all active flags to true
                void resize(IndexType _size, ITEM i = ITEM());
                /// Request size change in kernel
                void reserve(IndexType i);

                /// Clear the kernel
                void clear();

                /// Check if entity i is used
                bool in_use(IndexType i) const;

                /// get starting index (default: skip to first active index)
                IndexType index_begin(bool skip = true) const;

                /// get ending index
                IndexType index_end() const;

                /// get the next index (default: skip to first active index)
                IndexType index_next(IndexType index, bool skip = true) const;

                /// get the previous index (default: skip to first active index)
                IndexType index_prev(IndexType index, bool skip = true) const;

        private:

                IndexType size_active;
                std::vector<ITEM> items;

                /// Memory consideration - objects flagged as unused should be remembered for future use (unless purged)
                std::vector<bool> active_items;
        };

        template<typename ITEM>
        inline ItemVector<ITEM>::ItemVector() : size_active(0) {}

        template<typename ITEM>
        inline ItemVector<ITEM>::ItemVector(IndexType _size, ITEM i = ITEM()) : size_active(_size), items(_size, i){}

        template<typename ITEM>
        ITEM& ItemVector<ITEM>::get(IndexType i)
        {
                assert(i < items.size());
                return items[i];
        }

        template<typename ITEM>
        const ITEM& ItemVector<ITEM>::get(IndexType i) const
        {
                assert(i < items.size());
                return items[i];
        }

        template<typename ITEM>
        ITEM& ItemVector<ITEM>::operator [](IndexType i)
        {
                assert(i < items.size());
                return items[i];
        } 

        template<typename ITEM>
        const ITEM& ItemVector<ITEM>::operator [](IndexType i) const
        {
                assert(i < items.size());
                return items[i];
        }

        template<typename ITEM>
        IndexType ItemVector<ITEM>::add(const ITEM& i)
        {
                items.push_back(i);
                active_items.push_back(true);
                ++size_active;
                return items.size() - 1;
        }

        template<typename ITEM>
        void ItemVector<ITEM>::remove(IndexType i)
        {
                if(active_items[i]) 
                        --size_active;
                active_items[i] = false;
        }

        template<typename ITEM>
        void ItemVector<ITEM>::cleanup()
        {
                std::vector<ITEM> new_items;
                for(IndexType i = 0; i < items.size(); ++i){
                        if(active_items[i]) 
                                new_items.push_back(items[i]);          
                }
                items = new_items;
                active_items = std::vector<bool>(items.size(), true);
                size_active = items.size();
        }

        template<typename ITEM>
        IndexType ItemVector<ITEM>::size(bool active = true) const
        { return active ? size_active : items.size(); }

        template<typename ITEM>
        void ItemVector<ITEM>::resize(IndexType _size, ITEM i = ITEM())
        {
                items.resize(_size, i);
                active_items.resize(_size, true);
                size_active = _size;
        }

        template<typename ITEM>
        void ItemVector<ITEM>::reserve(IndexType i)
        {
                items.reserve(i);
                active_items.reserve(i);
        }

        template<typename ITEM>
        void ItemVector<ITEM>::clear()
        {
                items.clear();
                active_items.clear();
                size_active = 0;
        }

        template<typename ITEM>
        bool ItemVector<ITEM>::in_use(IndexType i) const
        {
                assert(i < active_items.size());
                return active_items[i];
        }

        template<typename ITEM>
        IndexType ItemVector<ITEM>::index_begin(bool skip = true) const
        {
                if(!skip)
                        return 0;
                IndexType i = 0;
                while(!active_items[i])
                        ++i;
                return i;
        }

        template<typename ITEM>
        IndexType ItemVector<ITEM>::index_end() const
        { return items.size(); }

        template<typename ITEM>
        IndexType ItemVector<ITEM>::index_next(IndexType index, bool skip = true) const
        {
                if(index != items.size())
                        ++index;

                if(skip){
                        while(!in_use(index) && index < items.size()){
                                ++index;
                        }
                }
                return index;
        }

        template<typename ITEM>
        IndexType ItemVector<ITEM>::index_prev(IndexType index, bool skip = true) const
        {
                if(index > 0)
                        --index;

                if(skip){
                        while(!in_use(index) && index > 0){
                                --index;
                        }
                }
                return index;
        }

}

#endif