Rev 595 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/* ----------------------------------------------------------------------- *
* This file is part of GEL, http://www.imm.dtu.dk/GEL
* Copyright (C) the authors and DTU Informatics
* For license and list of authors, see ../../doc/intro.pdf
* ----------------------------------------------------------------------- */
/**
* @file ItemVector.h
* @brief Contains the vector type used for the mesh entities.
*/
#ifndef __HMESH_ITEMVECTOR_H__
#define __HMESH_ITEMVECTOR_H__
#include <cassert>
#include <vector>
#include "ItemID.h"
namespace HMesh
{
/** The ItemVector is a vector of mesh entities.
An ItemVector is a layer on top of the regular vector class which keeps
track of the unused elements in a vector. This allows for garbage collection.
ItemVector is used for storing vectors of Face, HalfEdge, and Vertex type.
*/
template<typename ITEM>
class ItemVector
{
public:
typedef ItemID<ITEM> IDType;
/// default constructor
ItemVector(size_t _size = 0, ITEM i = ITEM());
/// Get a reference to item i from kernel
ITEM& get(IDType i);
/// Get a const reference to item i from kernel
const ITEM& get(IDType i) const;
/// Get a reference to item i from kernel
ITEM& operator[](IDType i);
/// Get a const reference to item i from kernel
const ITEM& operator[](IDType i) const;
/// Add an entity to the kernel
IDType add(const ITEM& i);
/// remove an entity from kernel - entity is NOT erased!
void remove(IDType i);
/// erase unused entities from the kernel
void cleanup();
/// active size of vector
size_t size() const;
/// total size of vector
size_t allocated_size() const;
/// Resize the kernel NOTE: Sets all active flags to true
void resize(size_t _size, ITEM i = ITEM());
/// Request size change in kernel
void reserve(size_t i);
/// Clear the kernel
void clear();
/// Check if entity i is used
bool in_use(IDType i) const;
/// get starting index (default: skip to first active index)
IDType index_begin(bool skip = true) const;
/// get one past the end index of vector
IDType index_end() const;
/// get the next index (default: skip to first active index)
IDType index_next(IDType index, bool skip = true) const;
/// get the previous index (default: skip to first active index)
IDType index_prev(IDType index, bool skip = true) const;
private:
size_t 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_t _size, ITEM i)
: size_active(_size),
items(_size, i),
active_items(_size, true){}
template<typename ITEM>
inline ITEM& ItemVector<ITEM>::get(IDType id)
{
assert(id.index < items.size());
return items[id.index];
}
template<typename ITEM>
inline const ITEM& ItemVector<ITEM>::get(IDType id) const
{
assert(id.index < items.size());
return items[id.index];
}
template<typename ITEM>
inline ITEM& ItemVector<ITEM>::operator [](IDType id)
{
assert(id.index < items.size());
return items[id.index];
}
template<typename ITEM>
inline const ITEM& ItemVector<ITEM>::operator [](IDType id) const
{
assert(id.index < items.size());
return items[id.index];
}
template<typename ITEM>
inline typename ItemVector<ITEM>::IDType ItemVector<ITEM>::add(const ITEM& item)
{
items.push_back(item);
active_items.push_back(true);
++size_active;
return IDType(items.size() - 1);
}
template<typename ITEM>
inline void ItemVector<ITEM>::remove(typename ItemVector<ITEM>::IDType id)
{
if(active_items[id.index]){
--size_active;
active_items[id.index] = false;
}
}
template<typename ITEM>
inline void ItemVector<ITEM>::cleanup()
{
std::vector<ITEM> new_items;
for(size_t i = 0; i < items.size(); ++i){
if(active_items[i])
new_items.push_back(items[i]);
}
std::swap(items, new_items);
active_items = std::vector<bool>(items.size(), true);
size_active = items.size();
}
template<typename ITEM>
inline size_t ItemVector<ITEM>::size() const
{ return size_active; }
template<typename ITEM>
inline size_t ItemVector<ITEM>::allocated_size() const
{ return items.size(); }
template<typename ITEM>
inline void ItemVector<ITEM>::resize(size_t _size, ITEM i)
{
items.resize(_size, i);
active_items.resize(_size, true);
size_active = _size;
}
template<typename ITEM>
inline void ItemVector<ITEM>::reserve(size_t i)
{
items.reserve(i);
active_items.reserve(i);
}
template<typename ITEM>
inline void ItemVector<ITEM>::clear()
{
items.clear();
active_items.clear();
size_active = 0;
}
template<typename ITEM>
inline bool ItemVector<ITEM>::in_use(typename ItemVector<ITEM>::IDType id) const
{
if(id.index < active_items.size())
return active_items[id.index];
return false;
}
template<typename ITEM>
inline typename ItemVector<ITEM>::IDType ItemVector<ITEM>::index_begin(bool skip) const
{
size_t i = 0;
if(!skip)
return IDType(i);
while(i < active_items.size() && !active_items[i])
++i;
return IDType(i);
}
template<typename ITEM>
inline typename ItemVector<ITEM>::IDType ItemVector<ITEM>::index_end() const
{ return IDType(items.size()); }
template<typename ITEM>
inline typename ItemVector<ITEM>::IDType ItemVector<ITEM>::index_next(typename ItemVector<ITEM>::IDType id, bool skip) const
{
if(id.index < items.size())
++id.index;
if(!skip)
return IDType(id);
while(id.index < items.size() && !active_items[id.index])
++id.index;
return id;
}
template<typename ITEM>
inline typename ItemVector<ITEM>::IDType ItemVector<ITEM>::index_prev(typename ItemVector<ITEM>::IDType id, bool skip) const
{
if(id.index > 0)
--id.index;
if(!skip)
return id;
while(!active_items[id.index] && id.index > 0)
--id.index;
return id;
}
}
#endif