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