2009-02-06 13:37:46 +00:00
|
|
|
/*===========================================================================*\
|
|
|
|
|
* *
|
|
|
|
|
* OpenMesh *
|
2011-01-26 09:21:12 +00:00
|
|
|
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
|
2009-02-06 13:37:46 +00:00
|
|
|
* www.openmesh.org *
|
|
|
|
|
* *
|
2009-06-04 08:46:29 +00:00
|
|
|
*---------------------------------------------------------------------------*
|
|
|
|
|
* This file is part of OpenMesh. *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
2009-06-04 08:46:29 +00:00
|
|
|
* 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: *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
2009-06-04 08:46:29 +00:00
|
|
|
* 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. *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
2009-06-04 08:46:29 +00:00
|
|
|
* 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. *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
2009-06-04 08:46:29 +00:00
|
|
|
* You should have received a copy of the GNU LesserGeneral Public *
|
|
|
|
|
* License along with OpenMesh. If not, *
|
|
|
|
|
* see <http://www.gnu.org/licenses/>. *
|
|
|
|
|
* *
|
|
|
|
|
\*===========================================================================*/
|
|
|
|
|
|
|
|
|
|
/*===========================================================================*\
|
|
|
|
|
* *
|
|
|
|
|
* $Revision$ *
|
|
|
|
|
* $Date$ *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
|
|
|
|
\*===========================================================================*/
|
|
|
|
|
|
|
|
|
|
#include <OpenMesh/Core/Mesh/ArrayKernel.hh>
|
|
|
|
|
|
|
|
|
|
namespace OpenMesh
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
ArrayKernel::ArrayKernel()
|
|
|
|
|
: refcount_vstatus_(0), refcount_hstatus_(0),
|
|
|
|
|
refcount_estatus_(0), refcount_fstatus_(0)
|
|
|
|
|
{
|
|
|
|
|
init_bit_masks(); //Status bit masks initialization
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ArrayKernel::~ArrayKernel()
|
|
|
|
|
{
|
|
|
|
|
clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ArrayKernel::ArrayKernel(const ArrayKernel& _rhs)
|
|
|
|
|
// : BaseKernel(_rhs),
|
|
|
|
|
// vertices_(_rhs.vertices_), edges_(_rhs.edges_), faces_(_rhs.faces_),
|
|
|
|
|
// vertex_status_(_rhs.vertex_status_), halfedge_status_(_rhs.halfedge_status_),
|
|
|
|
|
// edge_status_(_rhs.edge_status_), face_status_(_rhs.face_status_),
|
|
|
|
|
// refcount_vstatus_(_rhs.refcount_vstatus_), refcount_hstatus_(_rhs.refcount_hstatus_),
|
|
|
|
|
// refcount_estatus_(_rhs.refcount_estatus_), refcount_fstatus_(_rhs.refcount_fstatus_)
|
|
|
|
|
// {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ArrayKernel::assign_connectivity(const ArrayKernel& _other)
|
|
|
|
|
{
|
|
|
|
|
vertices_ = _other.vertices_;
|
|
|
|
|
edges_ = _other.edges_;
|
|
|
|
|
faces_ = _other.faces_;
|
|
|
|
|
|
|
|
|
|
vprops_resize(n_vertices());
|
|
|
|
|
hprops_resize(n_halfedges());
|
|
|
|
|
eprops_resize(n_edges());
|
|
|
|
|
fprops_resize(n_faces());
|
|
|
|
|
|
|
|
|
|
#define COPY_STATUS_PROPERTY(ENTITY) \
|
|
|
|
|
if (_other.ENTITY##_status_.is_valid()) \
|
|
|
|
|
{ \
|
|
|
|
|
if (!ENTITY##_status_.is_valid()) \
|
|
|
|
|
{ \
|
|
|
|
|
request_##ENTITY##_status(); \
|
|
|
|
|
} \
|
|
|
|
|
property(ENTITY##_status_) = _other.property(_other.ENTITY##_status_); \
|
|
|
|
|
}
|
|
|
|
|
COPY_STATUS_PROPERTY(vertex)
|
|
|
|
|
COPY_STATUS_PROPERTY(halfedge)
|
|
|
|
|
COPY_STATUS_PROPERTY(edge)
|
|
|
|
|
COPY_STATUS_PROPERTY(face)
|
|
|
|
|
|
|
|
|
|
#undef COPY_STATUS_PROPERTY
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint ArrayKernel::delete_isolated_vertices()
|
|
|
|
|
{
|
|
|
|
|
assert(has_vertex_status());//this function requires vertex status property
|
|
|
|
|
uint n_isolated = 0;
|
|
|
|
|
for (KernelVertexIter v_it = vertices_begin(); v_it != vertices_end(); ++v_it)
|
|
|
|
|
{
|
|
|
|
|
if (is_isolated(handle(*v_it)))
|
|
|
|
|
{
|
|
|
|
|
status(handle(*v_it)).set_deleted(true);
|
|
|
|
|
n_isolated++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return n_isolated;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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> 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()]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ArrayKernel::clear()
|
|
|
|
|
{
|
2009-08-10 10:50:34 +00:00
|
|
|
vprops_clear();
|
|
|
|
|
eprops_clear();
|
|
|
|
|
hprops_clear();
|
|
|
|
|
fprops_clear();
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
vertices_.clear();
|
2009-08-10 10:50:34 +00:00
|
|
|
VertexContainer().swap( vertices_ );
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
edges_.clear();
|
2009-08-10 10:50:34 +00:00
|
|
|
EdgeContainer().swap( edges_ );
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
faces_.clear();
|
2009-08-10 10:50:34 +00:00
|
|
|
FaceContainer().swap( faces_ );
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ArrayKernel::resize( uint _n_vertices, uint _n_edges, uint _n_faces )
|
|
|
|
|
{
|
|
|
|
|
vertices_.resize(_n_vertices);
|
|
|
|
|
edges_.resize(_n_edges);
|
|
|
|
|
faces_.resize(_n_faces);
|
|
|
|
|
|
|
|
|
|
vprops_resize(n_vertices());
|
|
|
|
|
hprops_resize(n_halfedges());
|
|
|
|
|
eprops_resize(n_edges());
|
|
|
|
|
fprops_resize(n_faces());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ArrayKernel::reserve(uint _n_vertices, uint _n_edges, uint _n_faces )
|
|
|
|
|
{
|
|
|
|
|
vertices_.reserve(_n_vertices);
|
|
|
|
|
edges_.reserve(_n_edges);
|
|
|
|
|
faces_.reserve(_n_faces);
|
|
|
|
|
|
|
|
|
|
vprops_reserve(_n_vertices);
|
|
|
|
|
hprops_reserve(_n_edges*2);
|
|
|
|
|
eprops_reserve(_n_edges);
|
|
|
|
|
fprops_reserve(_n_faces);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Status Sets API
|
|
|
|
|
void ArrayKernel::init_bit_masks(BitMaskContainer& _bmc)
|
|
|
|
|
{
|
|
|
|
|
for (uint i = Attributes::UNUSED; i != 0; i <<= 1)
|
|
|
|
|
{
|
|
|
|
|
_bmc.push_back(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ArrayKernel::init_bit_masks()
|
|
|
|
|
{
|
|
|
|
|
init_bit_masks(vertex_bit_masks_);
|
|
|
|
|
edge_bit_masks_ = vertex_bit_masks_;//init_bit_masks(edge_bit_masks_);
|
|
|
|
|
face_bit_masks_ = vertex_bit_masks_;//init_bit_masks(face_bit_masks_);
|
|
|
|
|
halfedge_bit_masks_= vertex_bit_masks_;//init_bit_masks(halfedge_bit_masks_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|