Garbage collection with tracking of handles. ( Thanks to Maxime Quiblier for the base of this update)
Unit tests for garbage collection (halfedges still missing yet) uint->unsigned int changes git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@640 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
@@ -94,10 +94,10 @@ void ArrayKernel::assign_connectivity(const ArrayKernel& _other)
|
|||||||
#undef COPY_STATUS_PROPERTY
|
#undef COPY_STATUS_PROPERTY
|
||||||
}
|
}
|
||||||
|
|
||||||
uint ArrayKernel::delete_isolated_vertices()
|
unsigned int ArrayKernel::delete_isolated_vertices()
|
||||||
{
|
{
|
||||||
assert(has_vertex_status());//this function requires vertex status property
|
assert(has_vertex_status());//this function requires vertex status property
|
||||||
uint n_isolated = 0;
|
unsigned int n_isolated = 0;
|
||||||
for (KernelVertexIter v_it = vertices_begin(); v_it != vertices_end(); ++v_it)
|
for (KernelVertexIter v_it = vertices_begin(); v_it != vertices_end(); ++v_it)
|
||||||
{
|
{
|
||||||
if (is_isolated(handle(*v_it)))
|
if (is_isolated(handle(*v_it)))
|
||||||
@@ -111,148 +111,10 @@ uint ArrayKernel::delete_isolated_vertices()
|
|||||||
|
|
||||||
void ArrayKernel::garbage_collection(bool _v, bool _e, bool _f)
|
void ArrayKernel::garbage_collection(bool _v, bool _e, bool _f)
|
||||||
{
|
{
|
||||||
int i, i0, i1, nV(n_vertices()), nE(n_edges()), nH(2*n_edges()), nF(n_faces());
|
std::vector<VertexHandle*> empty_vh;
|
||||||
|
std::vector<HalfedgeHandle*> empty_hh;
|
||||||
std::vector<VertexHandle> vh_map;
|
std::vector<FaceHandle*> empty_fh;
|
||||||
std::vector<HalfedgeHandle> hh_map;
|
garbage_collection( _v, _e, _f, &empty_vh,&empty_hh,&empty_fh);
|
||||||
std::vector<FaceHandle> fh_map;
|
|
||||||
|
|
||||||
// setup handle mapping:
|
|
||||||
vh_map.reserve(nV);
|
|
||||||
for (i=0; i<nV; ++i) vh_map.push_back(VertexHandle(i));
|
|
||||||
|
|
||||||
hh_map.reserve(nH);
|
|
||||||
for (i=0; i<nH; ++i) hh_map.push_back(HalfedgeHandle(i));
|
|
||||||
|
|
||||||
fh_map.reserve(nF);
|
|
||||||
for (i=0; i<nF; ++i) fh_map.push_back(FaceHandle(i));
|
|
||||||
|
|
||||||
// remove deleted vertices
|
|
||||||
if (_v && n_vertices() > 0)
|
|
||||||
{
|
|
||||||
i0=0; i1=nV-1;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
// find 1st deleted and last un-deleted
|
|
||||||
while (!status(VertexHandle(i0)).deleted() && i0 < i1) ++i0;
|
|
||||||
while ( status(VertexHandle(i1)).deleted() && i0 < i1) --i1;
|
|
||||||
if (i0 >= i1) break;
|
|
||||||
|
|
||||||
// swap
|
|
||||||
std::swap(vertices_[i0], vertices_[i1]);
|
|
||||||
std::swap(vh_map[i0], vh_map[i1]);
|
|
||||||
vprops_swap(i0, i1);
|
|
||||||
};
|
|
||||||
|
|
||||||
vertices_.resize(status(VertexHandle(i0)).deleted() ? i0 : i0+1);
|
|
||||||
vprops_resize(n_vertices());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// remove deleted edges
|
|
||||||
if (_e && n_edges() > 0)
|
|
||||||
{
|
|
||||||
i0=0; i1=nE-1;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
// find 1st deleted and last un-deleted
|
|
||||||
while (!status(EdgeHandle(i0)).deleted() && i0 < i1) ++i0;
|
|
||||||
while ( status(EdgeHandle(i1)).deleted() && i0 < i1) --i1;
|
|
||||||
if (i0 >= i1) break;
|
|
||||||
|
|
||||||
// swap
|
|
||||||
std::swap(edges_[i0], edges_[i1]);
|
|
||||||
std::swap(hh_map[2*i0], hh_map[2*i1]);
|
|
||||||
std::swap(hh_map[2*i0+1], hh_map[2*i1+1]);
|
|
||||||
eprops_swap(i0, i1);
|
|
||||||
hprops_swap(2*i0, 2*i1);
|
|
||||||
hprops_swap(2*i0+1, 2*i1+1);
|
|
||||||
};
|
|
||||||
|
|
||||||
edges_.resize(status(EdgeHandle(i0)).deleted() ? i0 : i0+1);
|
|
||||||
eprops_resize(n_edges());
|
|
||||||
hprops_resize(n_halfedges());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// remove deleted faces
|
|
||||||
if (_f && n_faces() > 0)
|
|
||||||
{
|
|
||||||
i0=0; i1=nF-1;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
// find 1st deleted and last un-deleted
|
|
||||||
while (!status(FaceHandle(i0)).deleted() && i0 < i1) ++i0;
|
|
||||||
while ( status(FaceHandle(i1)).deleted() && i0 < i1) --i1;
|
|
||||||
if (i0 >= i1) break;
|
|
||||||
|
|
||||||
// swap
|
|
||||||
std::swap(faces_[i0], faces_[i1]);
|
|
||||||
std::swap(fh_map[i0], fh_map[i1]);
|
|
||||||
fprops_swap(i0, i1);
|
|
||||||
};
|
|
||||||
|
|
||||||
faces_.resize(status(FaceHandle(i0)).deleted() ? i0 : i0+1);
|
|
||||||
fprops_resize(n_faces());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// update handles of vertices
|
|
||||||
if (_e)
|
|
||||||
{
|
|
||||||
KernelVertexIter v_it(vertices_begin()), v_end(vertices_end());
|
|
||||||
VertexHandle vh;
|
|
||||||
|
|
||||||
for (; v_it!=v_end; ++v_it)
|
|
||||||
{
|
|
||||||
vh = handle(*v_it);
|
|
||||||
if (!is_isolated(vh))
|
|
||||||
{
|
|
||||||
set_halfedge_handle(vh, hh_map[halfedge_handle(vh).idx()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HalfedgeHandle hh;
|
|
||||||
// update handles of halfedges
|
|
||||||
for (KernelEdgeIter e_it(edges_begin()); e_it != edges_end(); ++e_it)
|
|
||||||
{//in the first pass update the (half)edges vertices
|
|
||||||
hh = halfedge_handle(handle(*e_it), 0);
|
|
||||||
set_vertex_handle(hh, vh_map[to_vertex_handle(hh).idx()]);
|
|
||||||
hh = halfedge_handle(handle(*e_it), 1);
|
|
||||||
set_vertex_handle(hh, vh_map[to_vertex_handle(hh).idx()]);
|
|
||||||
}
|
|
||||||
for (KernelEdgeIter e_it(edges_begin()); e_it != edges_end(); ++e_it)
|
|
||||||
{//in the second pass update the connectivity of the (half)edges
|
|
||||||
hh = halfedge_handle(handle(*e_it), 0);
|
|
||||||
set_next_halfedge_handle(hh, hh_map[next_halfedge_handle(hh).idx()]);
|
|
||||||
if (!is_boundary(hh))
|
|
||||||
{
|
|
||||||
set_face_handle(hh, fh_map[face_handle(hh).idx()]);
|
|
||||||
}
|
|
||||||
hh = halfedge_handle(handle(*e_it), 1);
|
|
||||||
set_next_halfedge_handle(hh, hh_map[next_halfedge_handle(hh).idx()]);
|
|
||||||
if (!is_boundary(hh))
|
|
||||||
{
|
|
||||||
set_face_handle(hh, fh_map[face_handle(hh).idx()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// update handles of faces
|
|
||||||
if (_e)
|
|
||||||
{
|
|
||||||
KernelFaceIter f_it(faces_begin()), f_end(faces_end());
|
|
||||||
FaceHandle fh;
|
|
||||||
|
|
||||||
for (; f_it!=f_end; ++f_it)
|
|
||||||
{
|
|
||||||
fh = handle(*f_it);
|
|
||||||
set_halfedge_handle(fh, hh_map[halfedge_handle(fh).idx()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArrayKernel::clear()
|
void ArrayKernel::clear()
|
||||||
@@ -273,7 +135,7 @@ void ArrayKernel::clear()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArrayKernel::resize( uint _n_vertices, uint _n_edges, uint _n_faces )
|
void ArrayKernel::resize( unsigned int _n_vertices, unsigned int _n_edges, unsigned int _n_faces )
|
||||||
{
|
{
|
||||||
vertices_.resize(_n_vertices);
|
vertices_.resize(_n_vertices);
|
||||||
edges_.resize(_n_edges);
|
edges_.resize(_n_edges);
|
||||||
@@ -285,7 +147,7 @@ void ArrayKernel::resize( uint _n_vertices, uint _n_edges, uint _n_faces )
|
|||||||
fprops_resize(n_faces());
|
fprops_resize(n_faces());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArrayKernel::reserve(uint _n_vertices, uint _n_edges, uint _n_faces )
|
void ArrayKernel::reserve(unsigned int _n_vertices, unsigned int _n_edges, unsigned int _n_faces )
|
||||||
{
|
{
|
||||||
vertices_.reserve(_n_vertices);
|
vertices_.reserve(_n_vertices);
|
||||||
edges_.reserve(_n_edges);
|
edges_.reserve(_n_edges);
|
||||||
@@ -300,7 +162,7 @@ void ArrayKernel::reserve(uint _n_vertices, uint _n_edges, uint _n_faces )
|
|||||||
// Status Sets API
|
// Status Sets API
|
||||||
void ArrayKernel::init_bit_masks(BitMaskContainer& _bmc)
|
void ArrayKernel::init_bit_masks(BitMaskContainer& _bmc)
|
||||||
{
|
{
|
||||||
for (uint i = Attributes::UNUSED; i != 0; i <<= 1)
|
for (unsigned int i = Attributes::UNUSED; i != 0; i <<= 1)
|
||||||
{
|
{
|
||||||
_bmc.push_back(i);
|
_bmc.push_back(i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ public:
|
|||||||
// There are two halfedges stored per edge
|
// There are two halfedges stored per edge
|
||||||
// Get memory position inside edge vector and devide by size of an edge
|
// Get memory position inside edge vector and devide by size of an edge
|
||||||
// to get the corresponding edge for the requested halfedge
|
// to get the corresponding edge for the requested halfedge
|
||||||
uint eh = ( (char*)&_he - (char*)&edges_.front() ) / sizeof(Edge) ;
|
unsigned int eh = ( (char*)&_he - (char*)&edges_.front() ) / sizeof(Edge) ;
|
||||||
assert((&_he == &edges_[eh].halfedges_[0]) ||
|
assert((&_he == &edges_[eh].halfedges_[0]) ||
|
||||||
(&_he == &edges_[eh].halfedges_[1]));
|
(&_he == &edges_[eh].halfedges_[1]));
|
||||||
return ((&_he == &edges_[eh].halfedges_[0]) ?
|
return ((&_he == &edges_[eh].halfedges_[0]) ?
|
||||||
@@ -201,19 +201,19 @@ public:
|
|||||||
|
|
||||||
// --- get i'th items ---
|
// --- get i'th items ---
|
||||||
|
|
||||||
VertexHandle vertex_handle(uint _i) const
|
VertexHandle vertex_handle(unsigned int _i) const
|
||||||
{ return (_i < n_vertices()) ? handle( vertices_[_i] ) : VertexHandle(); }
|
{ return (_i < n_vertices()) ? handle( vertices_[_i] ) : VertexHandle(); }
|
||||||
|
|
||||||
HalfedgeHandle halfedge_handle(uint _i) const
|
HalfedgeHandle halfedge_handle(unsigned int _i) const
|
||||||
{
|
{
|
||||||
return (_i < n_halfedges()) ?
|
return (_i < n_halfedges()) ?
|
||||||
halfedge_handle(edge_handle(_i/2), _i%2) : HalfedgeHandle();
|
halfedge_handle(edge_handle(_i/2), _i%2) : HalfedgeHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeHandle edge_handle(uint _i) const
|
EdgeHandle edge_handle(unsigned int _i) const
|
||||||
{ return (_i < n_edges()) ? handle(edges_[_i]) : EdgeHandle(); }
|
{ return (_i < n_edges()) ? handle(edges_[_i]) : EdgeHandle(); }
|
||||||
|
|
||||||
FaceHandle face_handle(uint _i) const
|
FaceHandle face_handle(unsigned int _i) const
|
||||||
{ return (_i < n_faces()) ? handle(faces_[_i]) : FaceHandle(); }
|
{ return (_i < n_faces()) ? handle(faces_[_i]) : FaceHandle(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -257,18 +257,52 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// --- resize/reserve ---
|
// --- resize/reserve ---
|
||||||
void resize( uint _n_vertices, uint _n_edges, uint _n_faces );
|
void resize( unsigned int _n_vertices, unsigned int _n_edges, unsigned int _n_faces );
|
||||||
void reserve(uint _n_vertices, uint _n_edges, uint _n_faces );
|
void reserve(unsigned int _n_vertices, unsigned int _n_edges, unsigned int _n_faces );
|
||||||
|
|
||||||
// --- deletion ---
|
// --- deletion ---
|
||||||
|
/** \brief garbage collection
|
||||||
|
*
|
||||||
|
* Usually if you delete primitives in OpenMesh, they are only flagged as deleted.
|
||||||
|
* Only when you call garbage collection, they will be actually removed.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param _v Remove deleted vertices?
|
||||||
|
* @param _e Remove deleted edges?
|
||||||
|
* @param _f Remove deleted faces?
|
||||||
|
*/
|
||||||
void garbage_collection(bool _v=true, bool _e=true, bool _f=true);
|
void garbage_collection(bool _v=true, bool _e=true, bool _f=true);
|
||||||
|
|
||||||
|
/** \brief garbage collection
|
||||||
|
*
|
||||||
|
* Usually if you delete primitives in OpenMesh, they are only flagged as deleted.
|
||||||
|
* Only when you call garbage collection, they will be actually removed.
|
||||||
|
*
|
||||||
|
* \note Garbage collection invalidates all handles. If you need to keep track of
|
||||||
|
* a set of handles, you can pass vectors of pointers to the handles to this function
|
||||||
|
*
|
||||||
|
* @param vh_to_update Vertex handles that should get updated
|
||||||
|
* @param hh_to_update Halfedge handles that should get updated
|
||||||
|
* @param fh_to_update Face handles that should get updated
|
||||||
|
* @param _v Remove deleted vertices?
|
||||||
|
* @param _e Remove deleted edges?
|
||||||
|
* @param _f Remove deleted faces?
|
||||||
|
*/
|
||||||
|
template<typename std_API_Container_VHandlePointer,
|
||||||
|
typename std_API_Container_HHandlePointer,
|
||||||
|
typename std_API_Container_FHandlePointer>
|
||||||
|
void garbage_collection(bool _v=true, bool _e=true, bool _f=true,
|
||||||
|
std_API_Container_VHandlePointer* vh_to_update = 0,
|
||||||
|
std_API_Container_HHandlePointer* hh_to_update = 0,
|
||||||
|
std_API_Container_FHandlePointer* fh_to_update = 0);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
// --- number of items ---
|
// --- number of items ---
|
||||||
uint n_vertices() const { return vertices_.size(); }
|
unsigned int n_vertices() const { return vertices_.size(); }
|
||||||
uint n_halfedges() const { return 2*edges_.size(); }
|
unsigned int n_halfedges() const { return 2*edges_.size(); }
|
||||||
uint n_edges() const { return edges_.size(); }
|
unsigned int n_edges() const { return edges_.size(); }
|
||||||
uint n_faces() const { return faces_.size(); }
|
unsigned int n_faces() const { return faces_.size(); }
|
||||||
|
|
||||||
bool vertices_empty() const { return vertices_.empty(); }
|
bool vertices_empty() const { return vertices_.empty(); }
|
||||||
bool halfedges_empty() const { return edges_.empty(); }
|
bool halfedges_empty() const { return edges_.empty(); }
|
||||||
@@ -292,7 +326,7 @@ public:
|
|||||||
void set_isolated(VertexHandle _vh)
|
void set_isolated(VertexHandle _vh)
|
||||||
{ vertex(_vh).halfedge_handle_.invalidate(); }
|
{ vertex(_vh).halfedge_handle_.invalidate(); }
|
||||||
|
|
||||||
uint delete_isolated_vertices();
|
unsigned int delete_isolated_vertices();
|
||||||
|
|
||||||
// --- halfedge connectivity ---
|
// --- halfedge connectivity ---
|
||||||
VertexHandle to_vertex_handle(HalfedgeHandle _heh) const
|
VertexHandle to_vertex_handle(HalfedgeHandle _heh) const
|
||||||
@@ -394,7 +428,7 @@ public:
|
|||||||
{ return next_halfedge_handle(opposite_halfedge_handle(_heh)); }
|
{ return next_halfedge_handle(opposite_halfedge_handle(_heh)); }
|
||||||
|
|
||||||
// --- edge connectivity ---
|
// --- edge connectivity ---
|
||||||
HalfedgeHandle halfedge_handle(EdgeHandle _eh, uint _i) const
|
HalfedgeHandle halfedge_handle(EdgeHandle _eh, unsigned int _i) const
|
||||||
{
|
{
|
||||||
assert(_i<=1);
|
assert(_i<=1);
|
||||||
return HalfedgeHandle((_eh.idx() << 1) + _i);
|
return HalfedgeHandle((_eh.idx() << 1) + _i);
|
||||||
@@ -538,10 +572,10 @@ public:
|
|||||||
ArrayKernel& kernel_;
|
ArrayKernel& kernel_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const uint bit_mask_;
|
const unsigned int bit_mask_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StatusSetT(ArrayKernel& _kernel, uint _bit_mask)
|
StatusSetT(ArrayKernel& _kernel, unsigned int _bit_mask)
|
||||||
: kernel_(_kernel), bit_mask_(_bit_mask)
|
: kernel_(_kernel), bit_mask_(_bit_mask)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -558,14 +592,14 @@ public:
|
|||||||
{ kernel_.status(_hnd).unset_bit(bit_mask_); }
|
{ kernel_.status(_hnd).unset_bit(bit_mask_); }
|
||||||
|
|
||||||
/// Note: 0(n) complexity
|
/// Note: 0(n) complexity
|
||||||
uint size() const
|
unsigned int size() const
|
||||||
{
|
{
|
||||||
uint n_elements = kernel_.status_pph(Handle()).is_valid() ?
|
unsigned int n_elements = kernel_.status_pph(Handle()).is_valid() ?
|
||||||
kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0;
|
kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0;
|
||||||
uint sz = 0;
|
unsigned int sz = 0;
|
||||||
for (uint i = 0; i < n_elements; ++i)
|
for (unsigned int i = 0; i < n_elements; ++i)
|
||||||
{
|
{
|
||||||
sz += (uint)is_in(Handle(i));
|
sz += (unsigned int)is_in(Handle(i));
|
||||||
}
|
}
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
@@ -573,9 +607,9 @@ public:
|
|||||||
/// Note: O(n) complexity
|
/// Note: O(n) complexity
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
uint n_elements = kernel_.status_pph(Handle()).is_valid() ?
|
unsigned int n_elements = kernel_.status_pph(Handle()).is_valid() ?
|
||||||
kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0;
|
kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0;
|
||||||
for (uint i = 0; i < n_elements; ++i)
|
for (unsigned int i = 0; i < n_elements; ++i)
|
||||||
{
|
{
|
||||||
erase(Handle(i));
|
erase(Handle(i));
|
||||||
}
|
}
|
||||||
@@ -634,7 +668,7 @@ public:
|
|||||||
typedef typename HandleContainer::const_iterator
|
typedef typename HandleContainer::const_iterator
|
||||||
const_iterator;
|
const_iterator;
|
||||||
public:
|
public:
|
||||||
ExtStatusSetT(ArrayKernel& _kernel, uint _capacity_hint = 0)
|
ExtStatusSetT(ArrayKernel& _kernel, unsigned int _capacity_hint = 0)
|
||||||
: Base(_kernel)
|
: Base(_kernel)
|
||||||
{ handles_.reserve(_capacity_hint); }
|
{ handles_.reserve(_capacity_hint); }
|
||||||
|
|
||||||
@@ -682,7 +716,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Complexity: 0(1)
|
/// Complexity: 0(1)
|
||||||
inline uint size() const
|
inline unsigned int size() const
|
||||||
{ return handles_.size(); }
|
{ return handles_.size(); }
|
||||||
inline bool empty() const
|
inline bool empty() const
|
||||||
{ return handles_.empty(); }
|
{ return handles_.empty(); }
|
||||||
@@ -725,7 +759,7 @@ private:
|
|||||||
typedef EdgeContainer::const_iterator KernelConstEdgeIter;
|
typedef EdgeContainer::const_iterator KernelConstEdgeIter;
|
||||||
typedef FaceContainer::iterator KernelFaceIter;
|
typedef FaceContainer::iterator KernelFaceIter;
|
||||||
typedef FaceContainer::const_iterator KernelConstFaceIter;
|
typedef FaceContainer::const_iterator KernelConstFaceIter;
|
||||||
typedef std::vector<uint> BitMaskContainer;
|
typedef std::vector<unsigned int> BitMaskContainer;
|
||||||
|
|
||||||
|
|
||||||
KernelVertexIter vertices_begin() { return vertices_.begin(); }
|
KernelVertexIter vertices_begin() { return vertices_.begin(); }
|
||||||
@@ -754,16 +788,16 @@ private:
|
|||||||
{ return halfedge_bit_masks_; }
|
{ return halfedge_bit_masks_; }
|
||||||
|
|
||||||
template <class Handle>
|
template <class Handle>
|
||||||
uint pop_bit_mask(Handle _hnd)
|
unsigned int pop_bit_mask(Handle _hnd)
|
||||||
{
|
{
|
||||||
assert(!bit_masks(_hnd).empty());//check if the client request too many status sets
|
assert(!bit_masks(_hnd).empty());//check if the client request too many status sets
|
||||||
uint bit_mask = bit_masks(_hnd).back();
|
unsigned int bit_mask = bit_masks(_hnd).back();
|
||||||
bit_masks(_hnd).pop_back();
|
bit_masks(_hnd).pop_back();
|
||||||
return bit_mask;
|
return bit_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Handle>
|
template <class Handle>
|
||||||
void push_bit_mask(Handle _hnd, uint _bit_mask)
|
void push_bit_mask(Handle _hnd, unsigned int _bit_mask)
|
||||||
{
|
{
|
||||||
assert(std::find(bit_masks(_hnd).begin(), bit_masks(_hnd).end(), _bit_mask) ==
|
assert(std::find(bit_masks(_hnd).begin(), bit_masks(_hnd).end(), _bit_mask) ==
|
||||||
bit_masks(_hnd).end());//this mask should be not already used
|
bit_masks(_hnd).end());//this mask should be not already used
|
||||||
@@ -783,10 +817,10 @@ private:
|
|||||||
EdgeStatusPropertyHandle edge_status_;
|
EdgeStatusPropertyHandle edge_status_;
|
||||||
FaceStatusPropertyHandle face_status_;
|
FaceStatusPropertyHandle face_status_;
|
||||||
|
|
||||||
uint refcount_vstatus_;
|
unsigned int refcount_vstatus_;
|
||||||
uint refcount_hstatus_;
|
unsigned int refcount_hstatus_;
|
||||||
uint refcount_estatus_;
|
unsigned int refcount_estatus_;
|
||||||
uint refcount_fstatus_;
|
unsigned int refcount_fstatus_;
|
||||||
|
|
||||||
BitMaskContainer halfedge_bit_masks_;
|
BitMaskContainer halfedge_bit_masks_;
|
||||||
BitMaskContainer edge_bit_masks_;
|
BitMaskContainer edge_bit_masks_;
|
||||||
@@ -794,8 +828,14 @@ private:
|
|||||||
BitMaskContainer face_bit_masks_;
|
BitMaskContainer face_bit_masks_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
} // namespace OpenMesh
|
} // namespace OpenMesh
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_ARRAY_KERNEL_C)
|
||||||
|
# define OPENMESH_ARRAY_KERNEL_TEMPLATES
|
||||||
|
# include "ArrayKernelT.cc"
|
||||||
|
#endif
|
||||||
|
//=============================================================================
|
||||||
#endif // OPENMESH_ARRAY_KERNEL_HH defined
|
#endif // OPENMESH_ARRAY_KERNEL_HH defined
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|||||||
253
src/OpenMesh/Core/Mesh/ArrayKernelT.cc
Normal file
253
src/OpenMesh/Core/Mesh/ArrayKernelT.cc
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
/*===========================================================================*\
|
||||||
|
* *
|
||||||
|
* OpenMesh *
|
||||||
|
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
||||||
|
* www.openmesh.org *
|
||||||
|
* *
|
||||||
|
*---------------------------------------------------------------------------*
|
||||||
|
* This file is part of OpenMesh. *
|
||||||
|
* *
|
||||||
|
* OpenMesh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
* published by the Free Software Foundation, either version 3 of *
|
||||||
|
* the License, or (at your option) any later version with the *
|
||||||
|
* following exceptions: *
|
||||||
|
* *
|
||||||
|
* If other files instantiate templates or use macros *
|
||||||
|
* or inline functions from this file, or you compile this file and *
|
||||||
|
* link it with other files to produce an executable, this file does *
|
||||||
|
* not by itself cause the resulting executable to be covered by the *
|
||||||
|
* GNU Lesser General Public License. This exception does not however *
|
||||||
|
* invalidate any other reasons why the executable file might be *
|
||||||
|
* covered by the GNU Lesser General Public License. *
|
||||||
|
* *
|
||||||
|
* OpenMesh is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU LesserGeneral Public *
|
||||||
|
* License along with OpenMesh. If not, *
|
||||||
|
* see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
\*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*\
|
||||||
|
* *
|
||||||
|
* $Revision: 362 $ *
|
||||||
|
* $Date: 2011-01-26 10:21:12 +0100 (Mi, 26 Jan 2011) $ *
|
||||||
|
* *
|
||||||
|
\*===========================================================================*/
|
||||||
|
|
||||||
|
#define OPENMESH_ARRAY_KERNEL_C
|
||||||
|
|
||||||
|
//== INCLUDES =================================================================
|
||||||
|
|
||||||
|
#include <OpenMesh/Core/Mesh/ArrayKernel.hh>
|
||||||
|
//#include <vector>
|
||||||
|
|
||||||
|
//== NAMESPACES ===============================================================
|
||||||
|
|
||||||
|
namespace OpenMesh
|
||||||
|
{
|
||||||
|
|
||||||
|
//== IMPLEMENTATION ==========================================================
|
||||||
|
|
||||||
|
template<typename std_API_Container_VHandlePointer,
|
||||||
|
typename std_API_Container_HHandlePointer,
|
||||||
|
typename std_API_Container_FHandlePointer>
|
||||||
|
void ArrayKernel::garbage_collection(bool _v, bool _e, bool _f,
|
||||||
|
std_API_Container_VHandlePointer* vh_to_update,
|
||||||
|
std_API_Container_HHandlePointer* hh_to_update,
|
||||||
|
std_API_Container_FHandlePointer* fh_to_update
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int i, i0, i1, nV(n_vertices()), nE(n_edges()), nH(2*n_edges()), nF(n_faces());
|
||||||
|
|
||||||
|
std::vector<VertexHandle> vh_map;
|
||||||
|
std::vector<HalfedgeHandle> hh_map;
|
||||||
|
std::vector<FaceHandle> fh_map;
|
||||||
|
|
||||||
|
// setup handle mapping:
|
||||||
|
vh_map.reserve(nV);
|
||||||
|
for (i=0; i<nV; ++i) vh_map.push_back(VertexHandle(i));
|
||||||
|
|
||||||
|
hh_map.reserve(nH);
|
||||||
|
for (i=0; i<nH; ++i) hh_map.push_back(HalfedgeHandle(i));
|
||||||
|
|
||||||
|
fh_map.reserve(nF);
|
||||||
|
for (i=0; i<nF; ++i) fh_map.push_back(FaceHandle(i));
|
||||||
|
|
||||||
|
// remove deleted vertices
|
||||||
|
if (_v && n_vertices() > 0)
|
||||||
|
{
|
||||||
|
i0=0; i1=nV-1;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// find 1st deleted and last un-deleted
|
||||||
|
while (!status(VertexHandle(i0)).deleted() && i0 < i1) ++i0;
|
||||||
|
while ( status(VertexHandle(i1)).deleted() && i0 < i1) --i1;
|
||||||
|
if (i0 >= i1) break;
|
||||||
|
|
||||||
|
// swap
|
||||||
|
std::swap(vertices_[i0], vertices_[i1]);
|
||||||
|
std::swap(vh_map[i0], vh_map[i1]);
|
||||||
|
vprops_swap(i0, i1);
|
||||||
|
};
|
||||||
|
|
||||||
|
vertices_.resize(status(VertexHandle(i0)).deleted() ? i0 : i0+1);
|
||||||
|
vprops_resize(n_vertices());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// remove deleted edges
|
||||||
|
if (_e && n_edges() > 0)
|
||||||
|
{
|
||||||
|
i0=0; i1=nE-1;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// find 1st deleted and last un-deleted
|
||||||
|
while (!status(EdgeHandle(i0)).deleted() && i0 < i1) ++i0;
|
||||||
|
while ( status(EdgeHandle(i1)).deleted() && i0 < i1) --i1;
|
||||||
|
if (i0 >= i1) break;
|
||||||
|
|
||||||
|
// swap
|
||||||
|
std::swap(edges_[i0], edges_[i1]);
|
||||||
|
std::swap(hh_map[2*i0], hh_map[2*i1]);
|
||||||
|
std::swap(hh_map[2*i0+1], hh_map[2*i1+1]);
|
||||||
|
eprops_swap(i0, i1);
|
||||||
|
hprops_swap(2*i0, 2*i1);
|
||||||
|
hprops_swap(2*i0+1, 2*i1+1);
|
||||||
|
};
|
||||||
|
|
||||||
|
edges_.resize(status(EdgeHandle(i0)).deleted() ? i0 : i0+1);
|
||||||
|
eprops_resize(n_edges());
|
||||||
|
hprops_resize(n_halfedges());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// remove deleted faces
|
||||||
|
if (_f && n_faces() > 0)
|
||||||
|
{
|
||||||
|
i0=0; i1=nF-1;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// find 1st deleted and last un-deleted
|
||||||
|
while (!status(FaceHandle(i0)).deleted() && i0 < i1) ++i0;
|
||||||
|
while ( status(FaceHandle(i1)).deleted() && i0 < i1) --i1;
|
||||||
|
if (i0 >= i1) break;
|
||||||
|
|
||||||
|
// swap
|
||||||
|
std::swap(faces_[i0], faces_[i1]);
|
||||||
|
std::swap(fh_map[i0], fh_map[i1]);
|
||||||
|
fprops_swap(i0, i1);
|
||||||
|
};
|
||||||
|
|
||||||
|
faces_.resize(status(FaceHandle(i0)).deleted() ? i0 : i0+1);
|
||||||
|
fprops_resize(n_faces());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// update handles of vertices
|
||||||
|
if (_e)
|
||||||
|
{
|
||||||
|
KernelVertexIter v_it(vertices_begin()), v_end(vertices_end());
|
||||||
|
VertexHandle vh;
|
||||||
|
|
||||||
|
for (; v_it!=v_end; ++v_it)
|
||||||
|
{
|
||||||
|
vh = handle(*v_it);
|
||||||
|
if (!is_isolated(vh))
|
||||||
|
{
|
||||||
|
set_halfedge_handle(vh, hh_map[halfedge_handle(vh).idx()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HalfedgeHandle hh;
|
||||||
|
// update handles of halfedges
|
||||||
|
for (KernelEdgeIter e_it(edges_begin()); e_it != edges_end(); ++e_it)
|
||||||
|
{//in the first pass update the (half)edges vertices
|
||||||
|
hh = halfedge_handle(handle(*e_it), 0);
|
||||||
|
set_vertex_handle(hh, vh_map[to_vertex_handle(hh).idx()]);
|
||||||
|
hh = halfedge_handle(handle(*e_it), 1);
|
||||||
|
set_vertex_handle(hh, vh_map[to_vertex_handle(hh).idx()]);
|
||||||
|
}
|
||||||
|
for (KernelEdgeIter e_it(edges_begin()); e_it != edges_end(); ++e_it)
|
||||||
|
{//in the second pass update the connectivity of the (half)edges
|
||||||
|
hh = halfedge_handle(handle(*e_it), 0);
|
||||||
|
set_next_halfedge_handle(hh, hh_map[next_halfedge_handle(hh).idx()]);
|
||||||
|
if (!is_boundary(hh))
|
||||||
|
{
|
||||||
|
set_face_handle(hh, fh_map[face_handle(hh).idx()]);
|
||||||
|
}
|
||||||
|
hh = halfedge_handle(handle(*e_it), 1);
|
||||||
|
set_next_halfedge_handle(hh, hh_map[next_halfedge_handle(hh).idx()]);
|
||||||
|
if (!is_boundary(hh))
|
||||||
|
{
|
||||||
|
set_face_handle(hh, fh_map[face_handle(hh).idx()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update handles of faces
|
||||||
|
if (_e)
|
||||||
|
{
|
||||||
|
KernelFaceIter f_it(faces_begin()), f_end(faces_end());
|
||||||
|
FaceHandle fh;
|
||||||
|
|
||||||
|
for (; f_it!=f_end; ++f_it)
|
||||||
|
{
|
||||||
|
fh = handle(*f_it);
|
||||||
|
set_halfedge_handle(fh, hh_map[halfedge_handle(fh).idx()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the vertex handles in the vertex handle vector
|
||||||
|
if ( vh_to_update ) {
|
||||||
|
|
||||||
|
const int vertexCount = vertices_.size();
|
||||||
|
typename std_API_Container_VHandlePointer::iterator v_it(vh_to_update->begin()), v_it_end(vh_to_update->end());
|
||||||
|
for(; v_it != v_it_end; ++v_it)
|
||||||
|
{
|
||||||
|
if ( (*v_it)->idx() >= vertexCount )
|
||||||
|
(*v_it)->invalidate();
|
||||||
|
else
|
||||||
|
*(*v_it) = vh_map[(*v_it)->idx()];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the halfedge handles in the halfedge handle vector
|
||||||
|
if ( hh_to_update ) {
|
||||||
|
const int halfedgeCount = edges_.size() * 2;
|
||||||
|
|
||||||
|
typename std_API_Container_HHandlePointer::iterator hh_it(hh_to_update->begin()), hh_it_end(hh_to_update->end());
|
||||||
|
for(; hh_it != hh_it_end; ++hh_it)
|
||||||
|
{
|
||||||
|
if ( (*hh_it)->idx() >= halfedgeCount )
|
||||||
|
(*hh_it)->invalidate();
|
||||||
|
else
|
||||||
|
*(*hh_it) = hh_map[(*hh_it)->idx()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the face handles in the face handle vector
|
||||||
|
if(fh_to_update) {
|
||||||
|
const int faceCount = faces_.size();
|
||||||
|
|
||||||
|
typename std_API_Container_FHandlePointer::iterator fh_it(fh_to_update->begin()), fh_it_end(fh_to_update->end());
|
||||||
|
for(; fh_it != fh_it_end; ++fh_it)
|
||||||
|
{
|
||||||
|
if ( (*fh_it)->idx() >= faceCount )
|
||||||
|
(*fh_it)->invalidate();
|
||||||
|
else
|
||||||
|
*(*fh_it) = fh_map[(*fh_it)->idx()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "unittests_trimesh_normal_calculations.hh"
|
#include "unittests_trimesh_normal_calculations.hh"
|
||||||
#include "unittests_trimesh_others.hh"
|
#include "unittests_trimesh_others.hh"
|
||||||
#include "unittests_add_face.hh"
|
#include "unittests_add_face.hh"
|
||||||
|
#include "unittests_trimesh_garbage_collection.hh"
|
||||||
|
|
||||||
int main(int _argc, char** _argv) {
|
int main(int _argc, char** _argv) {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user