First checkin for OpenMesh 2.0
git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@2 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
17
Core/Mesh/ACGMakefile
Normal file
17
Core/Mesh/ACGMakefile
Normal file
@@ -0,0 +1,17 @@
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Config
|
||||
#==============================================================================
|
||||
|
||||
|
||||
SUBDIRS = $(call find-subdirs)
|
||||
|
||||
PACKAGES :=
|
||||
|
||||
PROJ_LIBS :=
|
||||
|
||||
MODULES := cxxlib
|
||||
|
||||
|
||||
#== SYSTEM PART -- DON'T TOUCH ==============================================
|
||||
include $(ACGMAKE)/Rules
|
||||
#==============================================================================
|
||||
112
Core/Mesh/ArrayItems.hh
Normal file
112
Core/Mesh/ArrayItems.hh
Normal file
@@ -0,0 +1,112 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.1.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_ARRAY_ITEMS_HH
|
||||
#define OPENMESH_ARRAY_ITEMS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||
#include <OpenMesh/Core/Mesh/Handles.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/// Definition of mesh items for use in the ArrayKernel
|
||||
struct ArrayItems
|
||||
{
|
||||
|
||||
//------------------------------------------------------ internal vertex type
|
||||
|
||||
/// The vertex item
|
||||
class Vertex
|
||||
{
|
||||
friend class ArrayKernel;
|
||||
HalfedgeHandle halfedge_handle_;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------- internal halfedge type
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
class Halfedge_without_prev
|
||||
{
|
||||
friend class ArrayKernel;
|
||||
FaceHandle face_handle_;
|
||||
VertexHandle vertex_handle_;
|
||||
HalfedgeHandle next_halfedge_handle_;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
class Halfedge_with_prev : public Halfedge_without_prev
|
||||
{
|
||||
friend class ArrayKernel;
|
||||
HalfedgeHandle prev_halfedge_handle_;
|
||||
};
|
||||
#endif
|
||||
|
||||
//TODO: should be selected with config.h define
|
||||
typedef Halfedge_with_prev Halfedge;
|
||||
typedef GenProg::Bool2Type<true> HasPrevHalfedge;
|
||||
|
||||
//-------------------------------------------------------- internal edge type
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
class Edge
|
||||
{
|
||||
friend class ArrayKernel;
|
||||
Halfedge halfedges_[2];
|
||||
};
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------- internal face type
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
class Face
|
||||
{
|
||||
friend class ArrayKernel;
|
||||
HalfedgeHandle halfedge_handle_;
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_ITEMS_HH defined
|
||||
//=============================================================================
|
||||
297
Core/Mesh/ArrayKernel.cc
Normal file
297
Core/Mesh/ArrayKernel.cc
Normal file
@@ -0,0 +1,297 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2004 by Computer Graphics Group, RWTH Aachen *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* License *
|
||||
* *
|
||||
* This library 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, version 2.1. *
|
||||
* *
|
||||
* This library 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 Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
|
||||
#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()
|
||||
{
|
||||
vertices_.clear();
|
||||
edges_.clear();
|
||||
faces_.clear();
|
||||
|
||||
vprops_resize(0);
|
||||
eprops_resize(0);
|
||||
hprops_resize(0);
|
||||
fprops_resize(0);
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
786
Core/Mesh/ArrayKernel.hh
Normal file
786
Core/Mesh/ArrayKernel.hh
Normal file
@@ -0,0 +1,786 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS ArrayKernel
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_ARRAY_KERNEL_HH
|
||||
#define OPENMESH_ARRAY_KERNEL_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
#include <vector>
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||
|
||||
#include <OpenMesh/Core/Mesh/ArrayItems.hh>
|
||||
#include <OpenMesh/Core/Mesh/BaseKernel.hh>
|
||||
#include <OpenMesh/Core/Mesh/Status.hh>
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
/** \ingroup mesh_kernels_group
|
||||
|
||||
Mesh kernel using arrays for mesh item storage.
|
||||
|
||||
This mesh kernel uses the std::vector as container to store the
|
||||
mesh items. Therefore all handle types are internally represented
|
||||
by integers. To get the index from a handle use the handle's \c
|
||||
idx() method.
|
||||
|
||||
\note For a description of the minimal kernel interface see
|
||||
OpenMesh::Mesh::BaseKernel.
|
||||
\note You do not have to use this class directly, use the predefined
|
||||
mesh-kernel combinations in \ref mesh_types_group.
|
||||
\see OpenMesh::Concepts::KernelT, \ref mesh_type
|
||||
*/
|
||||
|
||||
class ArrayKernel : public BaseKernel, public ArrayItems
|
||||
{
|
||||
public:
|
||||
|
||||
// handles
|
||||
typedef OpenMesh::VertexHandle VertexHandle;
|
||||
typedef OpenMesh::HalfedgeHandle HalfedgeHandle;
|
||||
typedef OpenMesh::EdgeHandle EdgeHandle;
|
||||
typedef OpenMesh::FaceHandle FaceHandle;
|
||||
typedef Attributes::StatusInfo StatusInfo;
|
||||
typedef VPropHandleT<StatusInfo> VertexStatusPropertyHandle;
|
||||
typedef HPropHandleT<StatusInfo> HalfedgeStatusPropertyHandle;
|
||||
typedef EPropHandleT<StatusInfo> EdgeStatusPropertyHandle;
|
||||
typedef FPropHandleT<StatusInfo> FaceStatusPropertyHandle;
|
||||
|
||||
public:
|
||||
|
||||
// --- constructor/destructor ---
|
||||
ArrayKernel();
|
||||
virtual ~ArrayKernel();
|
||||
|
||||
/** ArrayKernel uses the default copy constructor and assignment operator, which means
|
||||
that the connectivity and all properties are copied, including reference
|
||||
counters, allocated bit status masks, etc.. In contrast assign_connectivity
|
||||
copies only the connectivity, i.e. vertices, edges, faces and their status fields.
|
||||
NOTE: The geometry (the points property) is NOT copied. Poly/TriConnectivity
|
||||
override(and hide) that function to provide connectivity consistence.*/
|
||||
void assign_connectivity(const ArrayKernel& _other);
|
||||
|
||||
// --- handle -> item ---
|
||||
VertexHandle handle(const Vertex& _v) const
|
||||
{return VertexHandle(&_v - &vertices_.front()); }
|
||||
|
||||
HalfedgeHandle handle(const Halfedge& _he) const
|
||||
{
|
||||
uint eh(((char*)&edges_.front() - (char*)&_he) % sizeof(Edge));
|
||||
assert((&_he == &edges_[eh].halfedges_[0]) ||
|
||||
(&_he == &edges_[eh].halfedges_[1]));
|
||||
return ((&_he == &edges_[eh].halfedges_[0]) ?
|
||||
HalfedgeHandle(eh<<1) : HalfedgeHandle((eh<<1)+1));
|
||||
}
|
||||
|
||||
EdgeHandle handle(const Edge& _e) const
|
||||
{ return EdgeHandle(&_e - &edges_.front()); }
|
||||
|
||||
FaceHandle handle(const Face& _f) const
|
||||
{ return FaceHandle(&_f - &faces_.front()); }
|
||||
|
||||
#define SIGNED(x) signed( (x) )
|
||||
//checks handle validity - useful for debugging
|
||||
bool is_valid_handle(VertexHandle _vh) const
|
||||
{ return 0 <= _vh.idx() && _vh.idx() < SIGNED(n_vertices()); }
|
||||
|
||||
bool is_valid_handle(HalfedgeHandle _heh) const
|
||||
{ return 0 <= _heh.idx() && _heh.idx() < SIGNED(n_edges()*2); }
|
||||
|
||||
bool is_valid_handle(EdgeHandle _eh) const
|
||||
{ return 0 <= _eh.idx() && _eh.idx() < SIGNED(n_edges()); }
|
||||
|
||||
bool is_valid_handle(FaceHandle _fh) const
|
||||
{ return 0 <= _fh.idx() && _fh.idx() < SIGNED(n_faces()); }
|
||||
|
||||
// --- item -> handle ---
|
||||
const Vertex& vertex(VertexHandle _vh) const
|
||||
{
|
||||
assert(is_valid_handle(_vh));
|
||||
return vertices_[_vh.idx()];
|
||||
}
|
||||
|
||||
Vertex& vertex(VertexHandle _vh)
|
||||
{
|
||||
assert(is_valid_handle(_vh));
|
||||
return vertices_[_vh.idx()];
|
||||
}
|
||||
|
||||
const Halfedge& halfedge(HalfedgeHandle _heh) const
|
||||
{
|
||||
assert(is_valid_handle(_heh));
|
||||
return edges_[_heh.idx() >> 1].halfedges_[_heh.idx() & 1];
|
||||
}
|
||||
|
||||
Halfedge& halfedge(HalfedgeHandle _heh)
|
||||
{
|
||||
assert(is_valid_handle(_heh));
|
||||
return edges_[_heh.idx() >> 1].halfedges_[_heh.idx() & 1];
|
||||
}
|
||||
|
||||
const Edge& edge(EdgeHandle _eh) const
|
||||
{
|
||||
assert(is_valid_handle(_eh));
|
||||
return edges_[_eh.idx()];
|
||||
}
|
||||
|
||||
Edge& edge(EdgeHandle _eh)
|
||||
{
|
||||
assert(is_valid_handle(_eh));
|
||||
return edges_[_eh.idx()];
|
||||
}
|
||||
|
||||
const Face& face(FaceHandle _fh) const
|
||||
{
|
||||
assert(is_valid_handle(_fh));
|
||||
return faces_[_fh.idx()];
|
||||
}
|
||||
|
||||
Face& face(FaceHandle _fh)
|
||||
{
|
||||
assert(is_valid_handle(_fh));
|
||||
return faces_[_fh.idx()];
|
||||
}
|
||||
|
||||
#undef SIGNED
|
||||
|
||||
// --- get i'th items ---
|
||||
|
||||
VertexHandle vertex_handle(uint _i) const
|
||||
{ return (_i < n_vertices()) ? handle( vertices_[_i] ) : VertexHandle(); }
|
||||
|
||||
HalfedgeHandle halfedge_handle(uint _i) const
|
||||
{
|
||||
return (_i < n_halfedges()) ?
|
||||
halfedge_handle(edge_handle(_i/2), _i%2) : HalfedgeHandle();
|
||||
}
|
||||
|
||||
EdgeHandle edge_handle(uint _i) const
|
||||
{ return (_i < n_edges()) ? handle(edges_[_i]) : EdgeHandle(); }
|
||||
|
||||
FaceHandle face_handle(uint _i) const
|
||||
{ return (_i < n_faces()) ? handle(faces_[_i]) : FaceHandle(); }
|
||||
|
||||
public:
|
||||
|
||||
inline VertexHandle new_vertex()
|
||||
{
|
||||
vertices_.push_back(Vertex());
|
||||
vprops_resize(n_vertices());//TODO:should it be push_back()?
|
||||
|
||||
return handle(vertices_.back());
|
||||
}
|
||||
|
||||
inline HalfedgeHandle new_edge(VertexHandle _start_vh, VertexHandle _end_vh)
|
||||
{
|
||||
// assert(_start_vh != _end_vh);
|
||||
edges_.push_back(Edge());
|
||||
eprops_resize(n_edges());//TODO:should it be push_back()?
|
||||
hprops_resize(n_halfedges());//TODO:should it be push_back()?
|
||||
|
||||
EdgeHandle eh(handle(edges_.back()));
|
||||
HalfedgeHandle heh0(halfedge_handle(eh, 0));
|
||||
HalfedgeHandle heh1(halfedge_handle(eh, 1));
|
||||
set_vertex_handle(heh0, _end_vh);
|
||||
set_vertex_handle(heh1, _start_vh);
|
||||
return heh0;
|
||||
}
|
||||
|
||||
inline FaceHandle new_face()
|
||||
{
|
||||
faces_.push_back(Face());
|
||||
fprops_resize(n_faces());
|
||||
return handle(faces_.back());
|
||||
}
|
||||
|
||||
inline FaceHandle new_face(const Face& _f)
|
||||
{
|
||||
faces_.push_back(_f);
|
||||
fprops_resize(n_faces());
|
||||
return handle(faces_.back());
|
||||
}
|
||||
|
||||
public:
|
||||
// --- resize/reserve ---
|
||||
void resize( uint _n_vertices, uint _n_edges, uint _n_faces );
|
||||
void reserve(uint _n_vertices, uint _n_edges, uint _n_faces );
|
||||
|
||||
// --- deletion ---
|
||||
void garbage_collection(bool _v=true, bool _e=true, bool _f=true);
|
||||
void clear();
|
||||
|
||||
// --- number of items ---
|
||||
uint n_vertices() const { return vertices_.size(); }
|
||||
uint n_halfedges() const { return 2*edges_.size(); }
|
||||
uint n_edges() const { return edges_.size(); }
|
||||
uint n_faces() const { return faces_.size(); }
|
||||
|
||||
bool vertices_empty() const { return vertices_.empty(); }
|
||||
bool halfedges_empty() const { return edges_.empty(); }
|
||||
bool edges_empty() const { return edges_.empty(); }
|
||||
bool faces_empty() const { return faces_.empty(); }
|
||||
|
||||
// --- vertex connectivity ---
|
||||
|
||||
HalfedgeHandle halfedge_handle(VertexHandle _vh) const
|
||||
{ return vertex(_vh).halfedge_handle_; }
|
||||
|
||||
void set_halfedge_handle(VertexHandle _vh, HalfedgeHandle _heh)
|
||||
{
|
||||
// assert(is_valid_handle(_heh));
|
||||
vertex(_vh).halfedge_handle_ = _heh;
|
||||
}
|
||||
|
||||
bool is_isolated(VertexHandle _vh) const
|
||||
{ return !halfedge_handle(_vh).is_valid(); }
|
||||
|
||||
void set_isolated(VertexHandle _vh)
|
||||
{ vertex(_vh).halfedge_handle_.invalidate(); }
|
||||
|
||||
uint delete_isolated_vertices();
|
||||
|
||||
// --- halfedge connectivity ---
|
||||
VertexHandle to_vertex_handle(HalfedgeHandle _heh) const
|
||||
{ return halfedge(_heh).vertex_handle_; }
|
||||
|
||||
VertexHandle from_vertex_handle(HalfedgeHandle _heh) const
|
||||
{ return to_vertex_handle(opposite_halfedge_handle(_heh)); }
|
||||
|
||||
void set_vertex_handle(HalfedgeHandle _heh, VertexHandle _vh)
|
||||
{
|
||||
// assert(is_valid_handle(_vh));
|
||||
halfedge(_heh).vertex_handle_ = _vh;
|
||||
}
|
||||
|
||||
FaceHandle face_handle(HalfedgeHandle _heh) const
|
||||
{ return halfedge(_heh).face_handle_; }
|
||||
|
||||
void set_face_handle(HalfedgeHandle _heh, FaceHandle _fh)
|
||||
{
|
||||
// assert(is_valid_handle(_fh));
|
||||
halfedge(_heh).face_handle_ = _fh;
|
||||
}
|
||||
|
||||
void set_boundary(HalfedgeHandle _heh)
|
||||
{ halfedge(_heh).face_handle_.invalidate(); }
|
||||
|
||||
/// Is halfedge _heh a boundary halfedge (is its face handle invalid) ?
|
||||
bool is_boundary(HalfedgeHandle _heh) const
|
||||
{ return !face_handle(_heh).is_valid(); }
|
||||
|
||||
HalfedgeHandle next_halfedge_handle(HalfedgeHandle _heh) const
|
||||
{ return halfedge(_heh).next_halfedge_handle_; }
|
||||
|
||||
void set_next_halfedge_handle(HalfedgeHandle _heh, HalfedgeHandle _nheh)
|
||||
{
|
||||
assert(is_valid_handle(_nheh));
|
||||
// assert(to_vertex_handle(_heh) == from_vertex_handle(_nheh));
|
||||
halfedge(_heh).next_halfedge_handle_ = _nheh;
|
||||
set_prev_halfedge_handle(_nheh, _heh);
|
||||
}
|
||||
|
||||
|
||||
void set_prev_halfedge_handle(HalfedgeHandle _heh, HalfedgeHandle _pheh)
|
||||
{
|
||||
assert(is_valid_handle(_pheh));
|
||||
set_prev_halfedge_handle(_heh, _pheh, HasPrevHalfedge());
|
||||
}
|
||||
|
||||
void set_prev_halfedge_handle(HalfedgeHandle _heh, HalfedgeHandle _pheh,
|
||||
GenProg::True)
|
||||
{ halfedge(_heh).prev_halfedge_handle_ = _pheh; }
|
||||
|
||||
void set_prev_halfedge_handle(HalfedgeHandle /* _heh */, HalfedgeHandle /* _pheh */,
|
||||
GenProg::False)
|
||||
{}
|
||||
|
||||
HalfedgeHandle prev_halfedge_handle(HalfedgeHandle _heh) const
|
||||
{ return prev_halfedge_handle(_heh, HasPrevHalfedge() ); }
|
||||
|
||||
HalfedgeHandle prev_halfedge_handle(HalfedgeHandle _heh, GenProg::True) const
|
||||
{ return halfedge(_heh).prev_halfedge_handle_; }
|
||||
|
||||
HalfedgeHandle prev_halfedge_handle(HalfedgeHandle _heh, GenProg::False) const
|
||||
{
|
||||
if (is_boundary(_heh))
|
||||
{//iterating around the vertex should be faster than iterating the boundary
|
||||
HalfedgeHandle curr_heh(opposite_halfedge_handle(_heh));
|
||||
HalfedgeHandle next_heh(next_halfedge_handle(curr_heh));
|
||||
do
|
||||
{
|
||||
curr_heh = opposite_halfedge_handle(next_heh);
|
||||
next_heh = next_halfedge_handle(curr_heh);
|
||||
}
|
||||
while (next_heh != _heh);
|
||||
return curr_heh;
|
||||
}
|
||||
else
|
||||
{
|
||||
HalfedgeHandle heh(_heh);
|
||||
HalfedgeHandle next_heh(next_halfedge_handle(heh));
|
||||
while (next_heh != _heh) {
|
||||
heh = next_heh;
|
||||
next_heh = next_halfedge_handle(next_heh);
|
||||
}
|
||||
return heh;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HalfedgeHandle opposite_halfedge_handle(HalfedgeHandle _heh) const
|
||||
{ return HalfedgeHandle((_heh.idx() & 1) ? _heh.idx()-1 : _heh.idx()+1); }
|
||||
|
||||
|
||||
HalfedgeHandle ccw_rotated_halfedge_handle(HalfedgeHandle _heh) const
|
||||
{ return opposite_halfedge_handle(prev_halfedge_handle(_heh)); }
|
||||
|
||||
|
||||
HalfedgeHandle cw_rotated_halfedge_handle(HalfedgeHandle _heh) const
|
||||
{ return next_halfedge_handle(opposite_halfedge_handle(_heh)); }
|
||||
|
||||
// --- edge connectivity ---
|
||||
HalfedgeHandle halfedge_handle(EdgeHandle _eh, uint _i) const
|
||||
{
|
||||
assert(_i<=1);
|
||||
return HalfedgeHandle((_eh.idx() << 1) + _i);
|
||||
}
|
||||
|
||||
EdgeHandle edge_handle(HalfedgeHandle _heh) const
|
||||
{ return EdgeHandle(_heh.idx() >> 1); }
|
||||
|
||||
// --- face connectivity ---
|
||||
HalfedgeHandle halfedge_handle(FaceHandle _fh) const
|
||||
{ return face(_fh).halfedge_handle_; }
|
||||
|
||||
void set_halfedge_handle(FaceHandle _fh, HalfedgeHandle _heh)
|
||||
{
|
||||
// assert(is_valid_handle(_heh));
|
||||
face(_fh).halfedge_handle_ = _heh;
|
||||
}
|
||||
|
||||
/// Status Query API
|
||||
//------------------------------------------------------------ vertex status
|
||||
const StatusInfo& status(VertexHandle _vh) const
|
||||
{ return property(vertex_status_, _vh); }
|
||||
|
||||
StatusInfo& status(VertexHandle _vh)
|
||||
{ return property(vertex_status_, _vh); }
|
||||
|
||||
//----------------------------------------------------------- halfedge status
|
||||
const StatusInfo& status(HalfedgeHandle _hh) const
|
||||
{ return property(halfedge_status_, _hh); }
|
||||
|
||||
StatusInfo& status(HalfedgeHandle _hh)
|
||||
{ return property(halfedge_status_, _hh); }
|
||||
|
||||
//--------------------------------------------------------------- edge status
|
||||
const StatusInfo& status(EdgeHandle _eh) const
|
||||
{ return property(edge_status_, _eh); }
|
||||
|
||||
StatusInfo& status(EdgeHandle _eh)
|
||||
{ return property(edge_status_, _eh); }
|
||||
|
||||
//--------------------------------------------------------------- face status
|
||||
const StatusInfo& status(FaceHandle _fh) const
|
||||
{ return property(face_status_, _fh); }
|
||||
|
||||
StatusInfo& status(FaceHandle _fh)
|
||||
{ return property(face_status_, _fh); }
|
||||
|
||||
inline bool has_vertex_status() const
|
||||
{ return vertex_status_.is_valid(); }
|
||||
|
||||
inline bool has_halfedge_status() const
|
||||
{ return halfedge_status_.is_valid(); }
|
||||
|
||||
inline bool has_edge_status() const
|
||||
{ return edge_status_.is_valid(); }
|
||||
|
||||
inline bool has_face_status() const
|
||||
{ return face_status_.is_valid(); }
|
||||
|
||||
inline VertexStatusPropertyHandle vertex_status_pph() const
|
||||
{ return vertex_status_; }
|
||||
|
||||
inline HalfedgeStatusPropertyHandle halfedge_status_pph() const
|
||||
{ return halfedge_status_; }
|
||||
|
||||
inline EdgeStatusPropertyHandle edge_status_pph() const
|
||||
{ return edge_status_; }
|
||||
|
||||
inline FaceStatusPropertyHandle face_status_pph() const
|
||||
{ return face_status_; }
|
||||
|
||||
/// status property by handle
|
||||
inline VertexStatusPropertyHandle status_pph(VertexHandle /*_hnd*/) const
|
||||
{ return vertex_status_pph(); }
|
||||
|
||||
inline HalfedgeStatusPropertyHandle status_pph(HalfedgeHandle /*_hnd*/) const
|
||||
{ return halfedge_status_pph(); }
|
||||
|
||||
inline EdgeStatusPropertyHandle status_pph(EdgeHandle /*_hnd*/) const
|
||||
{ return edge_status_pph(); }
|
||||
|
||||
inline FaceStatusPropertyHandle status_pph(FaceHandle /*_hnd*/) const
|
||||
{ return face_status_pph(); }
|
||||
|
||||
/// Status Request API
|
||||
void request_vertex_status()
|
||||
{
|
||||
if (!refcount_vstatus_++)
|
||||
add_property( vertex_status_, "v:status" );
|
||||
}
|
||||
|
||||
void request_halfedge_status()
|
||||
{
|
||||
if (!refcount_hstatus_++)
|
||||
add_property( halfedge_status_, "h:status" );
|
||||
}
|
||||
|
||||
void request_edge_status()
|
||||
{
|
||||
if (!refcount_estatus_++)
|
||||
add_property( edge_status_, "e:status" );
|
||||
}
|
||||
|
||||
void request_face_status()
|
||||
{
|
||||
if (!refcount_fstatus_++)
|
||||
add_property( face_status_, "f:status" );
|
||||
}
|
||||
|
||||
/// Status Release API
|
||||
void release_vertex_status()
|
||||
{
|
||||
if ((refcount_vstatus_ > 0) && (! --refcount_vstatus_))
|
||||
remove_property(vertex_status_);
|
||||
}
|
||||
|
||||
void release_halfedge_status()
|
||||
{
|
||||
if ((refcount_hstatus_ > 0) && (! --refcount_hstatus_))
|
||||
remove_property(halfedge_status_);
|
||||
}
|
||||
|
||||
void release_edge_status()
|
||||
{
|
||||
if ((refcount_estatus_ > 0) && (! --refcount_estatus_))
|
||||
remove_property(edge_status_);
|
||||
}
|
||||
|
||||
void release_face_status()
|
||||
{
|
||||
if ((refcount_fstatus_ > 0) && (! --refcount_fstatus_))
|
||||
remove_property(face_status_);
|
||||
}
|
||||
|
||||
/// --- StatusSet API ---
|
||||
|
||||
template <class Handle>
|
||||
class StatusSetT
|
||||
{
|
||||
protected:
|
||||
ArrayKernel& kernel_;
|
||||
|
||||
public:
|
||||
const uint bit_mask_;
|
||||
|
||||
public:
|
||||
StatusSetT(ArrayKernel& _kernel, uint _bit_mask)
|
||||
: kernel_(_kernel), bit_mask_(_bit_mask)
|
||||
{}
|
||||
|
||||
~StatusSetT()
|
||||
{}
|
||||
|
||||
inline bool is_in(Handle _hnd) const
|
||||
{ return kernel_.status(_hnd).is_bit_set(bit_mask_); }
|
||||
|
||||
inline void insert(Handle _hnd)
|
||||
{ return kernel_.status(_hnd).set_bit(bit_mask_); }
|
||||
|
||||
inline void erase(Handle _hnd)
|
||||
{ return kernel_.status(_hnd).unset_bit(bit_mask_); }
|
||||
|
||||
/// Note: 0(n) complexity
|
||||
uint size() const
|
||||
{
|
||||
uint n_elements = kernel_.status_pph(Handle()).is_valid() ?
|
||||
kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0;
|
||||
uint sz = 0;
|
||||
for (uint i = 0; i < n_elements; ++i)
|
||||
{
|
||||
sz += (uint)is_in(Handle(i));
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
/// Note: O(n) complexity
|
||||
void clear()
|
||||
{
|
||||
uint n_elements = kernel_.status_pph(Handle()).is_valid() ?
|
||||
kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0;
|
||||
for (uint i = 0; i < n_elements; ++i)
|
||||
{
|
||||
erase(Handle(i));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
friend class StatusSetT<VertexHandle>;
|
||||
friend class StatusSetT<EdgeHandle>;
|
||||
friend class StatusSetT<FaceHandle>;
|
||||
friend class StatusSetT<HalfedgeHandle>;
|
||||
|
||||
/// --- AutoStatusSet API ---
|
||||
|
||||
template <class Handle>
|
||||
class AutoStatusSetT : public StatusSetT<Handle>
|
||||
{
|
||||
private:
|
||||
typedef StatusSetT<Handle> Base;
|
||||
public:
|
||||
AutoStatusSetT(ArrayKernel& _kernel)
|
||||
: StatusSetT<Handle>(_kernel, _kernel.pop_bit_mask(Handle()))
|
||||
{ /*assert(size() == 0);*/ } //the set should be empty on creation
|
||||
|
||||
~AutoStatusSetT()
|
||||
{
|
||||
//assert(size() == 0);//the set should be empty on leave?
|
||||
Base::kernel_.push_bit_mask(Handle(), Base::bit_mask_);
|
||||
}
|
||||
};
|
||||
|
||||
friend class AutoStatusSetT<VertexHandle>;
|
||||
friend class AutoStatusSetT<EdgeHandle>;
|
||||
friend class AutoStatusSetT<FaceHandle>;
|
||||
friend class AutoStatusSetT<HalfedgeHandle>;
|
||||
|
||||
typedef AutoStatusSetT<VertexHandle> VertexStatusSet;
|
||||
typedef AutoStatusSetT<EdgeHandle> EdgeStatusSet;
|
||||
typedef AutoStatusSetT<FaceHandle> FaceStatusSet;
|
||||
typedef AutoStatusSetT<HalfedgeHandle> HalfedgeStatusSet;
|
||||
|
||||
/// --- ExtStatusSet API --- (hybrid between a set and an array)
|
||||
|
||||
template <class Handle>
|
||||
class ExtStatusSetT : public AutoStatusSetT<Handle>
|
||||
{
|
||||
public:
|
||||
typedef AutoStatusSetT<Handle> Base;
|
||||
|
||||
protected:
|
||||
typedef std::vector<Handle> HandleContainer;
|
||||
HandleContainer handles_;
|
||||
|
||||
public:
|
||||
typedef typename HandleContainer::iterator
|
||||
iterator;
|
||||
typedef typename HandleContainer::const_iterator
|
||||
const_iterator;
|
||||
public:
|
||||
ExtStatusSetT(ArrayKernel& _kernel, uint _capacity_hint = 0)
|
||||
: Base(_kernel)
|
||||
{ handles_.reserve(_capacity_hint); }
|
||||
|
||||
~ExtStatusSetT()
|
||||
{ clear(); }
|
||||
|
||||
//set API
|
||||
// Complexity: O(1)
|
||||
inline void insert(Handle _hnd)
|
||||
{
|
||||
if (!is_in(_hnd))
|
||||
{
|
||||
Base::insert(_hnd);
|
||||
handles_.push_back(_hnd);
|
||||
}
|
||||
}
|
||||
|
||||
// Complexity: O(k), (k - number of the elements in the set)
|
||||
inline void erase(Handle _hnd)
|
||||
{
|
||||
if (is_in(_hnd))
|
||||
{
|
||||
iterator it = std::find(begin(), end(), _hnd);
|
||||
erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Complexity: O(1)
|
||||
inline void erase(iterator _it)
|
||||
{
|
||||
assert(_it != end() && is_in(*_it));
|
||||
clear(*_it);
|
||||
*_it = handles_.back();
|
||||
*_it.pop_back();
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
for (iterator it = begin(); it != end(); ++it)
|
||||
{
|
||||
assert(is_in(*it));
|
||||
Base::erase(*it);
|
||||
}
|
||||
handles_.clear();
|
||||
}
|
||||
|
||||
/// Complexity: 0(1)
|
||||
inline uint size() const
|
||||
{ return handles_.size(); }
|
||||
inline bool empty() const
|
||||
{ return handles_.empty(); }
|
||||
|
||||
//Vector API
|
||||
inline iterator begin()
|
||||
{ return handles_.begin(); }
|
||||
inline const_iterator begin() const
|
||||
{ return handles_.begin(); }
|
||||
|
||||
inline iterator end()
|
||||
{ return handles_.end(); }
|
||||
inline const_iterator end() const
|
||||
{ return handles_.end(); }
|
||||
|
||||
inline Handle& front()
|
||||
{ return handles_.front(); }
|
||||
inline const Handle& front() const
|
||||
{ return handles_.front(); }
|
||||
|
||||
inline Handle& back()
|
||||
{ return handles_.back(); }
|
||||
inline const Handle& back() const
|
||||
{ return handles_.back(); }
|
||||
};
|
||||
|
||||
typedef ExtStatusSetT<FaceHandle> ExtFaceStatusSet;
|
||||
typedef ExtStatusSetT<VertexHandle> ExtVertexStatusSet;
|
||||
typedef ExtStatusSetT<EdgeHandle> ExtEdgeStatusSet;
|
||||
typedef ExtStatusSetT<HalfedgeHandle> ExtHalfedgeStatusSet;
|
||||
|
||||
private:
|
||||
// iterators
|
||||
typedef std::vector<Vertex> VertexContainer;
|
||||
typedef std::vector<Edge> EdgeContainer;
|
||||
typedef std::vector<Face> FaceContainer;
|
||||
typedef VertexContainer::iterator KernelVertexIter;
|
||||
typedef VertexContainer::const_iterator KernelConstVertexIter;
|
||||
typedef EdgeContainer::iterator KernelEdgeIter;
|
||||
typedef EdgeContainer::const_iterator KernelConstEdgeIter;
|
||||
typedef FaceContainer::iterator KernelFaceIter;
|
||||
typedef FaceContainer::const_iterator KernelConstFaceIter;
|
||||
typedef std::vector<uint> BitMaskContainer;
|
||||
|
||||
|
||||
KernelVertexIter vertices_begin() { return vertices_.begin(); }
|
||||
KernelConstVertexIter vertices_begin() const { return vertices_.begin(); }
|
||||
KernelVertexIter vertices_end() { return vertices_.end(); }
|
||||
KernelConstVertexIter vertices_end() const { return vertices_.end(); }
|
||||
|
||||
KernelEdgeIter edges_begin() { return edges_.begin(); }
|
||||
KernelConstEdgeIter edges_begin() const { return edges_.begin(); }
|
||||
KernelEdgeIter edges_end() { return edges_.end(); }
|
||||
KernelConstEdgeIter edges_end() const { return edges_.end(); }
|
||||
|
||||
KernelFaceIter faces_begin() { return faces_.begin(); }
|
||||
KernelConstFaceIter faces_begin() const { return faces_.begin(); }
|
||||
KernelFaceIter faces_end() { return faces_.end(); }
|
||||
KernelConstFaceIter faces_end() const { return faces_.end(); }
|
||||
|
||||
/// bit mask container by handle
|
||||
inline BitMaskContainer& bit_masks(VertexHandle /*_dummy_hnd*/)
|
||||
{ return vertex_bit_masks_; }
|
||||
inline BitMaskContainer& bit_masks(EdgeHandle /*_dummy_hnd*/)
|
||||
{ return edge_bit_masks_; }
|
||||
inline BitMaskContainer& bit_masks(FaceHandle /*_dummy_hnd*/)
|
||||
{ return face_bit_masks_; }
|
||||
inline BitMaskContainer& bit_masks(HalfedgeHandle /*_dummy_hnd*/)
|
||||
{ return halfedge_bit_masks_; }
|
||||
|
||||
template <class Handle>
|
||||
uint pop_bit_mask(Handle _hnd)
|
||||
{
|
||||
assert(!bit_masks(_hnd).empty());//check if the client request too many status sets
|
||||
uint bit_mask = bit_masks(_hnd).back();
|
||||
bit_masks(_hnd).pop_back();
|
||||
return bit_mask;
|
||||
}
|
||||
|
||||
template <class Handle>
|
||||
void push_bit_mask(Handle _hnd, uint _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).push_back(_bit_mask);
|
||||
}
|
||||
|
||||
void init_bit_masks(BitMaskContainer& _bmc);
|
||||
void init_bit_masks();
|
||||
|
||||
private:
|
||||
VertexContainer vertices_;
|
||||
EdgeContainer edges_;
|
||||
FaceContainer faces_;
|
||||
|
||||
VertexStatusPropertyHandle vertex_status_;
|
||||
HalfedgeStatusPropertyHandle halfedge_status_;
|
||||
EdgeStatusPropertyHandle edge_status_;
|
||||
FaceStatusPropertyHandle face_status_;
|
||||
|
||||
uint refcount_vstatus_;
|
||||
uint refcount_hstatus_;
|
||||
uint refcount_estatus_;
|
||||
uint refcount_fstatus_;
|
||||
|
||||
BitMaskContainer halfedge_bit_masks_;
|
||||
BitMaskContainer edge_bit_masks_;
|
||||
BitMaskContainer vertex_bit_masks_;
|
||||
BitMaskContainer face_bit_masks_;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_ARRAY_KERNEL_HH defined
|
||||
//=============================================================================
|
||||
651
Core/Mesh/AttribKernelT.hh
Normal file
651
Core/Mesh/AttribKernelT.hh
Normal file
@@ -0,0 +1,651 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2001-2003 by Computer Graphics Group, RWTH Aachen *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* License *
|
||||
* *
|
||||
* This library 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, version 2.1. *
|
||||
* *
|
||||
* This library 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 Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
|
||||
#ifndef OPENMESH_ATTRIBKERNEL_HH
|
||||
#define OPENMESH_ATTRIBKERNEL_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/Mesh/Attributes.hh>
|
||||
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||
#include <OpenMesh/Core/Utils/vector_traits.hh>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/// This class adds the standard properties to the mesh type.
|
||||
///
|
||||
/// The attribute kernel adds all standard properties to the kernel. Therefore
|
||||
/// the functions/types defined here provide a subset of the kernel
|
||||
/// interface as described in Concepts::KernelT.
|
||||
///
|
||||
/// \see Concepts::KernelT
|
||||
template <class MeshItems, class Connectivity>
|
||||
class AttribKernelT : public Connectivity
|
||||
{
|
||||
public:
|
||||
|
||||
//---------------------------------------------------------------- item types
|
||||
|
||||
typedef typename Connectivity::Vertex Vertex;
|
||||
typedef typename Connectivity::Halfedge Halfedge;
|
||||
typedef typename Connectivity::Edge Edge;
|
||||
typedef typename Connectivity::Face Face;
|
||||
|
||||
typedef typename MeshItems::Point Point;
|
||||
typedef typename MeshItems::Normal Normal;
|
||||
typedef typename MeshItems::Color Color;
|
||||
typedef typename MeshItems::TexCoord1D TexCoord1D;
|
||||
typedef typename MeshItems::TexCoord2D TexCoord2D;
|
||||
typedef typename MeshItems::TexCoord3D TexCoord3D;
|
||||
typedef typename MeshItems::Scalar Scalar;
|
||||
typedef typename MeshItems::TextureIndex TextureIndex;
|
||||
|
||||
typedef typename MeshItems::VertexData VertexData;
|
||||
typedef typename MeshItems::HalfedgeData HalfedgeData;
|
||||
typedef typename MeshItems::EdgeData EdgeData;
|
||||
typedef typename MeshItems::FaceData FaceData;
|
||||
|
||||
typedef AttribKernelT<MeshItems,Connectivity> AttribKernel;
|
||||
|
||||
enum Attribs {
|
||||
VAttribs = MeshItems::VAttribs,
|
||||
HAttribs = MeshItems::HAttribs,
|
||||
EAttribs = MeshItems::EAttribs,
|
||||
FAttribs = MeshItems::FAttribs,
|
||||
};
|
||||
|
||||
typedef VPropHandleT<VertexData> DataVPropHandle;
|
||||
typedef HPropHandleT<HalfedgeData> DataHPropHandle;
|
||||
typedef EPropHandleT<EdgeData> DataEPropHandle;
|
||||
typedef FPropHandleT<FaceData> DataFPropHandle;
|
||||
|
||||
public:
|
||||
|
||||
//-------------------------------------------------- constructor / destructor
|
||||
|
||||
AttribKernelT()
|
||||
: refcount_vnormals_(0),
|
||||
refcount_vcolors_(0),
|
||||
refcount_vtexcoords1D_(0),
|
||||
refcount_vtexcoords2D_(0),
|
||||
refcount_vtexcoords3D_(0),
|
||||
refcount_htexcoords1D_(0),
|
||||
refcount_htexcoords2D_(0),
|
||||
refcount_htexcoords3D_(0),
|
||||
refcount_fnormals_(0),
|
||||
refcount_fcolors_(0),
|
||||
refcount_ftextureIndex_(0)
|
||||
{
|
||||
add_property( points_, "v:points" );
|
||||
|
||||
if (VAttribs & Attributes::Normal)
|
||||
request_vertex_normals();
|
||||
|
||||
if (VAttribs & Attributes::Color)
|
||||
request_vertex_colors();
|
||||
|
||||
if (VAttribs & Attributes::TexCoord1D)
|
||||
request_vertex_texcoords1D();
|
||||
|
||||
if (VAttribs & Attributes::TexCoord2D)
|
||||
request_vertex_texcoords2D();
|
||||
|
||||
if (VAttribs & Attributes::TexCoord3D)
|
||||
request_vertex_texcoords3D();
|
||||
|
||||
if (HAttribs & Attributes::TexCoord1D)
|
||||
request_halfedge_texcoords1D();
|
||||
|
||||
if (HAttribs & Attributes::TexCoord2D)
|
||||
request_halfedge_texcoords2D();
|
||||
|
||||
if (HAttribs & Attributes::TexCoord3D)
|
||||
request_halfedge_texcoords3D();
|
||||
|
||||
if (VAttribs & Attributes::Status)
|
||||
Connectivity::request_vertex_status();
|
||||
|
||||
if (HAttribs & Attributes::Status)
|
||||
Connectivity::request_halfedge_status();
|
||||
|
||||
if (EAttribs & Attributes::Status)
|
||||
Connectivity::request_edge_status();
|
||||
|
||||
if (FAttribs & Attributes::Normal)
|
||||
request_face_normals();
|
||||
|
||||
if (FAttribs & Attributes::Color)
|
||||
request_face_colors();
|
||||
|
||||
if (FAttribs & Attributes::Status)
|
||||
Connectivity::request_face_status();
|
||||
|
||||
if (FAttribs & Attributes::TextureIndex)
|
||||
request_face_texture_index();
|
||||
|
||||
//FIXME: data properties might actually cost storage even
|
||||
//if there are no data traits??
|
||||
add_property(data_vpph_);
|
||||
add_property(data_fpph_);
|
||||
add_property(data_hpph_);
|
||||
add_property(data_epph_);
|
||||
}
|
||||
|
||||
virtual ~AttribKernelT()
|
||||
{
|
||||
// should remove properties, but this will be done in
|
||||
// BaseKernel's destructor anyway...
|
||||
}
|
||||
|
||||
// Martin: This below does not make any sense, right?
|
||||
// -------------------------------------------------------- copy & assignment
|
||||
// AttribKernelT(const AttribKernelT& _rhs)
|
||||
// : BaseKernel(_rhs)
|
||||
// { operator=(_rhs); }
|
||||
//
|
||||
// AttribKernelT& operator=(const AttribKernelT& _rhs)
|
||||
// {
|
||||
// // remove old properties
|
||||
// remove_property(points_);
|
||||
// remove_property(vertex_normals_);
|
||||
// remove_property(vertex_colors_);
|
||||
// remove_property(vertex_texcoords_);
|
||||
// remove_property(vertex_status_);
|
||||
// remove_property(halfedge_status_);
|
||||
// remove_property(edge_status_);
|
||||
// remove_property(face_normals_);
|
||||
// remove_property(face_colors_);
|
||||
// remove_property(face_status_);
|
||||
//
|
||||
// // parent deep-copies properties
|
||||
// BaseKernel::operator=(_rhs);
|
||||
//
|
||||
// // copy property handles
|
||||
// points_ = _rhs.points_;
|
||||
// vertex_normals_ = _rhs.vertex_normals_;
|
||||
// vertex_colors_ = _rhs.vertex_colors_;
|
||||
// vertex_texcoords_ = _rhs.vertex_texcoords_;
|
||||
// vertex_status_ = _rhs.vertex_status_;
|
||||
// halfedge_status_ = _rhs.halfedge_status_;
|
||||
// edge_status_ = _rhs.edge_status_;
|
||||
// face_normals_ = _rhs.face_normals_;
|
||||
// face_colors_ = _rhs.face_colors_;
|
||||
// face_status_ = _rhs.face_status_;
|
||||
//
|
||||
// // copy ref-counts
|
||||
// refcount_vnormals_ = _rhs.refcount_vnormals_;
|
||||
// refcount_vcolors_ = _rhs.refcount_vcolors_;
|
||||
// refcount_vtexcoords_ = _rhs.refcount_vtexcoords_;
|
||||
// refcount_vstatus_ = _rhs.refcount_vstatus_;
|
||||
// refcount_hstatus_ = _rhs.refcount_hstatus_;
|
||||
// refcount_estatus_ = _rhs.refcount_estatus_;
|
||||
// refcount_fnormals_ = _rhs.refcount_fnormals_;
|
||||
// refcount_fcolors_ = _rhs.refcount_fcolors_;
|
||||
// refcount_fstatus_ = _rhs.refcount_fstatus_;
|
||||
//
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
/** Assignment from another mesh of \em another type.
|
||||
\note All that's copied is connectivity and vertex positions.
|
||||
All other information (like e.g. attributes or additional
|
||||
elements from traits classes) is not copied.
|
||||
\note If you want to copy all information, including *custom* properties,
|
||||
use PolyMeshT::operator=() instead.
|
||||
TODO: version which copies standard properties specified by the user
|
||||
*/
|
||||
template <class _AttribKernel>
|
||||
void assign(const _AttribKernel& _other)
|
||||
{
|
||||
assign_connectivity(_other);
|
||||
for (typename Connectivity::VertexIter v_it = Connectivity::vertices_begin();
|
||||
v_it != Connectivity::vertices_end(); ++v_it)
|
||||
{//assumes Point constructor supports cast from _AttribKernel::Point
|
||||
set_point(v_it, (Point)_other.point(v_it));
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------- points
|
||||
|
||||
const Point* points() const
|
||||
{ return property(points_).data(); }
|
||||
|
||||
const Point& point(VertexHandle _vh) const
|
||||
{ return property(points_, _vh); }
|
||||
|
||||
Point& point(VertexHandle _vh)
|
||||
{ return property(points_, _vh); }
|
||||
|
||||
void set_point(VertexHandle _vh, const Point& _p)
|
||||
{ property(points_, _vh) = _p; }
|
||||
|
||||
|
||||
//------------------------------------------------------------ vertex normals
|
||||
|
||||
const Normal* vertex_normals() const
|
||||
{ return property(vertex_normals_).data(); }
|
||||
|
||||
const Normal& normal(VertexHandle _vh) const
|
||||
{ return property(vertex_normals_, _vh); }
|
||||
|
||||
void set_normal(VertexHandle _vh, const Normal& _n)
|
||||
{ property(vertex_normals_, _vh) = _n; }
|
||||
|
||||
|
||||
//------------------------------------------------------------- vertex colors
|
||||
|
||||
const Color* vertex_colors() const
|
||||
{ return property(vertex_colors_).data(); }
|
||||
|
||||
const Color& color(VertexHandle _vh) const
|
||||
{ return property(vertex_colors_, _vh); }
|
||||
|
||||
void set_color(VertexHandle _vh, const Color& _c)
|
||||
{ property(vertex_colors_, _vh) = _c; }
|
||||
|
||||
|
||||
//------------------------------------------------------- vertex 1D texcoords
|
||||
|
||||
const TexCoord1D* texcoords1D() const {
|
||||
return property(vertex_texcoords1D_).data();
|
||||
}
|
||||
|
||||
const TexCoord1D& texcoord1D(VertexHandle _vh) const {
|
||||
return property(vertex_texcoords1D_, _vh);
|
||||
}
|
||||
|
||||
void set_texcoord1D(VertexHandle _vh, const TexCoord1D& _t) {
|
||||
property(vertex_texcoords1D_, _vh) = _t;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------- vertex 2D texcoords
|
||||
|
||||
const TexCoord2D* texcoords2D() const {
|
||||
return property(vertex_texcoords2D_).data();
|
||||
}
|
||||
|
||||
const TexCoord2D& texcoord2D(VertexHandle _vh) const {
|
||||
return property(vertex_texcoords2D_, _vh);
|
||||
}
|
||||
|
||||
void set_texcoord2D(VertexHandle _vh, const TexCoord2D& _t) {
|
||||
property(vertex_texcoords2D_, _vh) = _t;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------- vertex 3D texcoords
|
||||
|
||||
const TexCoord3D* texcoords3D() const {
|
||||
return property(vertex_texcoords3D_).data();
|
||||
}
|
||||
|
||||
const TexCoord3D& texcoord3D(VertexHandle _vh) const {
|
||||
return property(vertex_texcoords3D_, _vh);
|
||||
}
|
||||
|
||||
void set_texcoord3D(VertexHandle _vh, const TexCoord3D& _t) {
|
||||
property(vertex_texcoords3D_, _vh) = _t;
|
||||
}
|
||||
|
||||
//.------------------------------------------------------ halfedge 1D texcoords
|
||||
|
||||
const TexCoord1D* htexcoords1D() const {
|
||||
return property(halfedge_texcoords1D_).data();
|
||||
}
|
||||
|
||||
const TexCoord1D& texcoord1D(HalfedgeHandle _heh) const {
|
||||
return property(halfedge_texcoords1D_, _heh);
|
||||
}
|
||||
|
||||
void set_texcoord1D(HalfedgeHandle _heh, const TexCoord1D& _t) {
|
||||
property(halfedge_texcoords1D_, _heh) = _t;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------- halfedge 2D texcoords
|
||||
|
||||
const TexCoord2D* htexcoords2D() const {
|
||||
return property(halfedge_texcoords2D_).data();
|
||||
}
|
||||
|
||||
const TexCoord2D& texcoord2D(HalfedgeHandle _heh) const {
|
||||
return property(halfedge_texcoords2D_, _heh);
|
||||
}
|
||||
|
||||
void set_texcoord2D(HalfedgeHandle _heh, const TexCoord2D& _t) {
|
||||
property(halfedge_texcoords2D_, _heh) = _t;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------- halfedge 3D texcoords
|
||||
|
||||
const TexCoord3D* htexcoords3D() const {
|
||||
return property(halfedge_texcoords3D_).data();
|
||||
}
|
||||
|
||||
const TexCoord3D& texcoord3D(HalfedgeHandle _heh) const {
|
||||
return property(halfedge_texcoords3D_, _heh);
|
||||
}
|
||||
|
||||
void set_texcoord3D(HalfedgeHandle _heh, const TexCoord3D& _t) {
|
||||
property(halfedge_texcoords3D_, _heh) = _t;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------- face normals
|
||||
|
||||
const Normal& normal(FaceHandle _fh) const
|
||||
{ return property(face_normals_, _fh); }
|
||||
|
||||
void set_normal(FaceHandle _fh, const Normal& _n)
|
||||
{ property(face_normals_, _fh) = _n; }
|
||||
|
||||
//-------------------------------------------------------------- per Face Texture index
|
||||
|
||||
const TextureIndex& texture_index(FaceHandle _fh) const
|
||||
{ return property(face_texture_index_, _fh); }
|
||||
|
||||
void set_texture_index(FaceHandle _fh, const TextureIndex& _t)
|
||||
{ property(face_texture_index_, _fh) = _t; }
|
||||
|
||||
//--------------------------------------------------------------- face colors
|
||||
|
||||
const Color& color(FaceHandle _fh) const
|
||||
{ return property(face_colors_, _fh); }
|
||||
|
||||
void set_color(FaceHandle _fh, const Color& _c)
|
||||
{ property(face_colors_, _fh) = _c; }
|
||||
|
||||
//------------------------------------------------ request / alloc properties
|
||||
|
||||
void request_vertex_normals()
|
||||
{
|
||||
if (!refcount_vnormals_++)
|
||||
add_property( vertex_normals_, "v:normals" );
|
||||
}
|
||||
|
||||
void request_vertex_colors()
|
||||
{
|
||||
if (!refcount_vcolors_++)
|
||||
add_property( vertex_colors_, "v:colors" );
|
||||
}
|
||||
|
||||
void request_vertex_texcoords1D()
|
||||
{
|
||||
if (!refcount_vtexcoords1D_++)
|
||||
add_property( vertex_texcoords1D_, "v:texcoords1D" );
|
||||
}
|
||||
|
||||
void request_vertex_texcoords2D()
|
||||
{
|
||||
if (!refcount_vtexcoords2D_++)
|
||||
add_property( vertex_texcoords2D_, "v:texcoords2D" );
|
||||
}
|
||||
|
||||
void request_vertex_texcoords3D()
|
||||
{
|
||||
if (!refcount_vtexcoords3D_++)
|
||||
add_property( vertex_texcoords3D_, "v:texcoords3D" );
|
||||
}
|
||||
|
||||
void request_halfedge_texcoords1D()
|
||||
{
|
||||
if (!refcount_htexcoords1D_++)
|
||||
add_property( halfedge_texcoords1D_, "h:texcoords1D" );
|
||||
}
|
||||
|
||||
void request_halfedge_texcoords2D()
|
||||
{
|
||||
if (!refcount_htexcoords2D_++)
|
||||
add_property( halfedge_texcoords2D_, "h:texcoords2D" );
|
||||
}
|
||||
|
||||
void request_halfedge_texcoords3D()
|
||||
{
|
||||
if (!refcount_htexcoords3D_++)
|
||||
add_property( halfedge_texcoords3D_, "h:texcoords3D" );
|
||||
}
|
||||
|
||||
void request_face_normals()
|
||||
{
|
||||
if (!refcount_fnormals_++)
|
||||
add_property( face_normals_, "f:normals" );
|
||||
}
|
||||
|
||||
void request_face_colors()
|
||||
{
|
||||
if (!refcount_fcolors_++)
|
||||
add_property( face_colors_, "f:colors" );
|
||||
}
|
||||
|
||||
void request_face_texture_index()
|
||||
{
|
||||
if (!refcount_ftextureIndex_++)
|
||||
add_property( face_texture_index_, "f:textureindex" );
|
||||
}
|
||||
|
||||
//------------------------------------------------- release / free properties
|
||||
|
||||
void release_vertex_normals()
|
||||
{
|
||||
if ((refcount_vnormals_ > 0) && (! --refcount_vnormals_))
|
||||
remove_property(vertex_normals_);
|
||||
}
|
||||
|
||||
void release_vertex_colors()
|
||||
{
|
||||
if ((refcount_vcolors_ > 0) && (! --refcount_vcolors_))
|
||||
remove_property(vertex_colors_);
|
||||
}
|
||||
|
||||
void release_vertex_texcoords1D() {
|
||||
if ((refcount_vtexcoords1D_ > 0) && (! --refcount_vtexcoords1D_))
|
||||
remove_property(vertex_texcoords1D_);
|
||||
}
|
||||
|
||||
void release_vertex_texcoords2D() {
|
||||
if ((refcount_vtexcoords2D_ > 0) && (! --refcount_vtexcoords2D_))
|
||||
remove_property(vertex_texcoords2D_);
|
||||
}
|
||||
|
||||
void release_vertex_texcoords3D() {
|
||||
if ((refcount_vtexcoords3D_ > 0) && (! --refcount_vtexcoords3D_))
|
||||
remove_property(vertex_texcoords3D_);
|
||||
}
|
||||
|
||||
void release_halfedge_texcoords1D() {
|
||||
if ((refcount_htexcoords1D_ > 0) && (! --refcount_htexcoords1D_))
|
||||
remove_property(halfedge_texcoords1D_);
|
||||
}
|
||||
|
||||
void release_halfedge_texcoords2D() {
|
||||
if ((refcount_htexcoords2D_ > 0) && (! --refcount_htexcoords2D_))
|
||||
remove_property(halfedge_texcoords2D_);
|
||||
}
|
||||
|
||||
void release_halfedge_texcoords3D() {
|
||||
if ((refcount_htexcoords3D_ > 0) && (! --refcount_htexcoords3D_))
|
||||
remove_property(halfedge_texcoords3D_);
|
||||
}
|
||||
|
||||
void release_face_normals()
|
||||
{
|
||||
if ((refcount_fnormals_ > 0) && (! --refcount_fnormals_))
|
||||
remove_property(face_normals_);
|
||||
}
|
||||
|
||||
void release_face_colors()
|
||||
{
|
||||
if ((refcount_fcolors_ > 0) && (! --refcount_fcolors_))
|
||||
remove_property(face_colors_);
|
||||
}
|
||||
|
||||
void release_face_texture_index()
|
||||
{
|
||||
if ((refcount_ftextureIndex_ > 0) && (! --refcount_ftextureIndex_))
|
||||
remove_property(face_texture_index_);
|
||||
}
|
||||
|
||||
//---------------------------------------------- dynamic check for properties
|
||||
|
||||
bool has_vertex_normals() const { return vertex_normals_.is_valid(); }
|
||||
bool has_vertex_colors() const { return vertex_colors_.is_valid(); }
|
||||
bool has_vertex_texcoords1D() const { return vertex_texcoords1D_.is_valid(); }
|
||||
bool has_vertex_texcoords2D() const { return vertex_texcoords2D_.is_valid(); }
|
||||
bool has_vertex_texcoords3D() const { return vertex_texcoords3D_.is_valid(); }
|
||||
bool has_halfedge_texcoords1D() const { return halfedge_texcoords1D_.is_valid();}
|
||||
bool has_halfedge_texcoords2D() const { return halfedge_texcoords2D_.is_valid();}
|
||||
bool has_halfedge_texcoords3D() const { return halfedge_texcoords3D_.is_valid();}
|
||||
bool has_face_normals() const { return face_normals_.is_valid(); }
|
||||
bool has_face_colors() const { return face_colors_.is_valid(); }
|
||||
bool has_face_texture_index() const { return face_texture_index_.is_valid(); }
|
||||
|
||||
public:
|
||||
|
||||
typedef VPropHandleT<Point> PointsPropertyHandle;
|
||||
typedef VPropHandleT<Normal> VertexNormalsPropertyHandle;
|
||||
typedef VPropHandleT<Color> VertexColorsPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord1D> VertexTexCoords1DPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord2D> VertexTexCoords2DPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord3D> VertexTexCoords3DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord1D> HalfedgeTexCoords1DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord2D> HalfedgeTexCoords2DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord3D> HalfedgeTexCoords3DPropertyHandle;
|
||||
typedef FPropHandleT<Normal> FaceNormalsPropertyHandle;
|
||||
typedef FPropHandleT<Color> FaceColorsPropertyHandle;
|
||||
typedef FPropHandleT<TextureIndex> FaceTextureIndexPropertyHandle;
|
||||
|
||||
public:
|
||||
//standard vertex properties
|
||||
PointsPropertyHandle points_pph() const
|
||||
{ return points_; }
|
||||
|
||||
VertexNormalsPropertyHandle vertex_normals_pph() const
|
||||
{ return vertex_normals_; }
|
||||
|
||||
VertexColorsPropertyHandle vertex_colors_pph() const
|
||||
{ return vertex_colors_; }
|
||||
|
||||
VertexTexCoords1DPropertyHandle vertex_texcoords1D_pph() const
|
||||
{ return vertex_texcoords1D_; }
|
||||
|
||||
VertexTexCoords2DPropertyHandle vertex_texcoords2D_pph() const
|
||||
{ return vertex_texcoords2D_; }
|
||||
|
||||
VertexTexCoords3DPropertyHandle vertex_texcoords3D_pph() const
|
||||
{ return vertex_texcoords3D_; }
|
||||
|
||||
//standard halfedge properties
|
||||
HalfedgeTexCoords1DPropertyHandle halfedge_texcoords1D_pph() const
|
||||
{ return halfedge_texcoords1D_; }
|
||||
|
||||
HalfedgeTexCoords2DPropertyHandle halfedge_texcoords2D_pph() const
|
||||
{ return halfedge_texcoords2D_; }
|
||||
|
||||
HalfedgeTexCoords3DPropertyHandle halfedge_texcoords3D_pph() const
|
||||
{ return halfedge_texcoords3D_; }
|
||||
|
||||
//standard face properties
|
||||
FaceNormalsPropertyHandle face_normals_pph() const
|
||||
{ return face_normals_; }
|
||||
|
||||
FaceColorsPropertyHandle face_colors_pph() const
|
||||
{ return face_colors_; }
|
||||
|
||||
FaceTextureIndexPropertyHandle face_texture_index_pph() const
|
||||
{ return face_texture_index_; }
|
||||
|
||||
VertexData& data(VertexHandle _vh)
|
||||
{ return property(data_vpph_, _vh); }
|
||||
|
||||
const VertexData& data(VertexHandle _vh) const
|
||||
{ return property(data_vpph_, _vh); }
|
||||
|
||||
FaceData& data(FaceHandle _fh)
|
||||
{ return property(data_fpph_, _fh); }
|
||||
|
||||
const FaceData& data(FaceHandle _fh) const
|
||||
{ return property(data_fpph_, _fh); }
|
||||
|
||||
EdgeData& data(EdgeHandle _eh)
|
||||
{ return property(data_epph_, _eh); }
|
||||
|
||||
const EdgeData& data(EdgeHandle _eh) const
|
||||
{ return property(data_epph_, _eh); }
|
||||
|
||||
HalfedgeData& data(HalfedgeHandle _heh)
|
||||
{ return property(data_hpph_, _heh); }
|
||||
|
||||
const HalfedgeData& data(HalfedgeHandle _heh) const
|
||||
{ return property(data_hpph_, _heh); }
|
||||
|
||||
private:
|
||||
//standard vertex properties
|
||||
PointsPropertyHandle points_;
|
||||
VertexNormalsPropertyHandle vertex_normals_;
|
||||
VertexColorsPropertyHandle vertex_colors_;
|
||||
VertexTexCoords1DPropertyHandle vertex_texcoords1D_;
|
||||
VertexTexCoords2DPropertyHandle vertex_texcoords2D_;
|
||||
VertexTexCoords3DPropertyHandle vertex_texcoords3D_;
|
||||
//standard halfedge properties
|
||||
HalfedgeTexCoords1DPropertyHandle halfedge_texcoords1D_;
|
||||
HalfedgeTexCoords2DPropertyHandle halfedge_texcoords2D_;
|
||||
HalfedgeTexCoords3DPropertyHandle halfedge_texcoords3D_;
|
||||
//standard face properties
|
||||
FaceNormalsPropertyHandle face_normals_;
|
||||
FaceColorsPropertyHandle face_colors_;
|
||||
FaceTextureIndexPropertyHandle face_texture_index_;
|
||||
//data properties handles
|
||||
DataVPropHandle data_vpph_;
|
||||
DataHPropHandle data_hpph_;
|
||||
DataEPropHandle data_epph_;
|
||||
DataFPropHandle data_fpph_;
|
||||
|
||||
unsigned int refcount_vnormals_;
|
||||
unsigned int refcount_vcolors_;
|
||||
unsigned int refcount_vtexcoords1D_;
|
||||
unsigned int refcount_vtexcoords2D_;
|
||||
unsigned int refcount_vtexcoords3D_;
|
||||
unsigned int refcount_htexcoords1D_;
|
||||
unsigned int refcount_htexcoords2D_;
|
||||
unsigned int refcount_htexcoords3D_;
|
||||
unsigned int refcount_fnormals_;
|
||||
unsigned int refcount_fcolors_;
|
||||
unsigned int refcount_ftextureIndex_;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_ATTRIBKERNEL_HH defined
|
||||
//=============================================================================
|
||||
85
Core/Mesh/Attributes.hh
Normal file
85
Core/Mesh/Attributes.hh
Normal file
@@ -0,0 +1,85 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.1.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 3794 $
|
||||
// $Date: 2008-11-25 19:25:02 +0100 (Di, 25. Nov 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/**
|
||||
\file Attributes.hh
|
||||
This file provides some macros containing attribute usage.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OPENMESH_ATTRIBUTES_HH
|
||||
#define OPENMESH_ATTRIBUTES_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Mesh/Status.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Attributes {
|
||||
|
||||
|
||||
//== CLASS DEFINITION ========================================================
|
||||
|
||||
/** Attribute bits
|
||||
*
|
||||
* Use the bits to define a standard property at compile time using traits.
|
||||
*
|
||||
* \include traits5.cc
|
||||
*
|
||||
* \see \ref mesh_type
|
||||
*/
|
||||
enum AttributeBits
|
||||
{
|
||||
None = 0, ///< Clear all attribute bits
|
||||
Normal = 1, ///< Add normals to mesh item (vertices/faces)
|
||||
Color = 2, ///< Add colors to mesh item (vertices/faces)
|
||||
PrevHalfedge = 4, ///< Add storage for previous halfedge (halfedges). The bit is set by default in the DefaultTraits.
|
||||
Status = 8, ///< Add status to mesh item (all items)
|
||||
TexCoord1D = 16, ///< Add 1D texture coordinates (vertices, halfedges)
|
||||
TexCoord2D = 32, ///< Add 2D texture coordinates (vertices, halfedges)
|
||||
TexCoord3D = 64, ///< Add 3D texture coordinates (vertices, halfedges)
|
||||
TextureIndex = 128 ///< Add texture index (faces)
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace Attributes
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_ATTRIBUTES_HH defined
|
||||
//=============================================================================
|
||||
67
Core/Mesh/BaseKernel.cc
Normal file
67
Core/Mesh/BaseKernel.cc
Normal file
@@ -0,0 +1,67 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2001-2003 by Computer Graphics Group, RWTH Aachen *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* License *
|
||||
* *
|
||||
* This library 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, version 2.1. *
|
||||
* *
|
||||
* This library 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 Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
|
||||
#include <OpenMesh/Core/Mesh/BaseKernel.hh>
|
||||
namespace OpenMesh
|
||||
{
|
||||
|
||||
void BaseKernel::property_stats(std::ostream& _ostr) const
|
||||
{
|
||||
const PropertyContainer::Properties& vps = vprops_.properties();
|
||||
const PropertyContainer::Properties& hps = hprops_.properties();
|
||||
const PropertyContainer::Properties& eps = eprops_.properties();
|
||||
const PropertyContainer::Properties& fps = fprops_.properties();
|
||||
const PropertyContainer::Properties& mps = mprops_.properties();
|
||||
|
||||
PropertyContainer::Properties::const_iterator it;
|
||||
|
||||
_ostr << vprops_.size() << " vprops:\n";
|
||||
for (it=vps.begin(); it!=vps.end(); ++it)
|
||||
{
|
||||
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
|
||||
}
|
||||
_ostr << hprops_.size() << " hprops:\n";
|
||||
for (it=hps.begin(); it!=hps.end(); ++it)
|
||||
{
|
||||
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
|
||||
}
|
||||
_ostr << eprops_.size() << " eprops:\n";
|
||||
for (it=eps.begin(); it!=eps.end(); ++it)
|
||||
{
|
||||
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
|
||||
}
|
||||
_ostr << fprops_.size() << " fprops:\n";
|
||||
for (it=fps.begin(); it!=fps.end(); ++it)
|
||||
{
|
||||
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
|
||||
}
|
||||
_ostr << mprops_.size() << " mprops:\n";
|
||||
for (it=mps.begin(); it!=mps.end(); ++it)
|
||||
{
|
||||
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
568
Core/Mesh/BaseKernel.hh
Normal file
568
Core/Mesh/BaseKernel.hh
Normal file
@@ -0,0 +1,568 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS BaseKernel
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_BASE_KERNEL_HH
|
||||
#define OPENMESH_BASE_KERNEL_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
// --------------------
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
// --------------------
|
||||
#include <OpenMesh/Core/Utils/PropertyContainer.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/// This class provides the basic property management like adding/removing
|
||||
/// properties and access to properties.
|
||||
/// All operations provided by %BaseKernel need at least a property handle
|
||||
/// (VPropHandleT, EPropHandleT, HPropHandleT, FPropHandleT, MPropHandleT).
|
||||
/// which keeps the data type of the property, too.
|
||||
///
|
||||
/// There are two types of properties:
|
||||
/// -# Standard properties - mesh data (e.g. vertex normal or face color)
|
||||
/// -# Custom properties - user defined data
|
||||
///
|
||||
/// The differentiation is only semantically, technically both are
|
||||
/// equally handled. Therefore the methods provided by the %BaseKernel
|
||||
/// are applicable to both property types.
|
||||
///
|
||||
/// \attention Since the class PolyMeshT derives from a kernel, hence all public
|
||||
/// elements of %BaseKernel are usable.
|
||||
|
||||
class BaseKernel
|
||||
{
|
||||
public: //-------------------------------------------- constructor / destructor
|
||||
|
||||
BaseKernel() {}
|
||||
virtual ~BaseKernel() {}
|
||||
|
||||
|
||||
public: //-------------------------------------------------- add new properties
|
||||
|
||||
/// \name Add a property to a mesh item
|
||||
|
||||
//@{
|
||||
|
||||
/** Adds a property
|
||||
*
|
||||
* Depending on the property handle type a vertex, (half-)edge, face or
|
||||
* mesh property is added to the mesh. If the action fails the handle
|
||||
* is invalid.
|
||||
* On success the handle must be used to access the property data with
|
||||
* property().
|
||||
*
|
||||
* \param _ph A property handle defining the data type to bind to mesh.
|
||||
* On success the handle is valid else invalid.
|
||||
* \param _name Optional name of property. Following restrictions apply
|
||||
* to the name:
|
||||
* -# Maximum length of name is 256 characters
|
||||
* -# The prefixes matching "^[vhefm]:" are reserved for
|
||||
* internal usage.
|
||||
* -# The expression "^<.*>$" is reserved for internal usage.
|
||||
* \return \c true on success else \c false.
|
||||
*
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
void add_property( VPropHandleT<T>& _ph, const std::string& _name="<vprop>")
|
||||
{
|
||||
_ph = VPropHandleT<T>( vprops_.add(T(), _name) );
|
||||
vprops_.resize(n_vertices());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void add_property( HPropHandleT<T>& _ph, const std::string& _name="<hprop>")
|
||||
{
|
||||
_ph = HPropHandleT<T>( hprops_.add(T(), _name) );
|
||||
hprops_.resize(n_halfedges());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void add_property( EPropHandleT<T>& _ph, const std::string& _name="<eprop>")
|
||||
{
|
||||
_ph = EPropHandleT<T>( eprops_.add(T(), _name) );
|
||||
eprops_.resize(n_edges());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void add_property( FPropHandleT<T>& _ph, const std::string& _name="<fprop>")
|
||||
{
|
||||
_ph = FPropHandleT<T>( fprops_.add(T(), _name) );
|
||||
fprops_.resize(n_faces());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void add_property( MPropHandleT<T>& _ph, const std::string& _name="<mprop>")
|
||||
{
|
||||
_ph = MPropHandleT<T>( mprops_.add(T(), _name) );
|
||||
mprops_.resize(1);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
public: //--------------------------------------------------- remove properties
|
||||
|
||||
/// \name Removing a property from a mesh tiem
|
||||
//@{
|
||||
|
||||
/** Remove a property.
|
||||
*
|
||||
* Removes the property represented by the handle from the apropriate
|
||||
* mesh item.
|
||||
* \param _ph Property to be removed. The handle is invalid afterwords.
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
void remove_property(VPropHandleT<T>& _ph)
|
||||
{
|
||||
if (_ph.is_valid())
|
||||
vprops_.remove(_ph);
|
||||
_ph.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void remove_property(HPropHandleT<T>& _ph)
|
||||
{
|
||||
if (_ph.is_valid())
|
||||
hprops_.remove(_ph);
|
||||
_ph.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void remove_property(EPropHandleT<T>& _ph)
|
||||
{
|
||||
if (_ph.is_valid())
|
||||
eprops_.remove(_ph);
|
||||
_ph.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void remove_property(FPropHandleT<T>& _ph)
|
||||
{
|
||||
if (_ph.is_valid())
|
||||
fprops_.remove(_ph);
|
||||
_ph.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void remove_property(MPropHandleT<T>& _ph)
|
||||
{
|
||||
if (_ph.is_valid())
|
||||
mprops_.remove(_ph);
|
||||
_ph.reset();
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
public: //------------------------------------------------ get handle from name
|
||||
|
||||
/// \name Get property handle by name
|
||||
//@{
|
||||
|
||||
/** Retrieves the handle to a named property by it's name.
|
||||
*
|
||||
* \param _ph A property handle. On success the handle is valid else
|
||||
* invalid.
|
||||
* \param _name Name of wanted property.
|
||||
* \return \c true if such a named property is available, else \c false.
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
bool get_property_handle(VPropHandleT<T>& _ph,
|
||||
const std::string& _name) const
|
||||
{
|
||||
return (_ph = VPropHandleT<T>(vprops_.handle(T(), _name))).is_valid();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool get_property_handle(HPropHandleT<T>& _ph,
|
||||
const std::string& _name) const
|
||||
{
|
||||
return (_ph = HPropHandleT<T>(hprops_.handle(T(), _name))).is_valid();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool get_property_handle(EPropHandleT<T>& _ph,
|
||||
const std::string& _name) const
|
||||
{
|
||||
return (_ph = EPropHandleT<T>(eprops_.handle(T(), _name))).is_valid();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool get_property_handle(FPropHandleT<T>& _ph,
|
||||
const std::string& _name) const
|
||||
{
|
||||
return (_ph = FPropHandleT<T>(fprops_.handle(T(), _name))).is_valid();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool get_property_handle(MPropHandleT<T>& _ph,
|
||||
const std::string& _name) const
|
||||
{
|
||||
return (_ph = MPropHandleT<T>(mprops_.handle(T(), _name))).is_valid();
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
public: //--------------------------------------------------- access properties
|
||||
|
||||
/// \name Access a property
|
||||
//@{
|
||||
|
||||
/** Access a property
|
||||
*
|
||||
* This method returns a reference to property. The property handle
|
||||
* must be valid! The result is unpredictable if the handle is invalid!
|
||||
*
|
||||
* \param _ph A \em valid (!) property handle.
|
||||
* \return The wanted property if the handle is valid.
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
PropertyT<T>& property(VPropHandleT<T> _ph) {
|
||||
return vprops_.property(_ph);
|
||||
}
|
||||
template <class T>
|
||||
const PropertyT<T>& property(VPropHandleT<T> _ph) const {
|
||||
return vprops_.property(_ph);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PropertyT<T>& property(HPropHandleT<T> _ph) {
|
||||
return hprops_.property(_ph);
|
||||
}
|
||||
template <class T>
|
||||
const PropertyT<T>& property(HPropHandleT<T> _ph) const {
|
||||
return hprops_.property(_ph);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PropertyT<T>& property(EPropHandleT<T> _ph) {
|
||||
return eprops_.property(_ph);
|
||||
}
|
||||
template <class T>
|
||||
const PropertyT<T>& property(EPropHandleT<T> _ph) const {
|
||||
return eprops_.property(_ph);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PropertyT<T>& property(FPropHandleT<T> _ph) {
|
||||
return fprops_.property(_ph);
|
||||
}
|
||||
template <class T>
|
||||
const PropertyT<T>& property(FPropHandleT<T> _ph) const {
|
||||
return fprops_.property(_ph);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PropertyT<T>& mproperty(MPropHandleT<T> _ph) {
|
||||
return mprops_.property(_ph);
|
||||
}
|
||||
template <class T>
|
||||
const PropertyT<T>& mproperty(MPropHandleT<T> _ph) const {
|
||||
return mprops_.property(_ph);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
public: //-------------------------------------------- access property elements
|
||||
|
||||
/// \name Access a property element using a handle to a mesh item
|
||||
//@{
|
||||
|
||||
/** Return value of property for an item
|
||||
*/
|
||||
|
||||
template <class T>
|
||||
typename VPropHandleT<T>::reference
|
||||
property(VPropHandleT<T> _ph, VertexHandle _vh) {
|
||||
return vprops_.property(_ph)[_vh.idx()];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename VPropHandleT<T>::const_reference
|
||||
property(VPropHandleT<T> _ph, VertexHandle _vh) const {
|
||||
return vprops_.property(_ph)[_vh.idx()];
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
typename HPropHandleT<T>::reference
|
||||
property(HPropHandleT<T> _ph, HalfedgeHandle _hh) {
|
||||
return hprops_.property(_ph)[_hh.idx()];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename HPropHandleT<T>::const_reference
|
||||
property(HPropHandleT<T> _ph, HalfedgeHandle _hh) const {
|
||||
return hprops_.property(_ph)[_hh.idx()];
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
typename EPropHandleT<T>::reference
|
||||
property(EPropHandleT<T> _ph, EdgeHandle _eh) {
|
||||
return eprops_.property(_ph)[_eh.idx()];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename EPropHandleT<T>::const_reference
|
||||
property(EPropHandleT<T> _ph, EdgeHandle _eh) const {
|
||||
return eprops_.property(_ph)[_eh.idx()];
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
typename FPropHandleT<T>::reference
|
||||
property(FPropHandleT<T> _ph, FaceHandle _fh) {
|
||||
return fprops_.property(_ph)[_fh.idx()];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename FPropHandleT<T>::const_reference
|
||||
property(FPropHandleT<T> _ph, FaceHandle _fh) const {
|
||||
return fprops_.property(_ph)[_fh.idx()];
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
typename MPropHandleT<T>::reference
|
||||
property(MPropHandleT<T> _ph) {
|
||||
return mprops_.property(_ph)[0];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename MPropHandleT<T>::const_reference
|
||||
property(MPropHandleT<T> _ph) const {
|
||||
return mprops_.property(_ph)[0];
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
protected: //------------------------------------------------- low-level access
|
||||
|
||||
public: // used by non-native kernel and MeshIO, should be protected
|
||||
|
||||
size_t n_vprops(void) const { return vprops_.size(); }
|
||||
|
||||
size_t n_eprops(void) const { return eprops_.size(); }
|
||||
|
||||
size_t n_hprops(void) const { return hprops_.size(); }
|
||||
|
||||
size_t n_fprops(void) const { return fprops_.size(); }
|
||||
|
||||
size_t n_mprops(void) const { return mprops_.size(); }
|
||||
|
||||
BaseProperty* _get_vprop( const std::string& _name)
|
||||
{ return vprops_.property(_name); }
|
||||
|
||||
BaseProperty* _get_eprop( const std::string& _name)
|
||||
{ return eprops_.property(_name); }
|
||||
|
||||
BaseProperty* _get_hprop( const std::string& _name)
|
||||
{ return hprops_.property(_name); }
|
||||
|
||||
BaseProperty* _get_fprop( const std::string& _name)
|
||||
{ return fprops_.property(_name); }
|
||||
|
||||
BaseProperty* _get_mprop( const std::string& _name)
|
||||
{ return mprops_.property(_name); }
|
||||
|
||||
const BaseProperty* _get_vprop( const std::string& _name) const
|
||||
{ return vprops_.property(_name); }
|
||||
|
||||
const BaseProperty* _get_eprop( const std::string& _name) const
|
||||
{ return eprops_.property(_name); }
|
||||
|
||||
const BaseProperty* _get_hprop( const std::string& _name) const
|
||||
{ return hprops_.property(_name); }
|
||||
|
||||
const BaseProperty* _get_fprop( const std::string& _name) const
|
||||
{ return fprops_.property(_name); }
|
||||
|
||||
const BaseProperty* _get_mprop( const std::string& _name) const
|
||||
{ return mprops_.property(_name); }
|
||||
|
||||
BaseProperty& _vprop( size_t _idx ) { return vprops_._property( _idx ); }
|
||||
BaseProperty& _eprop( size_t _idx ) { return eprops_._property( _idx ); }
|
||||
BaseProperty& _hprop( size_t _idx ) { return hprops_._property( _idx ); }
|
||||
BaseProperty& _fprop( size_t _idx ) { return fprops_._property( _idx ); }
|
||||
BaseProperty& _mprop( size_t _idx ) { return mprops_._property( _idx ); }
|
||||
|
||||
const BaseProperty& _vprop( size_t _idx ) const
|
||||
{ return vprops_._property( _idx ); }
|
||||
const BaseProperty& _eprop( size_t _idx ) const
|
||||
{ return eprops_._property( _idx ); }
|
||||
const BaseProperty& _hprop( size_t _idx ) const
|
||||
{ return hprops_._property( _idx ); }
|
||||
const BaseProperty& _fprop( size_t _idx ) const
|
||||
{ return fprops_._property( _idx ); }
|
||||
const BaseProperty& _mprop( size_t _idx ) const
|
||||
{ return mprops_._property( _idx ); }
|
||||
|
||||
size_t _add_vprop( BaseProperty* _bp ) { return vprops_._add( _bp ); }
|
||||
size_t _add_eprop( BaseProperty* _bp ) { return eprops_._add( _bp ); }
|
||||
size_t _add_hprop( BaseProperty* _bp ) { return hprops_._add( _bp ); }
|
||||
size_t _add_fprop( BaseProperty* _bp ) { return fprops_._add( _bp ); }
|
||||
size_t _add_mprop( BaseProperty* _bp ) { return mprops_._add( _bp ); }
|
||||
|
||||
protected: // low-level access non-public
|
||||
|
||||
BaseProperty& _vprop( BaseHandle _h )
|
||||
{ return vprops_._property( _h.idx() ); }
|
||||
BaseProperty& _eprop( BaseHandle _h )
|
||||
{ return eprops_._property( _h.idx() ); }
|
||||
BaseProperty& _hprop( BaseHandle _h )
|
||||
{ return hprops_._property( _h.idx() ); }
|
||||
BaseProperty& _fprop( BaseHandle _h )
|
||||
{ return fprops_._property( _h.idx() ); }
|
||||
BaseProperty& _mprop( BaseHandle _h )
|
||||
{ return mprops_._property( _h.idx() ); }
|
||||
|
||||
const BaseProperty& _vprop( BaseHandle _h ) const
|
||||
{ return vprops_._property( _h.idx() ); }
|
||||
const BaseProperty& _eprop( BaseHandle _h ) const
|
||||
{ return eprops_._property( _h.idx() ); }
|
||||
const BaseProperty& _hprop( BaseHandle _h ) const
|
||||
{ return hprops_._property( _h.idx() ); }
|
||||
const BaseProperty& _fprop( BaseHandle _h ) const
|
||||
{ return fprops_._property( _h.idx() ); }
|
||||
const BaseProperty& _mprop( BaseHandle _h ) const
|
||||
{ return mprops_._property( _h.idx() ); }
|
||||
|
||||
|
||||
public: //----------------------------------------------------- element numbers
|
||||
|
||||
|
||||
virtual unsigned int n_vertices() const { return 0; }
|
||||
virtual unsigned int n_halfedges() const { return 0; }
|
||||
virtual unsigned int n_edges() const { return 0; }
|
||||
virtual unsigned int n_faces() const { return 0; }
|
||||
|
||||
|
||||
protected: //------------------------------------------- synchronize properties
|
||||
|
||||
void vprops_reserve(unsigned int _n) const { vprops_.reserve(_n); }
|
||||
void vprops_resize(unsigned int _n) const { vprops_.resize(_n); }
|
||||
void vprops_swap(unsigned int _i0, unsigned int _i1) const {
|
||||
vprops_.swap(_i0, _i1);
|
||||
}
|
||||
|
||||
void hprops_reserve(unsigned int _n) const { hprops_.reserve(_n); }
|
||||
void hprops_resize(unsigned int _n) const { hprops_.resize(_n); }
|
||||
void hprops_swap(unsigned int _i0, unsigned int _i1) const {
|
||||
hprops_.swap(_i0, _i1);
|
||||
}
|
||||
|
||||
void eprops_reserve(unsigned int _n) const { eprops_.reserve(_n); }
|
||||
void eprops_resize(unsigned int _n) const { eprops_.resize(_n); }
|
||||
void eprops_swap(unsigned int _i0, unsigned int _i1) const {
|
||||
eprops_.swap(_i0, _i1);
|
||||
}
|
||||
|
||||
void fprops_reserve(unsigned int _n) const { fprops_.reserve(_n); }
|
||||
void fprops_resize(unsigned int _n) const { fprops_.resize(_n); }
|
||||
void fprops_swap(unsigned int _i0, unsigned int _i1) const {
|
||||
fprops_.swap(_i0, _i1);
|
||||
}
|
||||
|
||||
void mprops_resize(unsigned int _n) const { mprops_.resize(_n); }
|
||||
|
||||
public:
|
||||
|
||||
void property_stats(std::ostream& _ostr = std::clog) const;
|
||||
|
||||
public:
|
||||
|
||||
typedef PropertyContainer::iterator prop_iterator;
|
||||
typedef PropertyContainer::const_iterator const_prop_iterator;
|
||||
|
||||
prop_iterator vprops_begin() { return vprops_.begin(); }
|
||||
prop_iterator vprops_end() { return vprops_.end(); }
|
||||
const_prop_iterator vprops_begin() const { return vprops_.begin(); }
|
||||
const_prop_iterator vprops_end() const { return vprops_.end(); }
|
||||
|
||||
prop_iterator eprops_begin() { return eprops_.begin(); }
|
||||
prop_iterator eprops_end() { return eprops_.end(); }
|
||||
const_prop_iterator eprops_begin() const { return eprops_.begin(); }
|
||||
const_prop_iterator eprops_end() const { return eprops_.end(); }
|
||||
|
||||
prop_iterator hprops_begin() { return hprops_.begin(); }
|
||||
prop_iterator hprops_end() { return hprops_.end(); }
|
||||
const_prop_iterator hprops_begin() const { return hprops_.begin(); }
|
||||
const_prop_iterator hprops_end() const { return hprops_.end(); }
|
||||
|
||||
prop_iterator fprops_begin() { return fprops_.begin(); }
|
||||
prop_iterator fprops_end() { return fprops_.end(); }
|
||||
const_prop_iterator fprops_begin() const { return fprops_.begin(); }
|
||||
const_prop_iterator fprops_end() const { return fprops_.end(); }
|
||||
|
||||
prop_iterator mprops_begin() { return mprops_.begin(); }
|
||||
prop_iterator mprops_end() { return mprops_.end(); }
|
||||
const_prop_iterator mprops_begin() const { return mprops_.begin(); }
|
||||
const_prop_iterator mprops_end() const { return mprops_.end(); }
|
||||
|
||||
private:
|
||||
|
||||
PropertyContainer vprops_;
|
||||
PropertyContainer hprops_;
|
||||
PropertyContainer eprops_;
|
||||
PropertyContainer fprops_;
|
||||
PropertyContainer mprops_;
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_BASE_KERNEL_HH defined
|
||||
//=============================================================================
|
||||
79
Core/Mesh/BaseMesh.hh
Normal file
79
Core/Mesh/BaseMesh.hh
Normal file
@@ -0,0 +1,79 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.1.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS BaseMesh
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_BASEMESH_HH
|
||||
#define OPENMESH_BASEMESH_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Mesh/IteratorsT.hh>
|
||||
#include <OpenMesh/Core/Mesh/CirculatorsT.hh>
|
||||
#include <OpenMesh/Core/Mesh/Attributes.hh>
|
||||
#include <vector>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class BaseMesh BaseMesh.hh <OpenMesh/Mesh/BaseMesh.hh>
|
||||
|
||||
Base class for all meshes.
|
||||
*/
|
||||
|
||||
class BaseMesh {
|
||||
public:
|
||||
virtual ~BaseMesh(void) {;}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_BASEMESH_HH defined
|
||||
//=============================================================================
|
||||
54
Core/Mesh/Casts.hh
Normal file
54
Core/Mesh/Casts.hh
Normal file
@@ -0,0 +1,54 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2004 by Computer Graphics Group, RWTH Aachen *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* License *
|
||||
* *
|
||||
* This library 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, version 2.1. *
|
||||
* *
|
||||
* This library 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 Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
|
||||
#ifndef OPENMESH_CASTS_HH
|
||||
#define OPENMESH_CASTS_HH
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
namespace OpenMesh
|
||||
{
|
||||
|
||||
template <class Traits>
|
||||
inline TriMesh_ArrayKernelT<Traits>& TRIMESH_CAST(PolyMesh_ArrayKernelT<Traits>& _poly_mesh)
|
||||
{ return reinterpret_cast< TriMesh_ArrayKernelT<Traits>& >(_poly_mesh); }
|
||||
|
||||
template <class Traits>
|
||||
inline const TriMesh_ArrayKernelT<Traits>& TRIMESH_CAST(const PolyMesh_ArrayKernelT<Traits>& _poly_mesh)
|
||||
{ return reinterpret_cast< const TriMesh_ArrayKernelT<Traits>& >(_poly_mesh); }
|
||||
|
||||
template <class Traits>
|
||||
inline PolyMesh_ArrayKernelT<Traits>& POLYMESH_CAST(TriMesh_ArrayKernelT<Traits>& _tri_mesh)
|
||||
{ return reinterpret_cast< PolyMesh_ArrayKernelT<Traits>& >(_tri_mesh); }
|
||||
|
||||
template <class Traits>
|
||||
inline const PolyMesh_ArrayKernelT<Traits>& POLYMESH_CAST(const TriMesh_ArrayKernelT<Traits>& _tri_mesh)
|
||||
{ return reinterpret_cast< const PolyMesh_ArrayKernelT<Traits>& >(_tri_mesh); }
|
||||
|
||||
};
|
||||
#endif//OPENMESH_CASTS_HH
|
||||
3499
Core/Mesh/CirculatorsT.hh
Normal file
3499
Core/Mesh/CirculatorsT.hh
Normal file
File diff suppressed because it is too large
Load Diff
121
Core/Mesh/FinalMeshItemsT.hh
Normal file
121
Core/Mesh/FinalMeshItemsT.hh
Normal file
@@ -0,0 +1,121 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.1.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 3794 $
|
||||
// $Date: 2008-11-25 19:25:02 +0100 (Di, 25. Nov 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_MESH_ITEMS_HH
|
||||
#define OPENMESH_MESH_ITEMS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Utils/GenProg.hh>
|
||||
#include <OpenMesh/Core/Utils/vector_traits.hh>
|
||||
#include <OpenMesh/Core/Mesh/Handles.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/// Definition of the mesh entities (items).
|
||||
template <class Traits, bool IsTriMesh>
|
||||
struct FinalMeshItemsT
|
||||
{
|
||||
//--- build Refs structure ---
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
struct Refs
|
||||
{
|
||||
typedef typename Traits::Point Point;
|
||||
typedef typename vector_traits<Point>::value_type Scalar;
|
||||
|
||||
typedef typename Traits::Normal Normal;
|
||||
typedef typename Traits::Color Color;
|
||||
typedef typename Traits::TexCoord1D TexCoord1D;
|
||||
typedef typename Traits::TexCoord2D TexCoord2D;
|
||||
typedef typename Traits::TexCoord3D TexCoord3D;
|
||||
typedef typename Traits::TextureIndex TextureIndex;
|
||||
typedef OpenMesh::VertexHandle VertexHandle;
|
||||
typedef OpenMesh::FaceHandle FaceHandle;
|
||||
typedef OpenMesh::EdgeHandle EdgeHandle;
|
||||
typedef OpenMesh::HalfedgeHandle HalfedgeHandle;
|
||||
};
|
||||
#endif
|
||||
//--- export Refs types ---
|
||||
typedef typename Refs::Point Point;
|
||||
typedef typename Refs::Scalar Scalar;
|
||||
typedef typename Refs::Normal Normal;
|
||||
typedef typename Refs::Color Color;
|
||||
typedef typename Refs::TexCoord1D TexCoord1D;
|
||||
typedef typename Refs::TexCoord2D TexCoord2D;
|
||||
typedef typename Refs::TexCoord3D TexCoord3D;
|
||||
typedef typename Refs::TextureIndex TextureIndex;
|
||||
|
||||
//--- get attribute bits from Traits ---
|
||||
enum Attribs
|
||||
{
|
||||
VAttribs = Traits::VertexAttributes,
|
||||
HAttribs = Traits::HalfedgeAttributes,
|
||||
EAttribs = Traits::EdgeAttributes,
|
||||
FAttribs = Traits::FaceAttributes
|
||||
};
|
||||
//--- merge internal items with traits items ---
|
||||
|
||||
|
||||
/*
|
||||
typedef typename GenProg::IF<
|
||||
(bool)(HAttribs & Attributes::PrevHalfedge),
|
||||
typename InternalItems::Halfedge_with_prev,
|
||||
typename InternalItems::Halfedge_without_prev
|
||||
>::Result InternalHalfedge;
|
||||
*/
|
||||
//typedef typename InternalItems::Vertex InternalVertex;
|
||||
//typedef typename InternalItems::template Edge<Halfedge> InternalEdge;
|
||||
//typedef typename InternalItems::template Face<IsTriMesh> InternalFace;
|
||||
class ITraits
|
||||
{};
|
||||
|
||||
typedef typename Traits::template VertexT<ITraits, Refs> VertexData;
|
||||
typedef typename Traits::template HalfedgeT<ITraits, Refs> HalfedgeData;
|
||||
typedef typename Traits::template EdgeT<ITraits, Refs> EdgeData;
|
||||
typedef typename Traits::template FaceT<ITraits, Refs> FaceData;
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_MESH_ITEMS_HH defined
|
||||
//=============================================================================
|
||||
|
||||
134
Core/Mesh/Handles.hh
Normal file
134
Core/Mesh/Handles.hh
Normal file
@@ -0,0 +1,134 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.1.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_HANDLES_HH
|
||||
#define OPENMESH_HANDLES_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/// Base class for all handle types
|
||||
class BaseHandle
|
||||
{
|
||||
public:
|
||||
|
||||
explicit BaseHandle(int _idx=-1) : idx_(_idx) {}
|
||||
|
||||
/// Get the underlying index of this handle
|
||||
int idx() const { return idx_; }
|
||||
|
||||
/// The handle is valid iff the index is not equal to -1.
|
||||
bool is_valid() const { return idx_ != -1; }
|
||||
|
||||
/// reset handle to be invalid
|
||||
void reset() { idx_=-1; }
|
||||
/// reset handle to be invalid
|
||||
void invalidate() { idx_ = -1; }
|
||||
|
||||
bool operator==(const BaseHandle& _rhs) const {
|
||||
return idx_ == _rhs.idx_;
|
||||
}
|
||||
|
||||
bool operator!=(const BaseHandle& _rhs) const {
|
||||
return idx_ != _rhs.idx_;
|
||||
}
|
||||
|
||||
bool operator<(const BaseHandle& _rhs) const {
|
||||
return idx_ < _rhs.idx_;
|
||||
}
|
||||
|
||||
|
||||
// this is to be used only by the iterators
|
||||
void __increment() { ++idx_; }
|
||||
void __decrement() { --idx_; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
int idx_;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/// Write handle \c _hnd to stream \c _os
|
||||
inline std::ostream& operator<<(std::ostream& _os, const BaseHandle& _hnd)
|
||||
{
|
||||
return (_os << _hnd.idx());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/// Handle for a vertex entity
|
||||
struct VertexHandle : public BaseHandle
|
||||
{
|
||||
explicit VertexHandle(int _idx=-1) : BaseHandle(_idx) {}
|
||||
};
|
||||
|
||||
|
||||
/// Handle for a halfedge entity
|
||||
struct HalfedgeHandle : public BaseHandle
|
||||
{
|
||||
explicit HalfedgeHandle(int _idx=-1) : BaseHandle(_idx) {}
|
||||
};
|
||||
|
||||
|
||||
/// Handle for a edge entity
|
||||
struct EdgeHandle : public BaseHandle
|
||||
{
|
||||
explicit EdgeHandle(int _idx=-1) : BaseHandle(_idx) {}
|
||||
};
|
||||
|
||||
|
||||
/// Handle for a face entity
|
||||
struct FaceHandle : public BaseHandle
|
||||
{
|
||||
explicit FaceHandle(int _idx=-1) : BaseHandle(_idx) {}
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_HANDLES_HH
|
||||
//=============================================================================
|
||||
1364
Core/Mesh/IteratorsT.hh
Normal file
1364
Core/Mesh/IteratorsT.hh
Normal file
File diff suppressed because it is too large
Load Diff
838
Core/Mesh/PolyConnectivity.cc
Normal file
838
Core/Mesh/PolyConnectivity.cc
Normal file
@@ -0,0 +1,838 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2004 by Computer Graphics Group, RWTH Aachen *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* License *
|
||||
* *
|
||||
* This library 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, version 2.1. *
|
||||
* *
|
||||
* This library 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 Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
|
||||
//== IMPLEMENTATION ==========================================================
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
#include <set>
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
const PolyConnectivity::VertexHandle PolyConnectivity::InvalidVertexHandle;
|
||||
const PolyConnectivity::HalfedgeHandle PolyConnectivity::InvalidHalfedgeHandle;
|
||||
const PolyConnectivity::EdgeHandle PolyConnectivity::InvalidEdgeHandle;
|
||||
const PolyConnectivity::FaceHandle PolyConnectivity::InvalidFaceHandle;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
PolyConnectivity::HalfedgeHandle
|
||||
PolyConnectivity::find_halfedge(VertexHandle _start_vh, VertexHandle _end_vh ) const
|
||||
{
|
||||
assert(_start_vh.is_valid() && _end_vh.is_valid());
|
||||
|
||||
for (ConstVertexVertexIter vvIt=cvv_iter(_start_vh); vvIt; ++vvIt)
|
||||
if (vvIt.handle() == _end_vh)
|
||||
return vvIt.current_halfedge_handle();
|
||||
|
||||
return InvalidHalfedgeHandle;
|
||||
}
|
||||
|
||||
|
||||
bool PolyConnectivity::is_boundary(FaceHandle _fh, bool _check_vertex) const
|
||||
{
|
||||
for (ConstFaceEdgeIter cfeit = cfe_iter( _fh ); cfeit; ++cfeit)
|
||||
if (is_boundary( cfeit.handle() ) )
|
||||
return true;
|
||||
|
||||
if (_check_vertex)
|
||||
{
|
||||
for (ConstFaceVertexIter cfvit = cfv_iter( _fh ); cfvit; ++cfvit)
|
||||
if (is_boundary( cfvit.handle() ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PolyConnectivity::is_manifold(VertexHandle _vh) const
|
||||
{
|
||||
/* The vertex is non-manifold if more than one gap exists, i.e.
|
||||
more than one outgoing boundary halfedge. If (at least) one
|
||||
boundary halfedge exists, the vertex' halfedge must be a
|
||||
boundary halfedge. If iterating around the vertex finds another
|
||||
boundary halfedge, the vertex is non-manifold. */
|
||||
|
||||
ConstVertexOHalfedgeIter vh_it(*this, _vh);
|
||||
if (vh_it)
|
||||
for (++vh_it; vh_it; ++vh_it)
|
||||
if (is_boundary(vh_it.handle()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::adjust_outgoing_halfedge(VertexHandle _vh)
|
||||
{
|
||||
for (ConstVertexOHalfedgeIter vh_it=cvoh_iter(_vh); vh_it; ++vh_it)
|
||||
{
|
||||
if (is_boundary(vh_it.handle()))
|
||||
{
|
||||
set_halfedge_handle(_vh, vh_it.handle());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace
|
||||
{
|
||||
template <class _Handle>
|
||||
struct NextCacheEntryT : public std::pair<_Handle, _Handle>
|
||||
{
|
||||
typedef std::pair<_Handle, _Handle> Base;
|
||||
|
||||
NextCacheEntryT(_Handle _heh0, _Handle _heh1)
|
||||
: Base(_heh0, _heh1)
|
||||
{
|
||||
assert(_heh0.is_valid());
|
||||
assert(_heh1.is_valid());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
PolyConnectivity::FaceHandle
|
||||
PolyConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size)
|
||||
{
|
||||
VertexHandle vh;
|
||||
uint i, ii, n(_vhs_size), id;
|
||||
std::vector<HalfedgeHandle> halfedge_handles(n);
|
||||
std::vector<bool> is_new(n), needs_adjust(n, false);
|
||||
HalfedgeHandle inner_next, inner_prev,
|
||||
outer_next, outer_prev,
|
||||
boundary_next, boundary_prev,
|
||||
patch_start, patch_end;
|
||||
|
||||
// cache for set_next_halfedge and vertex' set_halfedge
|
||||
typedef NextCacheEntryT<HalfedgeHandle> NextCacheEntry;
|
||||
typedef std::vector<NextCacheEntry> NextCache;
|
||||
|
||||
NextCache next_cache;
|
||||
next_cache.reserve(3*n);
|
||||
// don't allow degenerated faces
|
||||
assert (n > 2);
|
||||
|
||||
// test for topological errors
|
||||
for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
|
||||
{
|
||||
if ( !is_boundary(_vertex_handles[i]) )
|
||||
{
|
||||
omerr() << "PolyMeshT::add_face: complex vertex\n";
|
||||
return InvalidFaceHandle;
|
||||
}
|
||||
|
||||
halfedge_handles[i] = find_halfedge(_vertex_handles[i],
|
||||
_vertex_handles[ii]);
|
||||
is_new[i] = !halfedge_handles[i].is_valid();
|
||||
|
||||
if (!is_new[i] && !is_boundary(halfedge_handles[i]))
|
||||
{
|
||||
omerr() << "PolyMeshT::add_face: complex edge\n";
|
||||
return InvalidFaceHandle;
|
||||
}
|
||||
}
|
||||
|
||||
// re-link patches if necessary
|
||||
for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
|
||||
{
|
||||
if (!is_new[i] && !is_new[ii])
|
||||
{
|
||||
inner_prev = halfedge_handles[i];
|
||||
inner_next = halfedge_handles[ii];
|
||||
|
||||
if (next_halfedge_handle(inner_prev) != inner_next)
|
||||
{
|
||||
// here comes the ugly part... we have to relink a whole patch
|
||||
|
||||
// search a free gap
|
||||
// free gap will be between boundary_prev and boundary_next
|
||||
outer_prev = opposite_halfedge_handle(inner_next);
|
||||
outer_next = opposite_halfedge_handle(inner_prev);
|
||||
boundary_prev = outer_prev;
|
||||
do
|
||||
boundary_prev =
|
||||
opposite_halfedge_handle(next_halfedge_handle(boundary_prev));
|
||||
while (!is_boundary(boundary_prev) || boundary_prev==inner_prev);
|
||||
boundary_next = next_halfedge_handle(boundary_prev);
|
||||
assert(is_boundary(boundary_prev));
|
||||
assert(is_boundary(boundary_next));
|
||||
// ok ?
|
||||
if (boundary_next == inner_next)
|
||||
{
|
||||
omerr() << "PolyMeshT::add_face: patch re-linking failed\n";
|
||||
return InvalidFaceHandle;
|
||||
}
|
||||
|
||||
// other halfedges' handles
|
||||
patch_start = next_halfedge_handle(inner_prev);
|
||||
patch_end = prev_halfedge_handle(inner_next);
|
||||
|
||||
// relink
|
||||
next_cache.push_back(NextCacheEntry(boundary_prev, patch_start));
|
||||
next_cache.push_back(NextCacheEntry(patch_end, boundary_next));
|
||||
next_cache.push_back(NextCacheEntry(inner_prev, inner_next));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create missing edges
|
||||
for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
|
||||
if (is_new[i])
|
||||
halfedge_handles[i] = new_edge(_vertex_handles[i], _vertex_handles[ii]);
|
||||
|
||||
// create the face
|
||||
FaceHandle fh(new_face());
|
||||
set_halfedge_handle(fh, halfedge_handles[n-1]);
|
||||
|
||||
// setup halfedges
|
||||
for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
|
||||
{
|
||||
vh = _vertex_handles[ii];
|
||||
inner_prev = halfedge_handles[i];
|
||||
inner_next = halfedge_handles[ii];
|
||||
|
||||
id = 0;
|
||||
if (is_new[i]) id |= 1;
|
||||
if (is_new[ii]) id |= 2;
|
||||
|
||||
if (id)
|
||||
{
|
||||
outer_prev = opposite_halfedge_handle(inner_next);
|
||||
outer_next = opposite_halfedge_handle(inner_prev);
|
||||
|
||||
// set outer links
|
||||
switch (id)
|
||||
{
|
||||
case 1: // prev is new, next is old
|
||||
boundary_prev = prev_halfedge_handle(inner_next);
|
||||
next_cache.push_back(NextCacheEntry(boundary_prev, outer_next));
|
||||
set_halfedge_handle(vh, outer_next);
|
||||
break;
|
||||
|
||||
case 2: // next is new, prev is old
|
||||
boundary_next = next_halfedge_handle(inner_prev);
|
||||
next_cache.push_back(NextCacheEntry(outer_prev, boundary_next));
|
||||
set_halfedge_handle(vh, boundary_next);
|
||||
break;
|
||||
|
||||
case 3: // both are new
|
||||
if (!halfedge_handle(vh).is_valid())
|
||||
{
|
||||
set_halfedge_handle(vh, outer_next);
|
||||
next_cache.push_back(NextCacheEntry(outer_prev, outer_next));
|
||||
}
|
||||
else
|
||||
{
|
||||
boundary_next = halfedge_handle(vh);
|
||||
boundary_prev = prev_halfedge_handle(boundary_next);
|
||||
next_cache.push_back(NextCacheEntry(boundary_prev, outer_next));
|
||||
next_cache.push_back(NextCacheEntry(outer_prev, boundary_next));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// set inner link
|
||||
next_cache.push_back(NextCacheEntry(inner_prev, inner_next));
|
||||
}
|
||||
else needs_adjust[ii] = (halfedge_handle(vh) == inner_next);
|
||||
|
||||
// set face handle
|
||||
set_face_handle(halfedge_handles[i], fh);
|
||||
}
|
||||
|
||||
// process next halfedge cache
|
||||
NextCache::const_iterator ncIt(next_cache.begin()), ncEnd(next_cache.end());
|
||||
for (; ncIt != ncEnd; ++ncIt)
|
||||
set_next_halfedge_handle(ncIt->first, ncIt->second);
|
||||
|
||||
// adjust vertices' halfedge handle
|
||||
for (i=0; i<n; ++i)
|
||||
if (needs_adjust[i])
|
||||
adjust_outgoing_halfedge(_vertex_handles[i]);
|
||||
|
||||
return fh;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PolyConnectivity::delete_vertex(VertexHandle _vh, bool _delete_isolated_vertices)
|
||||
{
|
||||
// store incident faces
|
||||
std::vector<FaceHandle> face_handles;
|
||||
face_handles.reserve(8);
|
||||
for (VFIter vf_it(vf_iter(_vh)); vf_it; ++vf_it)
|
||||
face_handles.push_back(vf_it.handle());
|
||||
|
||||
|
||||
// delete collected faces
|
||||
std::vector<FaceHandle>::iterator fh_it(face_handles.begin()),
|
||||
fh_end(face_handles.end());
|
||||
|
||||
for (; fh_it!=fh_end; ++fh_it)
|
||||
delete_face(*fh_it, _delete_isolated_vertices);
|
||||
|
||||
status(_vh).set_deleted(true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PolyConnectivity::delete_edge(EdgeHandle _eh, bool _delete_isolated_vertices)
|
||||
{
|
||||
FaceHandle fh0(face_handle(halfedge_handle(_eh, 0)));
|
||||
FaceHandle fh1(face_handle(halfedge_handle(_eh, 1)));
|
||||
|
||||
if (fh0.is_valid()) delete_face(fh0, _delete_isolated_vertices);
|
||||
if (fh1.is_valid()) delete_face(fh1, _delete_isolated_vertices);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void PolyConnectivity::delete_face(FaceHandle _fh, bool _delete_isolated_vertices)
|
||||
{
|
||||
assert(_fh.is_valid() && !status(_fh).deleted());
|
||||
|
||||
// mark face deleted
|
||||
status(_fh).set_deleted(true);
|
||||
|
||||
|
||||
// this vector will hold all boundary edges of face _fh
|
||||
// these edges will be deleted
|
||||
std::vector<EdgeHandle> deleted_edges;
|
||||
deleted_edges.reserve(3);
|
||||
|
||||
|
||||
// this vector will hold all vertices of face _fh
|
||||
// for updating their outgoing halfedge
|
||||
std::vector<VertexHandle> vhandles;
|
||||
vhandles.reserve(3);
|
||||
|
||||
|
||||
// for all halfedges of face _fh do:
|
||||
// 1) invalidate face handle.
|
||||
// 2) collect all boundary halfedges, set them deleted
|
||||
// 3) store vertex handles
|
||||
HalfedgeHandle hh;
|
||||
for (FaceHalfedgeIter fh_it(fh_iter(_fh)); fh_it; ++fh_it)
|
||||
{
|
||||
hh = fh_it.handle();
|
||||
|
||||
set_boundary(hh);//set_face_handle(hh, InvalidFaceHandle);
|
||||
|
||||
if (is_boundary(opposite_halfedge_handle(hh)))
|
||||
deleted_edges.push_back(edge_handle(hh));
|
||||
|
||||
vhandles.push_back(to_vertex_handle(hh));
|
||||
}
|
||||
|
||||
|
||||
// delete all collected (half)edges
|
||||
// delete isolated vertices (if _delete_isolated_vertices is true)
|
||||
if (!deleted_edges.empty())
|
||||
{
|
||||
std::vector<EdgeHandle>::iterator del_it(deleted_edges.begin()),
|
||||
del_end(deleted_edges.end());
|
||||
HalfedgeHandle h0, h1, next0, next1, prev0, prev1;
|
||||
VertexHandle v0, v1;
|
||||
|
||||
for (; del_it!=del_end; ++del_it)
|
||||
{
|
||||
h0 = halfedge_handle(*del_it, 0);
|
||||
v0 = to_vertex_handle(h0);
|
||||
next0 = next_halfedge_handle(h0);
|
||||
prev0 = prev_halfedge_handle(h0);
|
||||
|
||||
h1 = halfedge_handle(*del_it, 1);
|
||||
v1 = to_vertex_handle(h1);
|
||||
next1 = next_halfedge_handle(h1);
|
||||
prev1 = prev_halfedge_handle(h1);
|
||||
|
||||
// adjust next and prev handles
|
||||
set_next_halfedge_handle(prev0, next1);
|
||||
set_next_halfedge_handle(prev1, next0);
|
||||
|
||||
// mark edge deleted
|
||||
status(*del_it).set_deleted(true);
|
||||
|
||||
// update v0
|
||||
if (halfedge_handle(v0) == h1)
|
||||
{
|
||||
// isolated ?
|
||||
if (next0 == h1)
|
||||
{
|
||||
if (_delete_isolated_vertices)
|
||||
status(v0).set_deleted(true);
|
||||
set_isolated(v0);
|
||||
}
|
||||
else set_halfedge_handle(v0, next0);
|
||||
}
|
||||
|
||||
// update v1
|
||||
if (halfedge_handle(v1) == h0)
|
||||
{
|
||||
// isolated ?
|
||||
if (next1 == h0)
|
||||
{
|
||||
if (_delete_isolated_vertices)
|
||||
status(v1).set_deleted(true);
|
||||
set_isolated(v1);
|
||||
}
|
||||
else set_halfedge_handle(v1, next1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update outgoing halfedge handles of remaining vertices
|
||||
std::vector<VertexHandle>::iterator v_it(vhandles.begin()),
|
||||
v_end(vhandles.end());
|
||||
for (; v_it!=v_end; ++v_it)
|
||||
adjust_outgoing_halfedge(*v_it);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::collapse(HalfedgeHandle _hh)
|
||||
{
|
||||
HalfedgeHandle h0 = _hh;
|
||||
HalfedgeHandle h1 = next_halfedge_handle(h0);
|
||||
HalfedgeHandle o0 = opposite_halfedge_handle(h0);
|
||||
HalfedgeHandle o1 = next_halfedge_handle(o0);
|
||||
|
||||
// remove edge
|
||||
collapse_edge(h0);
|
||||
|
||||
// remove loops
|
||||
if (next_halfedge_handle(next_halfedge_handle(h1)) == h1)
|
||||
collapse_loop(next_halfedge_handle(h1));
|
||||
if (next_halfedge_handle(next_halfedge_handle(o1)) == o1)
|
||||
collapse_loop(o1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::collapse_edge(HalfedgeHandle _hh)
|
||||
{
|
||||
HalfedgeHandle h = _hh;
|
||||
HalfedgeHandle hn = next_halfedge_handle(h);
|
||||
HalfedgeHandle hp = prev_halfedge_handle(h);
|
||||
|
||||
HalfedgeHandle o = opposite_halfedge_handle(h);
|
||||
HalfedgeHandle on = next_halfedge_handle(o);
|
||||
HalfedgeHandle op = prev_halfedge_handle(o);
|
||||
|
||||
FaceHandle fh = face_handle(h);
|
||||
FaceHandle fo = face_handle(o);
|
||||
|
||||
VertexHandle vh = to_vertex_handle(h);
|
||||
VertexHandle vo = to_vertex_handle(o);
|
||||
|
||||
|
||||
|
||||
// halfedge -> vertex
|
||||
for (VertexIHalfedgeIter vih_it(vih_iter(vo)); vih_it; ++vih_it)
|
||||
set_vertex_handle(vih_it.handle(), vh);
|
||||
|
||||
|
||||
// halfedge -> halfedge
|
||||
set_next_halfedge_handle(hp, hn);
|
||||
set_next_halfedge_handle(op, on);
|
||||
|
||||
|
||||
// face -> halfedge
|
||||
if (fh.is_valid()) set_halfedge_handle(fh, hn);
|
||||
if (fo.is_valid()) set_halfedge_handle(fo, on);
|
||||
|
||||
|
||||
// vertex -> halfedge
|
||||
if (halfedge_handle(vh) == o) set_halfedge_handle(vh, hn);
|
||||
adjust_outgoing_halfedge(vh);
|
||||
set_isolated(vo);
|
||||
|
||||
// delete stuff
|
||||
status(edge_handle(h)).set_deleted(true);
|
||||
status(vo).set_deleted(true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::collapse_loop(HalfedgeHandle _hh)
|
||||
{
|
||||
HalfedgeHandle h0 = _hh;
|
||||
HalfedgeHandle h1 = next_halfedge_handle(h0);
|
||||
|
||||
HalfedgeHandle o0 = opposite_halfedge_handle(h0);
|
||||
HalfedgeHandle o1 = opposite_halfedge_handle(h1);
|
||||
|
||||
VertexHandle v0 = to_vertex_handle(h0);
|
||||
VertexHandle v1 = to_vertex_handle(h1);
|
||||
|
||||
FaceHandle fh = face_handle(h0);
|
||||
FaceHandle fo = face_handle(o0);
|
||||
|
||||
|
||||
|
||||
// is it a loop ?
|
||||
assert ((next_halfedge_handle(h1) == h0) && (h1 != o0));
|
||||
|
||||
|
||||
// halfedge -> halfedge
|
||||
set_next_halfedge_handle(h1, next_halfedge_handle(o0));
|
||||
set_next_halfedge_handle(prev_halfedge_handle(o0), h1);
|
||||
|
||||
|
||||
// halfedge -> face
|
||||
set_face_handle(h1, fo);
|
||||
|
||||
|
||||
// vertex -> halfedge
|
||||
set_halfedge_handle(v0, h1); adjust_outgoing_halfedge(v0);
|
||||
set_halfedge_handle(v1, o1); adjust_outgoing_halfedge(v1);
|
||||
|
||||
|
||||
// face -> halfedge
|
||||
if (fo.is_valid() && halfedge_handle(fo) == o0)
|
||||
{
|
||||
set_halfedge_handle(fo, h1);
|
||||
}
|
||||
|
||||
// delete stuff
|
||||
if (fh.is_valid())
|
||||
{
|
||||
set_halfedge_handle(fh, InvalidHalfedgeHandle);
|
||||
status(fh).set_deleted(true);
|
||||
}
|
||||
status(edge_handle(h0)).set_deleted(true);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool PolyConnectivity::is_simple_link(EdgeHandle _eh) const
|
||||
{
|
||||
HalfedgeHandle heh0 = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle heh1 = halfedge_handle(_eh, 1);
|
||||
|
||||
FaceHandle fh0 = face_handle(heh0);//fh0 or fh1 might be a invalid,
|
||||
FaceHandle fh1 = face_handle(heh1);//i.e., representing the boundary
|
||||
|
||||
HalfedgeHandle next_heh = next_halfedge_handle(heh0);
|
||||
while (next_heh != heh0)
|
||||
{//check if there are no other edges shared between fh0 & fh1
|
||||
if (opposite_face_handle(next_heh) == fh1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
next_heh = next_halfedge_handle(next_heh);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool PolyConnectivity::is_simply_connected(FaceHandle _fh) const
|
||||
{
|
||||
std::set<FaceHandle> nb_fhs;
|
||||
for (ConstFaceFaceIter cff_it = cff_iter(_fh); cff_it; ++cff_it)
|
||||
{
|
||||
if (nb_fhs.find(cff_it) == nb_fhs.end())
|
||||
{
|
||||
nb_fhs.insert(cff_it);
|
||||
}
|
||||
else
|
||||
{//there is more than one link
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
PolyConnectivity::FaceHandle
|
||||
PolyConnectivity::remove_edge(EdgeHandle _eh)
|
||||
{
|
||||
//don't allow "dangling" vertices and edges
|
||||
assert(!status(_eh).deleted() && is_simple_link(_eh));
|
||||
|
||||
HalfedgeHandle heh0 = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle heh1 = halfedge_handle(_eh, 1);
|
||||
|
||||
//deal with the faces
|
||||
FaceHandle rem_fh = face_handle(heh0), del_fh = face_handle(heh1);
|
||||
if (!del_fh.is_valid())
|
||||
{//boundary case - we must delete the rem_fh
|
||||
std::swap(del_fh, rem_fh);
|
||||
}
|
||||
assert(del_fh.is_valid());
|
||||
/* for (FaceHalfedgeIter fh_it = fh_iter(del_fh); fh_it; ++fh_it)
|
||||
{//set the face handle of the halfedges of del_fh to point to rem_fh
|
||||
set_face_handle(fh_it, rem_fh);
|
||||
} */
|
||||
//fix the halfedge relations
|
||||
HalfedgeHandle prev_heh0 = prev_halfedge_handle(heh0);
|
||||
HalfedgeHandle prev_heh1 = prev_halfedge_handle(heh1);
|
||||
|
||||
HalfedgeHandle next_heh0 = next_halfedge_handle(heh0);
|
||||
HalfedgeHandle next_heh1 = next_halfedge_handle(heh1);
|
||||
|
||||
set_next_halfedge_handle(prev_heh0, next_heh1);
|
||||
set_next_halfedge_handle(prev_heh1, next_heh0);
|
||||
//correct outgoing vertex handles for the _eh vertices (if needed)
|
||||
VertexHandle vh0 = to_vertex_handle(heh0);
|
||||
VertexHandle vh1 = to_vertex_handle(heh1);
|
||||
|
||||
if (halfedge_handle(vh0) == heh1)
|
||||
{
|
||||
set_halfedge_handle(vh0, next_heh0);
|
||||
}
|
||||
if (halfedge_handle(vh1) == heh0)
|
||||
{
|
||||
set_halfedge_handle(vh1, next_heh1);
|
||||
}
|
||||
|
||||
//correct the hafledge handle of rem_fh if needed and preserve its first vertex
|
||||
if (halfedge_handle(rem_fh) == heh0)
|
||||
{//rem_fh is the face at heh0
|
||||
set_halfedge_handle(rem_fh, prev_heh1);
|
||||
}
|
||||
else if (halfedge_handle(rem_fh) == heh1)
|
||||
{//rem_fh is the face at heh1
|
||||
set_halfedge_handle(rem_fh, prev_heh0);
|
||||
}
|
||||
for (FaceHalfedgeIter fh_it = fh_iter(rem_fh); fh_it; ++fh_it)
|
||||
{//set the face handle of the halfedges of del_fh to point to rem_fh
|
||||
set_face_handle(fh_it, rem_fh);
|
||||
}
|
||||
|
||||
status(_eh).set_deleted(true);
|
||||
status(del_fh).set_deleted(true);
|
||||
return rem_fh;//returns the remaining face handle
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::reinsert_edge(EdgeHandle _eh)
|
||||
{
|
||||
//this does not work without prev_halfedge_handle
|
||||
assert_compile(sizeof(Halfedge) == sizeof(Halfedge_with_prev));
|
||||
//shoudl be deleted
|
||||
assert(status(_eh).deleted());
|
||||
status(_eh).set_deleted(false);
|
||||
|
||||
HalfedgeHandle heh0 = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle heh1 = halfedge_handle(_eh, 1);
|
||||
FaceHandle rem_fh = face_handle(heh0), del_fh = face_handle(heh1);
|
||||
if (!del_fh.is_valid())
|
||||
{//boundary case - we must delete the rem_fh
|
||||
std::swap(del_fh, rem_fh);
|
||||
}
|
||||
assert(status(del_fh).deleted());
|
||||
status(del_fh).set_deleted(false);
|
||||
|
||||
//restore halfedge relations
|
||||
HalfedgeHandle prev_heh0 = prev_halfedge_handle(heh0);
|
||||
HalfedgeHandle prev_heh1 = prev_halfedge_handle(heh1);
|
||||
|
||||
HalfedgeHandle next_heh0 = next_halfedge_handle(heh0);
|
||||
HalfedgeHandle next_heh1 = next_halfedge_handle(heh1);
|
||||
|
||||
set_next_halfedge_handle(prev_heh0, heh0);
|
||||
set_prev_halfedge_handle(next_heh0, heh0);
|
||||
|
||||
set_next_halfedge_handle(prev_heh1, heh1);
|
||||
set_prev_halfedge_handle(next_heh1, heh1);
|
||||
|
||||
for (FaceHalfedgeIter fh_it = fh_iter(del_fh); fh_it; ++fh_it)
|
||||
{//reassign halfedges to del_fh
|
||||
set_face_handle(fh_it, del_fh);
|
||||
}
|
||||
|
||||
if (face_handle(halfedge_handle(rem_fh)) == del_fh)
|
||||
{//correct the halfedge handle of rem_fh
|
||||
if (halfedge_handle(rem_fh) == prev_heh0)
|
||||
{//rem_fh is the face at heh1
|
||||
set_halfedge_handle(rem_fh, heh1);
|
||||
}
|
||||
else
|
||||
{//rem_fh is the face at heh0
|
||||
assert(halfedge_handle(rem_fh) == prev_heh1);
|
||||
set_halfedge_handle(rem_fh, heh0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
PolyConnectivity::HalfedgeHandle
|
||||
PolyConnectivity::insert_edge(HalfedgeHandle _prev_heh, HalfedgeHandle _next_heh)
|
||||
{
|
||||
assert(face_handle(_prev_heh) == face_handle(_next_heh));//only the manifold case
|
||||
assert(next_halfedge_handle(_prev_heh) != _next_heh);//this can not be done
|
||||
VertexHandle vh0 = to_vertex_handle(_prev_heh);
|
||||
VertexHandle vh1 = from_vertex_handle(_next_heh);
|
||||
//create the link between vh0 and vh1
|
||||
HalfedgeHandle heh0 = new_edge(vh0, vh1);
|
||||
HalfedgeHandle heh1 = opposite_halfedge_handle(heh0);
|
||||
HalfedgeHandle next_prev_heh = next_halfedge_handle(_prev_heh);
|
||||
HalfedgeHandle prev_next_heh = prev_halfedge_handle(_next_heh);
|
||||
set_next_halfedge_handle(_prev_heh, heh0);
|
||||
set_next_halfedge_handle(heh0, _next_heh);
|
||||
set_next_halfedge_handle(prev_next_heh, heh1);
|
||||
set_next_halfedge_handle(heh1, next_prev_heh);
|
||||
|
||||
//now set the face handles - the new face is assigned to heh0
|
||||
FaceHandle new_fh = new_face();
|
||||
set_halfedge_handle(new_fh, heh0);
|
||||
for (FaceHalfedgeIter fh_it = fh_iter(new_fh); fh_it; ++fh_it)
|
||||
{
|
||||
set_face_handle(fh_it, new_fh);
|
||||
}
|
||||
FaceHandle old_fh = face_handle(next_prev_heh);
|
||||
set_face_handle(heh1, old_fh);
|
||||
if (old_fh.is_valid() && face_handle(halfedge_handle(old_fh)) == new_fh)
|
||||
{//fh pointed to one of the halfedges now assigned to new_fh
|
||||
set_halfedge_handle(old_fh, heh1);
|
||||
}
|
||||
adjust_outgoing_halfedge(vh0);
|
||||
adjust_outgoing_halfedge(vh1);
|
||||
return heh0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::triangulate(FaceHandle _fh)
|
||||
{
|
||||
/*
|
||||
Split an arbitrary face into triangles by connecting
|
||||
each vertex of fh after its second to vh.
|
||||
|
||||
- fh will remain valid (it will become one of the
|
||||
triangles)
|
||||
- the halfedge handles of the new triangles will
|
||||
point to the old halfedges
|
||||
*/
|
||||
|
||||
HalfedgeHandle base_heh(halfedge_handle(_fh));
|
||||
VertexHandle start_vh = from_vertex_handle(base_heh);
|
||||
HalfedgeHandle next_heh(next_halfedge_handle(base_heh));
|
||||
|
||||
while (to_vertex_handle(next_halfedge_handle(next_heh)) != start_vh)
|
||||
{
|
||||
HalfedgeHandle next_next_heh(next_halfedge_handle(next_heh));
|
||||
|
||||
FaceHandle new_fh = new_face();
|
||||
set_halfedge_handle(new_fh, base_heh);
|
||||
|
||||
HalfedgeHandle new_heh = new_edge(to_vertex_handle(next_heh), start_vh);
|
||||
|
||||
set_next_halfedge_handle(base_heh, next_heh);
|
||||
set_next_halfedge_handle(next_heh, new_heh);
|
||||
set_next_halfedge_handle(new_heh, base_heh);
|
||||
|
||||
set_face_handle(base_heh, new_fh);
|
||||
set_face_handle(next_heh, new_fh);
|
||||
set_face_handle(new_heh, new_fh);
|
||||
|
||||
base_heh = opposite_halfedge_handle(new_heh);
|
||||
next_heh = next_next_heh;
|
||||
}
|
||||
set_halfedge_handle(_fh, base_heh); //the last face takes the handle _fh
|
||||
|
||||
set_next_halfedge_handle(base_heh, next_heh);
|
||||
set_next_halfedge_handle(next_halfedge_handle(next_heh), base_heh);
|
||||
|
||||
set_face_handle(base_heh, _fh);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::triangulate()
|
||||
{
|
||||
/* The iterators will stay valid, even though new faces are added,
|
||||
because they are now implemented index-based instead of
|
||||
pointer-based.
|
||||
*/
|
||||
FaceIter f_it(faces_begin()), f_end(faces_end());
|
||||
for (; f_it!=f_end; ++f_it)
|
||||
triangulate(f_it);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void PolyConnectivity::split(FaceHandle fh, VertexHandle vh)
|
||||
{
|
||||
/*
|
||||
Split an arbitrary face into triangles by connecting
|
||||
each vertex of fh to vh.
|
||||
|
||||
- fh will remain valid (it will become one of the
|
||||
triangles)
|
||||
- the halfedge handles of the new triangles will
|
||||
point to the old halfeges
|
||||
*/
|
||||
|
||||
HalfedgeHandle hend = halfedge_handle(fh);
|
||||
HalfedgeHandle hh = next_halfedge_handle(hend);
|
||||
|
||||
HalfedgeHandle hold = new_edge(to_vertex_handle(hend), vh);
|
||||
|
||||
set_next_halfedge_handle(hend, hold);
|
||||
set_face_handle(hold, fh);
|
||||
|
||||
hold = opposite_halfedge_handle(hold);
|
||||
|
||||
while (hh != hend) {
|
||||
|
||||
HalfedgeHandle hnext = next_halfedge_handle(hh);
|
||||
|
||||
FaceHandle fnew = new_face();
|
||||
set_halfedge_handle(fnew, hh);
|
||||
|
||||
HalfedgeHandle hnew = new_edge(to_vertex_handle(hh), vh);
|
||||
|
||||
set_next_halfedge_handle(hnew, hold);
|
||||
set_next_halfedge_handle(hold, hh);
|
||||
set_next_halfedge_handle(hh, hnew);
|
||||
|
||||
set_face_handle(hnew, fnew);
|
||||
set_face_handle(hold, fnew);
|
||||
set_face_handle(hh, fnew);
|
||||
|
||||
hold = opposite_halfedge_handle(hnew);
|
||||
|
||||
hh = hnext;
|
||||
}
|
||||
|
||||
set_next_halfedge_handle(hold, hend);
|
||||
set_next_halfedge_handle(next_halfedge_handle(hend), hold);
|
||||
|
||||
set_face_handle(hold, fh);
|
||||
|
||||
set_halfedge_handle(vh, hold);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint PolyConnectivity::valence(VertexHandle _vh) const
|
||||
{
|
||||
uint count(0);
|
||||
for (ConstVertexVertexIter vv_it=cvv_iter(_vh); vv_it; ++vv_it)
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint PolyConnectivity::valence(FaceHandle _fh) const
|
||||
{
|
||||
uint count(0);
|
||||
for (ConstFaceVertexIter fv_it=cfv_iter(_fh); fv_it; ++fv_it)
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
}//namespace OpenMesh
|
||||
|
||||
513
Core/Mesh/PolyConnectivity.hh
Normal file
513
Core/Mesh/PolyConnectivity.hh
Normal file
@@ -0,0 +1,513 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2004 by Computer Graphics Group, RWTH Aachen *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* License *
|
||||
* *
|
||||
* This library 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, version 2.1. *
|
||||
* *
|
||||
* This library 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 Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
|
||||
#ifndef OPENMESH_POLYCONNECTIVITY_HH
|
||||
#define OPENMESH_POLYCONNECTIVITY_HH
|
||||
|
||||
#include <OpenMesh/Core/Mesh/ArrayKernel.hh>
|
||||
#include <OpenMesh/Core/Mesh/IteratorsT.hh>
|
||||
#include <OpenMesh/Core/Mesh/CirculatorsT.hh>
|
||||
|
||||
namespace OpenMesh
|
||||
{
|
||||
|
||||
class PolyConnectivity : public ArrayKernel
|
||||
{
|
||||
public:
|
||||
/// \name Mesh Handles
|
||||
//@{
|
||||
/// Invalid handle
|
||||
static const VertexHandle InvalidVertexHandle;
|
||||
/// Invalid handle
|
||||
static const HalfedgeHandle InvalidHalfedgeHandle;
|
||||
/// Invalid handle
|
||||
static const EdgeHandle InvalidEdgeHandle;
|
||||
/// Invalid handle
|
||||
static const FaceHandle InvalidFaceHandle;
|
||||
//@}
|
||||
|
||||
typedef PolyConnectivity This;
|
||||
|
||||
//--- iterators ---
|
||||
|
||||
/** \name Mesh Iterators
|
||||
Refer to OpenMesh::Mesh::Iterators or \ref mesh_iterators for
|
||||
documentation.
|
||||
*/
|
||||
//@{
|
||||
/// Linear iterator
|
||||
typedef Iterators::VertexIterT<This> VertexIter;
|
||||
typedef Iterators::HalfedgeIterT<This> HalfedgeIter;
|
||||
typedef Iterators::EdgeIterT<This> EdgeIter;
|
||||
typedef Iterators::FaceIterT<This> FaceIter;
|
||||
|
||||
typedef Iterators::ConstVertexIterT<This> ConstVertexIter;
|
||||
typedef Iterators::ConstHalfedgeIterT<This> ConstHalfedgeIter;
|
||||
typedef Iterators::ConstEdgeIterT<This> ConstEdgeIter;
|
||||
typedef Iterators::ConstFaceIterT<This> ConstFaceIter;
|
||||
//@}
|
||||
|
||||
//--- circulators ---
|
||||
|
||||
/** \name Mesh Circulators
|
||||
Refer to OpenMesh::Mesh::Iterators or \ref mesh_iterators
|
||||
for documentation.
|
||||
*/
|
||||
//@{
|
||||
/// Circulator
|
||||
typedef Iterators::VertexVertexIterT<This> VertexVertexIter;
|
||||
typedef Iterators::VertexOHalfedgeIterT<This> VertexOHalfedgeIter;
|
||||
typedef Iterators::VertexIHalfedgeIterT<This> VertexIHalfedgeIter;
|
||||
typedef Iterators::VertexEdgeIterT<This> VertexEdgeIter;
|
||||
typedef Iterators::VertexFaceIterT<This> VertexFaceIter;
|
||||
typedef Iterators::FaceVertexIterT<This> FaceVertexIter;
|
||||
typedef Iterators::FaceHalfedgeIterT<This> FaceHalfedgeIter;
|
||||
typedef Iterators::FaceEdgeIterT<This> FaceEdgeIter;
|
||||
typedef Iterators::FaceFaceIterT<This> FaceFaceIter;
|
||||
|
||||
typedef Iterators::ConstVertexVertexIterT<This> ConstVertexVertexIter;
|
||||
typedef Iterators::ConstVertexOHalfedgeIterT<This> ConstVertexOHalfedgeIter;
|
||||
typedef Iterators::ConstVertexIHalfedgeIterT<This> ConstVertexIHalfedgeIter;
|
||||
typedef Iterators::ConstVertexEdgeIterT<This> ConstVertexEdgeIter;
|
||||
typedef Iterators::ConstVertexFaceIterT<This> ConstVertexFaceIter;
|
||||
typedef Iterators::ConstFaceVertexIterT<This> ConstFaceVertexIter;
|
||||
typedef Iterators::ConstFaceHalfedgeIterT<This> ConstFaceHalfedgeIter;
|
||||
typedef Iterators::ConstFaceEdgeIterT<This> ConstFaceEdgeIter;
|
||||
typedef Iterators::ConstFaceFaceIterT<This> ConstFaceFaceIter;
|
||||
//@}
|
||||
|
||||
// --- shortcuts
|
||||
|
||||
/** \name Typedef Shortcuts
|
||||
Provided for convenience only
|
||||
*/
|
||||
//@{
|
||||
/// Alias typedef
|
||||
typedef VertexHandle VHandle;
|
||||
typedef HalfedgeHandle HHandle;
|
||||
typedef EdgeHandle EHandle;
|
||||
typedef FaceHandle FHandle;
|
||||
|
||||
typedef VertexIter VIter;
|
||||
typedef HalfedgeIter HIter;
|
||||
typedef EdgeIter EIter;
|
||||
typedef FaceIter FIter;
|
||||
|
||||
typedef ConstVertexIter CVIter;
|
||||
typedef ConstHalfedgeIter CHIter;
|
||||
typedef ConstEdgeIter CEIter;
|
||||
typedef ConstFaceIter CFIter;
|
||||
|
||||
typedef VertexVertexIter VVIter;
|
||||
typedef VertexOHalfedgeIter VOHIter;
|
||||
typedef VertexIHalfedgeIter VIHIter;
|
||||
typedef VertexEdgeIter VEIter;
|
||||
typedef VertexFaceIter VFIter;
|
||||
typedef FaceVertexIter FVIter;
|
||||
typedef FaceHalfedgeIter FHIter;
|
||||
typedef FaceEdgeIter FEIter;
|
||||
typedef FaceFaceIter FFIter;
|
||||
|
||||
typedef ConstVertexVertexIter CVVIter;
|
||||
typedef ConstVertexOHalfedgeIter CVOHIter;
|
||||
typedef ConstVertexIHalfedgeIter CVIHIter;
|
||||
typedef ConstVertexEdgeIter CVEIter;
|
||||
typedef ConstVertexFaceIter CVFIter;
|
||||
typedef ConstFaceVertexIter CFVIter;
|
||||
typedef ConstFaceHalfedgeIter CFHIter;
|
||||
typedef ConstFaceEdgeIter CFEIter;
|
||||
typedef ConstFaceFaceIter CFFIter;
|
||||
//@}
|
||||
|
||||
public:
|
||||
|
||||
PolyConnectivity() {}
|
||||
virtual ~PolyConnectivity() {}
|
||||
|
||||
inline static bool is_triangles()
|
||||
{ return false; }
|
||||
|
||||
/** assign_connectivity() method. See ArrayKernel::assign_connectivity()
|
||||
for more details. */
|
||||
inline void assign_connectivity(const PolyConnectivity& _other)
|
||||
{ ArrayKernel::assign_connectivity(_other); }
|
||||
|
||||
/** \name Adding items to a mesh
|
||||
*/
|
||||
//@{
|
||||
/// Add a new vertex
|
||||
inline VertexHandle add_vertex()
|
||||
{ return new_vertex(); }
|
||||
|
||||
/// Add and connect a new face
|
||||
FaceHandle add_face(const std::vector<VertexHandle>& _vhandles)
|
||||
{ return add_face(&_vhandles.front(), _vhandles.size()); }
|
||||
|
||||
FaceHandle add_face(VertexHandle _vh0, VertexHandle _vh1, VertexHandle _vh2)
|
||||
{
|
||||
VertexHandle vhs[3] = { _vh0, _vh1, _vh2 };
|
||||
return add_face(vhs, 3);
|
||||
}
|
||||
|
||||
FaceHandle add_face(VertexHandle _vh0, VertexHandle _vh1, VertexHandle _vh2, VertexHandle _vh3)
|
||||
{
|
||||
VertexHandle vhs[4] = { _vh0, _vh1, _vh2, _vh3 };
|
||||
return add_face(vhs, 4);
|
||||
}
|
||||
|
||||
FaceHandle add_face(const VertexHandle* _vhandles, uint _vhs_size);
|
||||
//@}
|
||||
|
||||
/// \name Deleting mesh items and other connectivity/topology modifications
|
||||
//@{
|
||||
|
||||
/** Mark vertex and all incident edges and faces deleted.
|
||||
Items marked deleted will be removed by garbageCollection().
|
||||
\attention Needs the Attributes::Status attribute for vertices,
|
||||
edges and faces.
|
||||
*/
|
||||
void delete_vertex(VertexHandle _vh, bool _delete_isolated_vertices = true);
|
||||
|
||||
/** Mark edge (two opposite halfedges) and incident faces deleted.
|
||||
Resulting isolated vertices are marked deleted if
|
||||
_delete_isolated_vertices is true. Items marked deleted will be
|
||||
removed by garbageCollection().
|
||||
|
||||
\attention Needs the Attributes::Status attribute for vertices,
|
||||
edges and faces.
|
||||
*/
|
||||
void delete_edge(EdgeHandle _eh, bool _delete_isolated_vertices=true);
|
||||
|
||||
/** Delete face _fh and resulting degenerated empty halfedges as
|
||||
well. Resultling isolated vertices will be deleted if
|
||||
_delete_isolated_vertices is true.
|
||||
|
||||
\attention All item will only be marked to be deleted. They will
|
||||
actually be removed by calling garbage_collection().
|
||||
|
||||
\attention Needs the Attributes::Status attribute for vertices,
|
||||
edges and faces.
|
||||
*/
|
||||
void delete_face(FaceHandle _fh, bool _delete_isolated_vertices=true);
|
||||
|
||||
//@}
|
||||
|
||||
/** \name Begin and end iterators
|
||||
*/
|
||||
//@{
|
||||
|
||||
/// Begin iterator for vertices
|
||||
VertexIter vertices_begin()
|
||||
{ return VertexIter(*this, VertexHandle(0)); }
|
||||
/// Const begin iterator for vertices
|
||||
ConstVertexIter vertices_begin() const
|
||||
{ return ConstVertexIter(*this, VertexHandle(0)); }
|
||||
/// End iterator for vertices
|
||||
VertexIter vertices_end()
|
||||
{ return VertexIter(*this, VertexHandle(n_vertices())); }
|
||||
/// Const end iterator for vertices
|
||||
ConstVertexIter vertices_end() const
|
||||
{ return ConstVertexIter(*this, VertexHandle(n_vertices())); }
|
||||
|
||||
/// Begin iterator for halfedges
|
||||
HalfedgeIter halfedges_begin()
|
||||
{ return HalfedgeIter(*this, HalfedgeHandle(0)); }
|
||||
/// Const begin iterator for halfedges
|
||||
ConstHalfedgeIter halfedges_begin() const
|
||||
{ return ConstHalfedgeIter(*this, HalfedgeHandle(0)); }
|
||||
/// End iterator for halfedges
|
||||
HalfedgeIter halfedges_end()
|
||||
{ return HalfedgeIter(*this, HalfedgeHandle(n_halfedges())); }
|
||||
/// Const end iterator for halfedges
|
||||
ConstHalfedgeIter halfedges_end() const
|
||||
{ return ConstHalfedgeIter(*this, HalfedgeHandle(n_halfedges())); }
|
||||
|
||||
/// Begin iterator for edges
|
||||
EdgeIter edges_begin()
|
||||
{ return EdgeIter(*this, EdgeHandle(0)); }
|
||||
/// Const begin iterator for edges
|
||||
ConstEdgeIter edges_begin() const
|
||||
{ return ConstEdgeIter(*this, EdgeHandle(0)); }
|
||||
/// End iterator for edges
|
||||
EdgeIter edges_end()
|
||||
{ return EdgeIter(*this, EdgeHandle(n_edges())); }
|
||||
/// Const end iterator for edges
|
||||
ConstEdgeIter edges_end() const
|
||||
{ return ConstEdgeIter(*this, EdgeHandle(n_edges())); }
|
||||
|
||||
/// Begin iterator for faces
|
||||
FaceIter faces_begin()
|
||||
{ return FaceIter(*this, FaceHandle(0)); }
|
||||
/// Const begin iterator for faces
|
||||
ConstFaceIter faces_begin() const
|
||||
{ return ConstFaceIter(*this, FaceHandle(0)); }
|
||||
/// End iterator for faces
|
||||
FaceIter faces_end()
|
||||
{ return FaceIter(*this, FaceHandle(n_faces())); }
|
||||
/// Const end iterator for faces
|
||||
ConstFaceIter faces_end() const
|
||||
{ return ConstFaceIter(*this, FaceHandle(n_faces())); }
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
|
||||
/** \name Begin for skipping iterators
|
||||
*/
|
||||
//@{
|
||||
|
||||
/// Begin iterator for vertices
|
||||
VertexIter vertices_sbegin()
|
||||
{ return VertexIter(*this, VertexHandle(0), true); }
|
||||
/// Const begin iterator for vertices
|
||||
ConstVertexIter vertices_sbegin() const
|
||||
{ return ConstVertexIter(*this, VertexHandle(0), true); }
|
||||
|
||||
/// Begin iterator for halfedges
|
||||
HalfedgeIter halfedges_sbegin()
|
||||
{ return HalfedgeIter(*this, HalfedgeHandle(0), true); }
|
||||
/// Const begin iterator for halfedges
|
||||
ConstHalfedgeIter halfedges_sbegin() const
|
||||
{ return ConstHalfedgeIter(*this, HalfedgeHandle(0), true); }
|
||||
|
||||
/// Begin iterator for edges
|
||||
EdgeIter edges_sbegin()
|
||||
{ return EdgeIter(*this, EdgeHandle(0), true); }
|
||||
/// Const begin iterator for edges
|
||||
ConstEdgeIter edges_sbegin() const
|
||||
{ return ConstEdgeIter(*this, EdgeHandle(0), true); }
|
||||
|
||||
/// Begin iterator for faces
|
||||
FaceIter faces_sbegin()
|
||||
{ return FaceIter(*this, FaceHandle(0), true); }
|
||||
/// Const begin iterator for faces
|
||||
ConstFaceIter faces_sbegin() const
|
||||
{ return ConstFaceIter(*this, FaceHandle(0), true); }
|
||||
|
||||
//@}
|
||||
|
||||
//--- circulators ---
|
||||
|
||||
/** \name Vertex and Face circulators
|
||||
*/
|
||||
//@{
|
||||
|
||||
/// vertex - vertex circulator
|
||||
VertexVertexIter vv_iter(VertexHandle _vh) {
|
||||
return VertexVertexIter(*this, _vh); }
|
||||
/// vertex - incoming halfedge circulator
|
||||
VertexIHalfedgeIter vih_iter(VertexHandle _vh)
|
||||
{ return VertexIHalfedgeIter(*this, _vh); }
|
||||
/// vertex - outgoing halfedge circulator
|
||||
VertexOHalfedgeIter voh_iter(VertexHandle _vh)
|
||||
{ return VertexOHalfedgeIter(*this, _vh); }
|
||||
/// vertex - edge circulator
|
||||
VertexEdgeIter ve_iter(VertexHandle _vh)
|
||||
{ return VertexEdgeIter(*this, _vh); }
|
||||
/// vertex - face circulator
|
||||
VertexFaceIter vf_iter(VertexHandle _vh)
|
||||
{ return VertexFaceIter(*this, _vh); }
|
||||
|
||||
/// const vertex circulator
|
||||
ConstVertexVertexIter cvv_iter(VertexHandle _vh) const
|
||||
{ return ConstVertexVertexIter(*this, _vh); }
|
||||
/// const vertex - incoming halfedge circulator
|
||||
ConstVertexIHalfedgeIter cvih_iter(VertexHandle _vh) const
|
||||
{ return ConstVertexIHalfedgeIter(*this, _vh); }
|
||||
/// const vertex - outgoing halfedge circulator
|
||||
ConstVertexOHalfedgeIter cvoh_iter(VertexHandle _vh) const
|
||||
{ return ConstVertexOHalfedgeIter(*this, _vh); }
|
||||
/// const vertex - edge circulator
|
||||
ConstVertexEdgeIter cve_iter(VertexHandle _vh) const
|
||||
{ return ConstVertexEdgeIter(*this, _vh); }
|
||||
/// const vertex - face circulator
|
||||
ConstVertexFaceIter cvf_iter(VertexHandle _vh) const
|
||||
{ return ConstVertexFaceIter(*this, _vh); }
|
||||
|
||||
/// face - vertex circulator
|
||||
FaceVertexIter fv_iter(FaceHandle _fh)
|
||||
{ return FaceVertexIter(*this, _fh); }
|
||||
/// face - halfedge circulator
|
||||
FaceHalfedgeIter fh_iter(FaceHandle _fh)
|
||||
{ return FaceHalfedgeIter(*this, _fh); }
|
||||
/// face - edge circulator
|
||||
FaceEdgeIter fe_iter(FaceHandle _fh)
|
||||
{ return FaceEdgeIter(*this, _fh); }
|
||||
/// face - face circulator
|
||||
FaceFaceIter ff_iter(FaceHandle _fh)
|
||||
{ return FaceFaceIter(*this, _fh); }
|
||||
|
||||
/// const face - vertex circulator
|
||||
ConstFaceVertexIter cfv_iter(FaceHandle _fh) const
|
||||
{ return ConstFaceVertexIter(*this, _fh); }
|
||||
/// const face - halfedge circulator
|
||||
ConstFaceHalfedgeIter cfh_iter(FaceHandle _fh) const
|
||||
{ return ConstFaceHalfedgeIter(*this, _fh); }
|
||||
/// const face - edge circulator
|
||||
ConstFaceEdgeIter cfe_iter(FaceHandle _fh) const
|
||||
{ return ConstFaceEdgeIter(*this, _fh); }
|
||||
/// const face - face circulator
|
||||
ConstFaceFaceIter cff_iter(FaceHandle _fh) const
|
||||
{ return ConstFaceFaceIter(*this, _fh); }
|
||||
//@}
|
||||
|
||||
/** \name Boundary and manifold tests
|
||||
*/
|
||||
//@{
|
||||
bool is_boundary(HalfedgeHandle _heh) const
|
||||
{ return ArrayKernel::is_boundary(_heh); }
|
||||
|
||||
/** Is the edge _eh a boundary edge, i.e. is one of its halfedges
|
||||
a boundary halfege ? */
|
||||
bool is_boundary(EdgeHandle _eh) const
|
||||
{
|
||||
return (is_boundary(halfedge_handle(_eh, 0)) ||
|
||||
is_boundary(halfedge_handle(_eh, 1)));
|
||||
}
|
||||
/// Is vertex _vh a boundary vertex ?
|
||||
bool is_boundary(VertexHandle _vh) const
|
||||
{
|
||||
HalfedgeHandle heh(halfedge_handle(_vh));
|
||||
return (!(heh.is_valid() && face_handle(heh).is_valid()));
|
||||
}
|
||||
|
||||
/** Is face _fh at boundary, i.e. is one of its edges (or vertices)
|
||||
* a boundary edge?
|
||||
* \param _fh Check this face
|
||||
* \param _check_vertex If \c true, check the corner vertices of
|
||||
* the face, too.
|
||||
*/
|
||||
bool is_boundary(FaceHandle _fh, bool _check_vertex=false) const;
|
||||
/// Is (the mesh at) vertex _vh two-manifold ?
|
||||
bool is_manifold(VertexHandle _vh) const;
|
||||
//@}
|
||||
|
||||
// --- shortcuts ---
|
||||
|
||||
/// returns the face handle of the opposite halfedge
|
||||
inline FaceHandle opposite_face_handle(HalfedgeHandle _heh) const
|
||||
{ return face_handle(opposite_halfedge_handle(_heh)); }
|
||||
|
||||
// --- misc ---
|
||||
|
||||
/** Adjust outgoing halfedge handle for vertices, so that it is a
|
||||
boundary halfedge whenever possible.
|
||||
*/
|
||||
void adjust_outgoing_halfedge(VertexHandle _vh);
|
||||
/// Find halfedge from _vh0 to _vh1. Returns invalid handle if not found.
|
||||
HalfedgeHandle find_halfedge(VertexHandle _start_vh, VertexHandle _end_vh) const;
|
||||
/// Vertex valence
|
||||
uint valence(VertexHandle _vh) const;
|
||||
/// Face valence
|
||||
uint valence(FaceHandle _fh) const;
|
||||
|
||||
// --- connectivity operattions
|
||||
|
||||
/** Halfedge collapse: collapse the from-vertex of halfedge _heh
|
||||
into its to-vertex.
|
||||
|
||||
\attention Needs vertex/edge/face status attribute in order to
|
||||
delete the items that degenerate.
|
||||
|
||||
\note This function does not perform a garbage collection. It
|
||||
only marks degenerate items as deleted.
|
||||
|
||||
\attention A halfedge collapse may lead to topological inconsistencies.
|
||||
Therefore you should check this using is_collapse_ok().
|
||||
\TODO: implement is_collapse_ok() const for polygonal/triangle meshes
|
||||
*/
|
||||
void collapse(HalfedgeHandle _heh);
|
||||
/** return true if the this the only link between the faces adjacent to _eh.
|
||||
_eh is allowed to be boundary, in which case true is returned iff _eh is
|
||||
the only boundary edge of its ajdacent face.
|
||||
*/
|
||||
bool is_simple_link(EdgeHandle _eh) const;
|
||||
/** return true if _fh shares only one edge with all of its adjacent faces.
|
||||
Boundary is treated as one face, i.e., the function false if _fh has more
|
||||
than one boundary edge.
|
||||
*/
|
||||
bool is_simply_connected(FaceHandle _fh) const;
|
||||
/** Removes the edge _eh. Its adjacent faces are merged. _eh and one of the
|
||||
adjacent faces are set deleted. The handle of the remaining face is
|
||||
returned (InvalidFaceHandle is returned if _eh is a boundary edge).
|
||||
|
||||
\precondition is_simple_link(_eh). This ensures that there are no hole faces
|
||||
or isolated vertices appearing in result of the operation.
|
||||
|
||||
\attention Needs the Attributes::Status attribute for edges and faces.
|
||||
|
||||
\note This function does not perform a garbage collection. It
|
||||
only marks items as deleted.
|
||||
*/
|
||||
FaceHandle remove_edge(EdgeHandle _eh);
|
||||
/** Inverse of remove_edge. _eh should be the handle of the edge and the
|
||||
vertex and halfedge handles pointed by edge(_eh) should be valid.
|
||||
*/
|
||||
void reinsert_edge(EdgeHandle _eh);
|
||||
/** Inserts an edge between to_vh(_prev_heh) and from_vh(_next_heh).
|
||||
A new face is created started at heh0 of the inserted edge and
|
||||
its halfedges loop includes both _prev_heh and _next_heh. If an
|
||||
old face existed which includes the argument halfedges, it is
|
||||
split at the new edge. heh0 is returned.
|
||||
|
||||
\note assumes _prev_heh and _next_heh are either boundary or pointed
|
||||
to the same face
|
||||
*/
|
||||
HalfedgeHandle insert_edge(HalfedgeHandle _prev_heh, HalfedgeHandle _next_heh);
|
||||
|
||||
/// Face split (= 1-to-n split)
|
||||
void split(FaceHandle _fh, VertexHandle _vh);
|
||||
/// triangulate the face _fh
|
||||
void triangulate(FaceHandle _fh);
|
||||
/// triangulate the entire mesh
|
||||
void triangulate();
|
||||
|
||||
|
||||
/** \name Generic handle derefertiation.
|
||||
Calls the respective vertex(), halfedge(), edge(), face()
|
||||
method of the mesh kernel.
|
||||
*/
|
||||
//@{
|
||||
/// Get item from handle
|
||||
const Vertex& deref(VertexHandle _h) const { return vertex(_h); }
|
||||
Vertex& deref(VertexHandle _h) { return vertex(_h); }
|
||||
const Halfedge& deref(HalfedgeHandle _h) const { return halfedge(_h); }
|
||||
Halfedge& deref(HalfedgeHandle _h) { return halfedge(_h); }
|
||||
const Edge& deref(EdgeHandle _h) const { return edge(_h); }
|
||||
Edge& deref(EdgeHandle _h) { return edge(_h); }
|
||||
const Face& deref(FaceHandle _h) const { return face(_h); }
|
||||
Face& deref(FaceHandle _h) { return face(_h); }
|
||||
//@}
|
||||
|
||||
protected:
|
||||
/// Helper for halfedge collapse
|
||||
void collapse_edge(HalfedgeHandle _hh);
|
||||
/// Helper for halfedge collapse
|
||||
void collapse_loop(HalfedgeHandle _hh);
|
||||
};
|
||||
|
||||
}//namespace OpenMesh
|
||||
|
||||
#endif//OPENMESH_POLYCONNECTIVITY_HH
|
||||
265
Core/Mesh/PolyMeshT.cc
Normal file
265
Core/Mesh/PolyMeshT.cc
Normal file
@@ -0,0 +1,265 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS PolyMeshT - IMPLEMENTATION
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#define OPENMESH_POLYMESH_C
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/Mesh/PolyMeshT.hh>
|
||||
#include <OpenMesh/Core/Geometry/LoopSchemeMaskT.hh>
|
||||
#include <OpenMesh/Core/Utils/vector_cast.hh>
|
||||
#include <OpenMesh/Core/System/omstream.hh>
|
||||
#include <vector>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
//== IMPLEMENTATION ==========================================================
|
||||
|
||||
template <class Kernel>
|
||||
uint PolyMeshT<Kernel>::find_feature_edges(Scalar _angle_tresh)
|
||||
{
|
||||
assert(Kernel::has_edge_status());//this function needs edge status property
|
||||
uint n_feature_edges = 0;
|
||||
for (EdgeIter e_it = Kernel::edges_begin(); e_it != Kernel::edges_end(); ++e_it)
|
||||
{
|
||||
if (fabs(calc_dihedral_angle(e_it)) > _angle_tresh)
|
||||
{//note: could be optimized by comparing cos(dih_angle) vs. cos(_angle_tresh)
|
||||
status(e_it).set_feature(true);
|
||||
n_feature_edges++;
|
||||
}
|
||||
else
|
||||
{
|
||||
status(e_it).set_feature(false);
|
||||
}
|
||||
}
|
||||
return n_feature_edges;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class Kernel>
|
||||
typename PolyMeshT<Kernel>::Normal
|
||||
PolyMeshT<Kernel>::
|
||||
calc_face_normal(FaceHandle _fh) const
|
||||
{
|
||||
assert(halfedge_handle(_fh).is_valid());
|
||||
ConstFaceVertexIter fv_it(cfv_iter(_fh));
|
||||
|
||||
const Point& p0(point(fv_it)); ++fv_it;
|
||||
const Point& p1(point(fv_it)); ++fv_it;
|
||||
const Point& p2(point(fv_it));
|
||||
|
||||
return calc_face_normal(p0, p1, p2);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class Kernel>
|
||||
typename PolyMeshT<Kernel>::Normal
|
||||
PolyMeshT<Kernel>::
|
||||
calc_face_normal(const Point& _p0,
|
||||
const Point& _p1,
|
||||
const Point& _p2) const
|
||||
{
|
||||
#if 1
|
||||
// The OpenSG <Vector>::operator -= () does not support the type Point
|
||||
// as rhs. Therefore use vector_cast at this point!!!
|
||||
// Note! OpenSG distinguishes between Normal and Point!!!
|
||||
Normal p1p0(_p0); p1p0 -= vector_cast<Normal>(_p1);
|
||||
Normal p1p2(_p2); p1p2 -= vector_cast<Normal>(_p1);
|
||||
|
||||
Normal n = cross(p1p2, p1p0);
|
||||
Scalar norm = n.length();
|
||||
|
||||
// The expression ((n *= (1.0/norm)),n) is used because the OpenSG
|
||||
// vector class does not return self after component-wise
|
||||
// self-multiplication with a scalar!!!
|
||||
return (norm != Scalar(0)) ? ((n *= (Scalar(1)/norm)),n) : Normal(0,0,0);
|
||||
#else
|
||||
Point p1p0 = _p0; p1p0 -= _p1;
|
||||
Point p1p2 = _p2; p1p2 -= _p1;
|
||||
|
||||
Normal n = vector_cast<Normal>(cross(p1p2, p1p0));
|
||||
Scalar norm = n.length();
|
||||
|
||||
return (norm != 0.0) ? n *= (1.0/norm) : Normal(0,0,0);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <class Kernel>
|
||||
void
|
||||
PolyMeshT<Kernel>::
|
||||
calc_face_centroid(FaceHandle _fh, Point& _pt) const
|
||||
{
|
||||
_pt.vectorize(0);
|
||||
uint valence = 0;
|
||||
for (ConstFaceVertexIter cfv_it = cfv_iter(_fh); cfv_it; ++cfv_it, ++valence)
|
||||
{
|
||||
_pt += point(cfv_it);
|
||||
}
|
||||
_pt /= valence;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class Kernel>
|
||||
void
|
||||
PolyMeshT<Kernel>::
|
||||
update_normals()
|
||||
{
|
||||
if (Kernel::has_face_normals()) update_face_normals();
|
||||
if (Kernel::has_vertex_normals()) update_vertex_normals();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class Kernel>
|
||||
void
|
||||
PolyMeshT<Kernel>::
|
||||
update_face_normals()
|
||||
{
|
||||
FaceIter f_it(Kernel::faces_begin()), f_end(Kernel::faces_end());
|
||||
|
||||
for (; f_it != f_end; ++f_it)
|
||||
set_normal(f_it.handle(), calc_face_normal(f_it.handle()));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class Kernel>
|
||||
typename PolyMeshT<Kernel>::Normal
|
||||
PolyMeshT<Kernel>::
|
||||
calc_vertex_normal(VertexHandle _vh) const
|
||||
{
|
||||
Normal n;
|
||||
calc_vertex_normal_fast(_vh,n);
|
||||
|
||||
Scalar norm = n.length();
|
||||
if (norm != 0.0) n *= (1.0/norm);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class Kernel>
|
||||
void PolyMeshT<Kernel>::
|
||||
calc_vertex_normal_fast(VertexHandle _vh, Normal& _n) const
|
||||
{
|
||||
_n.vectorize(0.0);
|
||||
for (ConstVertexFaceIter vf_it=cvf_iter(_vh); vf_it; ++vf_it)
|
||||
_n += normal(vf_it.handle());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class Kernel>
|
||||
void PolyMeshT<Kernel>::
|
||||
calc_vertex_normal_correct(VertexHandle _vh, Normal& _n) const
|
||||
{
|
||||
_n.vectorize(0.0);
|
||||
ConstVertexIHalfedgeIter cvih_it = cvih_iter(_vh);
|
||||
if (!cvih_it)
|
||||
{//don't crash on isolated vertices
|
||||
return;
|
||||
}
|
||||
Normal in_he_vec;
|
||||
calc_edge_vector(cvih_it, in_he_vec);
|
||||
for ( ; cvih_it; ++cvih_it)
|
||||
{//calculates the sector normal defined by cvih_it and adds it to _n
|
||||
if (is_boundary(cvih_it))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
HalfedgeHandle out_heh(next_halfedge_handle(cvih_it));
|
||||
Normal out_he_vec;
|
||||
calc_edge_vector(out_heh, out_he_vec);
|
||||
_n += cross(in_he_vec, out_he_vec);//sector area is taken into account
|
||||
in_he_vec = out_he_vec;
|
||||
in_he_vec *= -1;//change the orientation
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class Kernel>
|
||||
void PolyMeshT<Kernel>::
|
||||
calc_vertex_normal_loop(VertexHandle _vh, Normal& _n) const
|
||||
{
|
||||
static const LoopSchemeMaskDouble& loop_scheme_mask__ =
|
||||
LoopSchemeMaskDoubleSingleton::Instance();
|
||||
|
||||
Normal t_v(0.0,0.0,0.0), t_w(0.0,0.0,0.0);
|
||||
unsigned int vh_val = valence(_vh);
|
||||
unsigned int i = 0;
|
||||
for (ConstVertexOHalfedgeIter cvoh_it = cvoh_iter(_vh); cvoh_it; ++cvoh_it, ++i)
|
||||
{
|
||||
VertexHandle r1_v(to_vertex_handle(cvoh_it));
|
||||
t_v += (typename Point::value_type)(loop_scheme_mask__.tang0_weight(vh_val, i))*point(r1_v);
|
||||
t_w += (typename Point::value_type)(loop_scheme_mask__.tang1_weight(vh_val, i))*point(r1_v);
|
||||
}
|
||||
_n = cross(t_w, t_v);//hack: should be cross(t_v, t_w), but then the normals are reversed?
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <class Kernel>
|
||||
void
|
||||
PolyMeshT<Kernel>::
|
||||
update_vertex_normals()
|
||||
{
|
||||
VertexIter v_it(Kernel::vertices_begin()), v_end(Kernel::vertices_end());
|
||||
|
||||
for (; v_it!=v_end; ++v_it)
|
||||
set_normal(v_it.handle(), calc_vertex_normal(v_it.handle()));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
434
Core/Mesh/PolyMeshT.hh
Normal file
434
Core/Mesh/PolyMeshT.hh
Normal file
@@ -0,0 +1,434 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 2983 $
|
||||
// $Date: 2008-09-22 17:13:19 +0200 (Mo, 22. Sep 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS PolyMeshT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_POLYMESHT_HH
|
||||
#define OPENMESH_POLYMESHT_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Geometry/MathDefs.hh>
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
#include <vector>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class PolyMeshT PolyMeshT.hh <OpenMesh/Mesh/PolyMeshT.hh>
|
||||
|
||||
Base type for a polygonal mesh.
|
||||
|
||||
This is the base class for a polygonal mesh. It is parameterized
|
||||
by a mesh kernel that is given as a template argument. This class
|
||||
inherits all methods from its mesh kernel.
|
||||
|
||||
\param Kernel: template argument for the mesh kernel
|
||||
\note You should use the predefined mesh-kernel combinations in
|
||||
\ref mesh_types_group
|
||||
\see \ref mesh_type
|
||||
*/
|
||||
|
||||
template <class Kernel>
|
||||
class PolyMeshT : public Kernel
|
||||
{
|
||||
public:
|
||||
|
||||
/// Self type. Used to specify iterators/circulators.
|
||||
typedef PolyMeshT<Kernel> This;
|
||||
//--- item types ---
|
||||
|
||||
//@{
|
||||
/// Determine whether this is a PolyMeshT or TriMeshT
|
||||
enum { IsPolyMesh = 1 };
|
||||
enum { IsTriMesh = 0 };
|
||||
static bool is_polymesh() { return true; }
|
||||
static bool is_trimesh() { return false; }
|
||||
//@}
|
||||
|
||||
/// \name Mesh Items
|
||||
//@{
|
||||
/// Scalar type
|
||||
typedef typename Kernel::Scalar Scalar;
|
||||
/// Coordinate type
|
||||
typedef typename Kernel::Point Point;
|
||||
/// Normal type
|
||||
typedef typename Kernel::Normal Normal;
|
||||
/// Color type
|
||||
typedef typename Kernel::Color Color;
|
||||
/// TexCoord1D type
|
||||
typedef typename Kernel::TexCoord1D TexCoord1D;
|
||||
/// TexCoord2D type
|
||||
typedef typename Kernel::TexCoord2D TexCoord2D;
|
||||
/// TexCoord3D type
|
||||
typedef typename Kernel::TexCoord3D TexCoord3D;
|
||||
/// Vertex type
|
||||
typedef typename Kernel::Vertex Vertex;
|
||||
/// Halfedge type
|
||||
typedef typename Kernel::Halfedge Halfedge;
|
||||
/// Edge type
|
||||
typedef typename Kernel::Edge Edge;
|
||||
/// Face type
|
||||
typedef typename Kernel::Face Face;
|
||||
//@}
|
||||
|
||||
//--- handle types ---
|
||||
|
||||
/// Handle for referencing the corresponding item
|
||||
typedef typename Kernel::VertexHandle VertexHandle;
|
||||
typedef typename Kernel::HalfedgeHandle HalfedgeHandle;
|
||||
typedef typename Kernel::EdgeHandle EdgeHandle;
|
||||
typedef typename Kernel::FaceHandle FaceHandle;
|
||||
|
||||
|
||||
|
||||
typedef typename Kernel::VertexIter VertexIter;
|
||||
typedef typename Kernel::HalfedgeIter HalfedgeIter;
|
||||
typedef typename Kernel::EdgeIter EdgeIter;
|
||||
typedef typename Kernel::FaceIter FaceIter;
|
||||
|
||||
typedef typename Kernel::ConstVertexIter ConstVertexIter;
|
||||
typedef typename Kernel::ConstHalfedgeIter ConstHalfedgeIter;
|
||||
typedef typename Kernel::ConstEdgeIter ConstEdgeIter;
|
||||
typedef typename Kernel::ConstFaceIter ConstFaceIter;
|
||||
//@}
|
||||
|
||||
//--- circulators ---
|
||||
|
||||
/** \name Mesh Circulators
|
||||
Refer to OpenMesh::Mesh::Iterators or \ref mesh_iterators
|
||||
for documentation.
|
||||
*/
|
||||
//@{
|
||||
/// Circulator
|
||||
typedef typename Kernel::VertexVertexIter VertexVertexIter;
|
||||
typedef typename Kernel::VertexOHalfedgeIter VertexOHalfedgeIter;
|
||||
typedef typename Kernel::VertexIHalfedgeIter VertexIHalfedgeIter;
|
||||
typedef typename Kernel::VertexEdgeIter VertexEdgeIter;
|
||||
typedef typename Kernel::VertexFaceIter VertexFaceIter;
|
||||
typedef typename Kernel::FaceVertexIter FaceVertexIter;
|
||||
typedef typename Kernel::FaceHalfedgeIter FaceHalfedgeIter;
|
||||
typedef typename Kernel::FaceEdgeIter FaceEdgeIter;
|
||||
typedef typename Kernel::FaceFaceIter FaceFaceIter;
|
||||
|
||||
typedef typename Kernel::ConstVertexVertexIter ConstVertexVertexIter;
|
||||
typedef typename Kernel::ConstVertexOHalfedgeIter ConstVertexOHalfedgeIter;
|
||||
typedef typename Kernel::ConstVertexIHalfedgeIter ConstVertexIHalfedgeIter;
|
||||
typedef typename Kernel::ConstVertexEdgeIter ConstVertexEdgeIter;
|
||||
typedef typename Kernel::ConstVertexFaceIter ConstVertexFaceIter;
|
||||
typedef typename Kernel::ConstFaceVertexIter ConstFaceVertexIter;
|
||||
typedef typename Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter;
|
||||
typedef typename Kernel::ConstFaceEdgeIter ConstFaceEdgeIter;
|
||||
typedef typename Kernel::ConstFaceFaceIter ConstFaceFaceIter;
|
||||
//@}
|
||||
|
||||
|
||||
// --- constructor/destructor
|
||||
PolyMeshT() {}
|
||||
virtual ~PolyMeshT() {}
|
||||
|
||||
/** Uses default copy and assignment operator.
|
||||
Use them to assign two meshes of \b equal type.
|
||||
If the mesh types vary, use PolyMeshT::assign() instead. */
|
||||
|
||||
// --- creation ---
|
||||
inline VertexHandle new_vertex()
|
||||
{ return Kernel::new_vertex(); }
|
||||
|
||||
inline VertexHandle new_vertex(const Point& _p)
|
||||
{
|
||||
VertexHandle vh(Kernel::new_vertex());
|
||||
set_point(vh, _p);
|
||||
return vh;
|
||||
}
|
||||
|
||||
inline VertexHandle add_vertex(const Point& _p)
|
||||
{ return new_vertex(_p); }
|
||||
|
||||
// --- normal vectors ---
|
||||
|
||||
/** \name Normal vector computation
|
||||
*/
|
||||
//@{
|
||||
|
||||
/** Calls update_face_normals() and update_vertex_normals() if
|
||||
these normals (i.e. the properties) exist */
|
||||
void update_normals();
|
||||
|
||||
/// Update normal for face _fh
|
||||
void update_normal(FaceHandle _fh)
|
||||
{ set_normal(_fh, calc_face_normal(_fh)); }
|
||||
|
||||
/** Update normal vectors for all faces.
|
||||
\attention Needs the Attributes::Normal attribute for faces. */
|
||||
void update_face_normals();
|
||||
|
||||
/** Calculate normal vector for face _fh. */
|
||||
Normal calc_face_normal(FaceHandle _fh) const;
|
||||
|
||||
/** Calculate normal vector for face (_p0, _p1, _p2). */
|
||||
Normal calc_face_normal(const Point& _p0, const Point& _p1,
|
||||
const Point& _p2) const;
|
||||
// calculates the average of the vertices defining _fh
|
||||
void calc_face_centroid(FaceHandle _fh, Point& _pt) const;
|
||||
/// Update normal for vertex _vh
|
||||
void update_normal(VertexHandle _vh)
|
||||
{ set_normal(_vh, calc_vertex_normal(_vh)); }
|
||||
|
||||
/** Update normal vectors for all vertices. \attention Needs the
|
||||
Attributes::Normal attribute for faces and vertices. */
|
||||
void update_vertex_normals();
|
||||
|
||||
/** Calculate normal vector for vertex _vh by averaging normals
|
||||
of adjacent faces. Face normals have to be computed first.
|
||||
\attention Needs the Attributes::Normal attribute for faces. */
|
||||
Normal calc_vertex_normal(VertexHandle _vh) const;
|
||||
|
||||
/** Different methods for calculation of the normal at _vh:
|
||||
- -"-_fast - the default one - the same as calc vertex_normal()
|
||||
- needs the Attributes::Normal attribute for faces
|
||||
- -"-_correct - works properly for non-triangular meshes
|
||||
- does not need any attributes
|
||||
- -"-_loop - calculates loop surface normals
|
||||
- does not need any attributes */
|
||||
void calc_vertex_normal_fast(VertexHandle _vh, Normal& _n) const;
|
||||
void calc_vertex_normal_correct(VertexHandle _vh, Normal& _n) const;
|
||||
void calc_vertex_normal_loop(VertexHandle _vh, Normal& _n) const;
|
||||
|
||||
|
||||
//@}
|
||||
|
||||
// --- Geometry API - still in development ---
|
||||
|
||||
/** Calculates the edge vector as the vector defined by
|
||||
the halfedge with id #0 (see below) */
|
||||
void calc_edge_vector(EdgeHandle _eh, Normal& _edge_vec) const
|
||||
{ calc_edge_vector(halfedge_handle(_eh,0), _edge_vec); }
|
||||
|
||||
/** Calculates the edge vector as the difference of the
|
||||
the points defined by to_vertex_handle() and from_vertex_handle() */
|
||||
void calc_edge_vector(HalfedgeHandle _heh, Normal& _edge_vec) const
|
||||
{
|
||||
_edge_vec = point(to_vertex_handle(_heh));
|
||||
_edge_vec -= point(from_vertex_handle(_heh));
|
||||
}
|
||||
|
||||
// Calculates the length of the edge _eh
|
||||
Scalar calc_edge_length(EdgeHandle _eh) const
|
||||
{ return calc_edge_length(halfedge_handle(_eh,0)); }
|
||||
|
||||
/** Calculates the length of the edge _heh
|
||||
*/
|
||||
Scalar calc_edge_length(HalfedgeHandle _heh) const
|
||||
{ return (Scalar)sqrt(calc_edge_sqr_length(_heh)); }
|
||||
|
||||
Scalar calc_edge_sqr_length(EdgeHandle _eh) const
|
||||
{ return calc_edge_sqr_length(halfedge_handle(_eh,0)); }
|
||||
|
||||
Scalar calc_edge_sqr_length(HalfedgeHandle _heh) const
|
||||
{
|
||||
Normal edge_vec;
|
||||
calc_edge_vector(_heh, edge_vec);
|
||||
return edge_vec.sqrnorm();
|
||||
}
|
||||
|
||||
/** defines a consistent representation of a sector geometry:
|
||||
the halfedge _in_heh defines the sector orientation
|
||||
the vertex pointed by _in_heh defines the sector center
|
||||
_vec0 and _vec1 are resp. the first and the second vectors defining the sector */
|
||||
void calc_sector_vectors(HalfedgeHandle _in_heh, Normal& _vec0, Normal& _vec1) const
|
||||
{
|
||||
calc_edge_vector(next_halfedge_handle(_in_heh), _vec0);//p2 - p1
|
||||
calc_edge_vector(opposite_halfedge_handle(_in_heh), _vec1);//p0 - p1
|
||||
}
|
||||
|
||||
/** calculates the sector angle.\n
|
||||
* The vertex pointed by _in_heh defines the sector center
|
||||
* The angle will be calculated between the given halfedge and the next halfedge.\n
|
||||
* Seen from the center vertex this will be the next halfedge in clockwise direction.\n
|
||||
NOTE: only boundary concave sectors are treated correctly */
|
||||
Scalar calc_sector_angle(HalfedgeHandle _in_heh) const
|
||||
{
|
||||
Normal v0, v1;
|
||||
calc_sector_vectors(_in_heh, v0, v1);
|
||||
Scalar denom = v0.norm()*v1.norm();
|
||||
if (is_zero(denom))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Scalar cos_a = (v0 | v1) / denom;
|
||||
if (is_boundary(_in_heh))
|
||||
{//determine if the boundary sector is concave or convex
|
||||
FaceHandle fh(face_handle(opposite_halfedge_handle(_in_heh)));
|
||||
Normal f_n(calc_face_normal(fh));//this normal is (for convex fh) OK
|
||||
Scalar sign_a = dot(cross(v0, v1), f_n);
|
||||
return angle(cos_a, sign_a);
|
||||
}
|
||||
else
|
||||
{
|
||||
return acos(sane_aarg(cos_a));
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the cos and the sin of angle <(_in_heh,next_halfedge(_in_heh))
|
||||
/*
|
||||
void calc_sector_angle_cos_sin(HalfedgeHandle _in_heh, Scalar& _cos_a, Scalar& _sin_a) const
|
||||
{
|
||||
Normal in_vec, out_vec;
|
||||
calc_edge_vector(_in_heh, in_vec);
|
||||
calc_edge_vector(next_halfedge_handle(_in_heh), out_vec);
|
||||
Scalar denom = in_vec.norm()*out_vec.norm();
|
||||
if (is_zero(denom))
|
||||
{
|
||||
_cos_a = 1;
|
||||
_sin_a = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_cos_a = dot(in_vec, out_vec)/denom;
|
||||
_sin_a = cross(in_vec, out_vec).norm()/denom;
|
||||
}
|
||||
}
|
||||
*/
|
||||
/** calculates the normal (non-normalized) of the face sector defined by
|
||||
the angle <(_in_heh,next_halfedge(_in_heh)) */
|
||||
void calc_sector_normal(HalfedgeHandle _in_heh, Normal& _sector_normal) const
|
||||
{
|
||||
Normal vec0, vec1;
|
||||
calc_sector_vectors(_in_heh, vec0, vec1);
|
||||
_sector_normal = cross(vec0, vec1);//(p2-p1)^(p0-p1)
|
||||
}
|
||||
|
||||
/** calculates the area of the face sector defined by
|
||||
the angle <(_in_heh,next_halfedge(_in_heh))
|
||||
NOTE: special cases (e.g. concave sectors) are not handled correctly */
|
||||
Scalar calc_sector_area(HalfedgeHandle _in_heh) const
|
||||
{
|
||||
Normal sector_normal;
|
||||
calc_sector_normal(_in_heh, sector_normal);
|
||||
return sector_normal.norm()/2;
|
||||
}
|
||||
|
||||
/** calculates the dihedral angle on the halfedge _heh
|
||||
\attention Needs the Attributes::Normal attribute for faces */
|
||||
Scalar calc_dihedral_angle_fast(HalfedgeHandle _heh) const
|
||||
{
|
||||
CHECK(Kernel::has_face_normals());
|
||||
if (is_boundary(edge_handle(_heh)))
|
||||
{//the dihedral angle at a boundary edge is 0
|
||||
return 0;
|
||||
}
|
||||
const Normal& n0 = normal(face_handle(_heh));
|
||||
const Normal& n1 = normal(face_handle(opposite_halfedge_handle(_heh)));
|
||||
Normal he;
|
||||
calc_edge_vector(_heh, he);
|
||||
Scalar da_cos = dot(n0, n1);
|
||||
//should be normalized, but we need only the sign
|
||||
Scalar da_sin_sign = dot(cross(n0, n1), he);
|
||||
return angle(da_cos, da_sin_sign);
|
||||
}
|
||||
|
||||
/** calculates the dihedral angle on the edge _eh
|
||||
\attention Needs the Attributes::Normal attribute for faces */
|
||||
Scalar calc_dihedral_angle_fast(EdgeHandle _eh) const
|
||||
{ return calc_dihedral_angle_fast(halfedge_handle(_eh,0)); }
|
||||
|
||||
// calculates the dihedral angle on the halfedge _heh
|
||||
Scalar calc_dihedral_angle(HalfedgeHandle _heh) const
|
||||
{
|
||||
if (is_boundary(edge_handle(_heh)))
|
||||
{//the dihedral angle at a boundary edge is 0
|
||||
return 0;
|
||||
}
|
||||
Normal n0, n1, he;
|
||||
calc_sector_normal(_heh, n0);
|
||||
calc_sector_normal(opposite_halfedge_handle(_heh), n1);
|
||||
calc_edge_vector(_heh, he);
|
||||
Scalar denom = n0.norm()*n1.norm();
|
||||
if (denom == Scalar(0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Scalar da_cos = dot(n0, n1)/denom;
|
||||
//should be normalized, but we need only the sign
|
||||
Scalar da_sin_sign = dot(cross(n0, n1), he);
|
||||
return angle(da_cos, da_sin_sign);
|
||||
}
|
||||
|
||||
// calculates the dihedral angle on the edge _eh
|
||||
Scalar calc_dihedral_angle(EdgeHandle _eh) const
|
||||
{ return calc_dihedral_angle(halfedge_handle(_eh,0)); }
|
||||
|
||||
/** tags an edge as a feature if its dihedral angle is larger than _angle_tresh
|
||||
returns the number of the found feature edges, requires edge_status property*/
|
||||
uint find_feature_edges(Scalar _angle_tresh = OpenMesh::deg_to_rad(44.0));
|
||||
// --- misc ---
|
||||
|
||||
/// Face split (= 1-to-n split)
|
||||
inline void split(FaceHandle _fh, const Point& _p)
|
||||
{ Kernel::split(_fh, add_vertex(_p)); }
|
||||
|
||||
inline void split(FaceHandle _fh, VertexHandle _vh)
|
||||
{ Kernel::split(_fh, _vh); }
|
||||
|
||||
inline void split(EdgeHandle _eh, const Point& _p)
|
||||
{ Kernel::split(_eh, add_vertex(_p)); }
|
||||
|
||||
inline void split(EdgeHandle _eh, VertexHandle _vh)
|
||||
{ Kernel::split(_eh, _vh); }
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_POLYMESH_C)
|
||||
# define OPENMESH_POLYMESH_TEMPLATES
|
||||
# include "PolyMeshT.cc"
|
||||
#endif
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_POLYMESHT_HH defined
|
||||
//=============================================================================
|
||||
89
Core/Mesh/PolyMesh_ArrayKernelT.hh
Normal file
89
Core/Mesh/PolyMesh_ArrayKernelT.hh
Normal file
@@ -0,0 +1,89 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.1.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS PolyMesh_ArrayKernelT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_POLY_MESH_ARRAY_KERNEL_HH
|
||||
#define OPENMESH_POLY_MESH_ARRAY_KERNEL_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
#include <OpenMesh/Core/Mesh/Traits.hh>
|
||||
#include <OpenMesh/Core/Mesh/FinalMeshItemsT.hh>
|
||||
#include <OpenMesh/Core/Mesh/AttribKernelT.hh>
|
||||
#include <OpenMesh/Core/Mesh/PolyMeshT.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
/// Helper class to build a PolyMesh-type
|
||||
template <class Traits>
|
||||
struct PolyMesh_ArrayKernel_GeneratorT
|
||||
{
|
||||
typedef FinalMeshItemsT<Traits, false> MeshItems;
|
||||
typedef AttribKernelT<MeshItems, PolyConnectivity> AttribKernel;
|
||||
typedef PolyMeshT<AttribKernel> Mesh;
|
||||
};
|
||||
|
||||
|
||||
/** \class PolyMesh_ArrayKernelT PolyMesh_ArrayKernelT.hh <OpenMesh/Mesh/Types/PolyMesh_ArrayKernelT.hh>
|
||||
|
||||
\ingroup mesh_types_group
|
||||
Polygonal mesh based on the ArrayKernel.
|
||||
\see OpenMesh::PolyMeshT
|
||||
\see OpenMesh::ArrayKernel
|
||||
*/
|
||||
template <class Traits = DefaultTraits>
|
||||
class PolyMesh_ArrayKernelT
|
||||
: public PolyMesh_ArrayKernel_GeneratorT<Traits>::Mesh
|
||||
{};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_POLY_MESH_ARRAY_KERNEL_HH
|
||||
//=============================================================================
|
||||
158
Core/Mesh/Status.hh
Normal file
158
Core/Mesh/Status.hh
Normal file
@@ -0,0 +1,158 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.1.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS Status
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_ATTRIBUTE_STATUS_HH
|
||||
#define OPENMESH_ATTRIBUTE_STATUS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Attributes {
|
||||
|
||||
|
||||
//== CLASS DEFINITION ========================================================
|
||||
|
||||
|
||||
/** Status bits used by the Status class.
|
||||
* \see OpenMesh::Attributes::StatusInfo
|
||||
*/
|
||||
enum StatusBits {
|
||||
|
||||
DELETED = 1, ///< Item has been deleted
|
||||
LOCKED = 2, ///< Item is locked.
|
||||
SELECTED = 4, ///< Item is selected.
|
||||
HIDDEN = 8, ///< Item is hidden.
|
||||
FEATURE = 16, ///< Item is a feature or belongs to a feature.
|
||||
TAGGED = 32, ///< Item is tagged.
|
||||
TAGGED2 = 64, ///< Alternate bit for tagging an item.
|
||||
UNUSED = 128 ///<
|
||||
};
|
||||
|
||||
|
||||
/** \class StatusInfo Status.hh <OpenMesh/Attributes/Status.hh>
|
||||
*
|
||||
* Add status information to a base class.
|
||||
*
|
||||
* \see StatusBits
|
||||
*/
|
||||
class StatusInfo
|
||||
{
|
||||
public:
|
||||
|
||||
typedef unsigned int value_type;
|
||||
|
||||
StatusInfo() : status_(0) {}
|
||||
|
||||
/// is deleted ?
|
||||
bool deleted() const { return is_bit_set(DELETED); }
|
||||
/// set deleted
|
||||
void set_deleted(bool _b) { change_bit(DELETED, _b); }
|
||||
|
||||
|
||||
/// is locked ?
|
||||
bool locked() const { return is_bit_set(LOCKED); }
|
||||
/// set locked
|
||||
void set_locked(bool _b) { change_bit(LOCKED, _b); }
|
||||
|
||||
|
||||
/// is selected ?
|
||||
bool selected() const { return is_bit_set(SELECTED); }
|
||||
/// set selected
|
||||
void set_selected(bool _b) { change_bit(SELECTED, _b); }
|
||||
|
||||
|
||||
/// is hidden ?
|
||||
bool hidden() const { return is_bit_set(HIDDEN); }
|
||||
/// set hidden
|
||||
void set_hidden(bool _b) { change_bit(HIDDEN, _b); }
|
||||
|
||||
|
||||
/// is feature ?
|
||||
bool feature() const { return is_bit_set(FEATURE); }
|
||||
/// set feature
|
||||
void set_feature(bool _b) { change_bit(FEATURE, _b); }
|
||||
|
||||
|
||||
/// is tagged ?
|
||||
bool tagged() const { return is_bit_set(TAGGED); }
|
||||
/// set tagged
|
||||
void set_tagged(bool _b) { change_bit(TAGGED, _b); }
|
||||
|
||||
|
||||
/// is tagged2 ? This is just one more tag info.
|
||||
bool tagged2() const { return is_bit_set(TAGGED2); }
|
||||
/// set tagged
|
||||
void set_tagged2(bool _b) { change_bit(TAGGED2, _b); }
|
||||
|
||||
|
||||
/// return whole status
|
||||
unsigned int bits() const { return status_; }
|
||||
/// set whole status at once
|
||||
void set_bits(unsigned int _bits) { status_ = _bits; }
|
||||
|
||||
|
||||
/// is a certain bit set ?
|
||||
bool is_bit_set(unsigned int _s) const { return (status_ & _s) > 0; }
|
||||
/// set a certain bit
|
||||
void set_bit(unsigned int _s) { status_ |= _s; }
|
||||
/// unset a certain bit
|
||||
void unset_bit(unsigned int _s) { status_ &= ~_s; }
|
||||
/// set or unset a certain bit
|
||||
void change_bit(unsigned int _s, bool _b) {
|
||||
if (_b) status_ |= _s; else status_ &= ~_s; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
value_type status_;
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace Attributes
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_ATTRIBUTE_STATUS_HH defined
|
||||
//=============================================================================
|
||||
227
Core/Mesh/Traits.hh
Normal file
227
Core/Mesh/Traits.hh
Normal file
@@ -0,0 +1,227 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.1.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 3794 $
|
||||
// $Date: 2008-11-25 19:25:02 +0100 (Di, 25. Nov 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
/** \file Core/Mesh/Traits.hh
|
||||
This file defines the default traits and some convenience macros.
|
||||
*/
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS Traits
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef OPENMESH_TRAITS_HH
|
||||
#define OPENMESH_TRAITS_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Geometry/VectorT.hh>
|
||||
#include <OpenMesh/Core/Mesh/Attributes.hh>
|
||||
#include <OpenMesh/Core/Mesh/Handles.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/// Macro for defining the vertex attributes. See \ref mesh_type.
|
||||
#define VertexAttributes(_i) enum { VertexAttributes = _i }
|
||||
|
||||
/// Macro for defining the halfedge attributes. See \ref mesh_type.
|
||||
#define HalfedgeAttributes(_i) enum { HalfedgeAttributes = _i }
|
||||
|
||||
/// Macro for defining the edge attributes. See \ref mesh_type.
|
||||
#define EdgeAttributes(_i) enum { EdgeAttributes = _i }
|
||||
|
||||
/// Macro for defining the face attributes. See \ref mesh_type.
|
||||
#define FaceAttributes(_i) enum { FaceAttributes = _i }
|
||||
|
||||
/// Macro for defining the vertex traits. See \ref mesh_type.
|
||||
#define VertexTraits \
|
||||
template <class Base, class Refs> struct VertexT : public Base
|
||||
|
||||
/// Macro for defining the halfedge traits. See \ref mesh_type.
|
||||
#define HalfedgeTraits \
|
||||
template <class Base, class Refs> struct HalfedgeT : public Base
|
||||
|
||||
/// Macro for defining the edge traits. See \ref mesh_type.
|
||||
#define EdgeTraits \
|
||||
template <class Base, class Refs> struct EdgeT : public Base
|
||||
|
||||
/// Macro for defining the face traits. See \ref mesh_type.
|
||||
#define FaceTraits \
|
||||
template <class Base, class Refs> struct FaceT : public Base
|
||||
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class DefaultTraits Traits.hh <OpenMesh/Mesh/Traits.hh>
|
||||
|
||||
Base class for all traits. All user traits should be derived from
|
||||
this class. You may enrich all basic items by additional
|
||||
properties or define one or more of the types \c Point, \c Normal,
|
||||
\c TexCoord, or \c Color.
|
||||
|
||||
\see The Mesh docu section on \ref mesh_type.
|
||||
\see Traits.hh for a list of macros for traits classes.
|
||||
*/
|
||||
struct DefaultTraits
|
||||
{
|
||||
/// The default coordinate type is OpenMesh::Vec3f.
|
||||
typedef Vec3f Point;
|
||||
|
||||
/// The default normal type is OpenMesh::Vec3f.
|
||||
typedef Vec3f Normal;
|
||||
|
||||
/// The default 1D texture coordinate type is float.
|
||||
typedef float TexCoord1D;
|
||||
/// The default 2D texture coordinate type is OpenMesh::Vec2f.
|
||||
typedef Vec2f TexCoord2D;
|
||||
/// The default 3D texture coordinate type is OpenMesh::Vec3f.
|
||||
typedef Vec3f TexCoord3D;
|
||||
|
||||
/// The default texture index type
|
||||
typedef int TextureIndex;
|
||||
|
||||
/// The default color type is OpenMesh::Vec3uc.
|
||||
typedef Vec3uc Color;
|
||||
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
VertexTraits {};
|
||||
HalfedgeTraits {};
|
||||
EdgeTraits {};
|
||||
FaceTraits {};
|
||||
#endif
|
||||
|
||||
VertexAttributes(0);
|
||||
HalfedgeAttributes(Attributes::PrevHalfedge);
|
||||
EdgeAttributes(0);
|
||||
FaceAttributes(0);
|
||||
};
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** Helper class to merge two mesh traits.
|
||||
* \internal
|
||||
*
|
||||
* With the help of this class it's possible to merge two mesh traits.
|
||||
* Whereby \c _Traits1 overrides equally named symbols of \c _Traits2.
|
||||
*
|
||||
* For your convenience use the provided defines \c OM_Merge_Traits
|
||||
* and \c OM_Merge_Traits_In_Template instead.
|
||||
*
|
||||
* \see OM_Merge_Traits, OM_Merge_Traits_In_Template
|
||||
*/
|
||||
template <class _Traits1, class _Traits2> struct MergeTraits
|
||||
{
|
||||
#ifndef DOXY_IGNORE_THIS
|
||||
struct Result
|
||||
{
|
||||
// Mipspro needs this (strange) typedef
|
||||
typedef _Traits1 T1;
|
||||
typedef _Traits2 T2;
|
||||
|
||||
|
||||
VertexAttributes ( T1::VertexAttributes | T2::VertexAttributes );
|
||||
HalfedgeAttributes ( T1::HalfedgeAttributes | T2::HalfedgeAttributes );
|
||||
EdgeAttributes ( T1::EdgeAttributes | T2::EdgeAttributes );
|
||||
FaceAttributes ( T1::FaceAttributes | T2::FaceAttributes );
|
||||
|
||||
|
||||
typedef typename T1::Point Point;
|
||||
typedef typename T1::Normal Normal;
|
||||
typedef typename T1::Color Color;
|
||||
typedef typename T1::TexCoord TexCoord;
|
||||
|
||||
template <class Base, class Refs> class VertexT :
|
||||
public T1::template VertexT<
|
||||
typename T2::template VertexT<Base, Refs>, Refs>
|
||||
{};
|
||||
|
||||
template <class Base, class Refs> class HalfedgeT :
|
||||
public T1::template HalfedgeT<
|
||||
typename T2::template HalfedgeT<Base, Refs>, Refs>
|
||||
{};
|
||||
|
||||
|
||||
template <class Base, class Refs> class EdgeT :
|
||||
public T1::template EdgeT<
|
||||
typename T2::template EdgeT<Base, Refs>, Refs>
|
||||
{};
|
||||
|
||||
|
||||
template <class Base, class Refs> class FaceT :
|
||||
public T1::template FaceT<
|
||||
typename T2::template FaceT<Base, Refs>, Refs>
|
||||
{};
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Macro for merging two traits classes _S1 and _S2 into one traits class _D.
|
||||
Note that in case of ambiguities class _S1 overrides _S2, especially
|
||||
the point/normal/color/texcoord type to be used is taken from _S1::Point/
|
||||
_S1::Normal/_S1::Color/_S1::TexCoord.
|
||||
*/
|
||||
#define OM_Merge_Traits(_S1, _S2, _D) \
|
||||
typedef OpenMesh::MergeTraits<_S1, _S2>::Result _D;
|
||||
|
||||
|
||||
/**
|
||||
Macro for merging two traits classes _S1 and _S2 into one traits class _D.
|
||||
Same as OM_Merge_Traits, but this can be used inside template classes.
|
||||
*/
|
||||
#define OM_Merge_Traits_In_Template(_S1, _S2, _D) \
|
||||
typedef typename OpenMesh::MergeTraits<_S1, _S2>::Result _D;
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_TRAITS_HH defined
|
||||
//=============================================================================
|
||||
|
||||
448
Core/Mesh/TriConnectivity.cc
Normal file
448
Core/Mesh/TriConnectivity.cc
Normal file
@@ -0,0 +1,448 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
// CLASS TriMeshT - IMPLEMENTATION
|
||||
|
||||
#include <OpenMesh/Core/Mesh/TriConnectivity.hh>
|
||||
#include <OpenMesh/Core/System/omstream.hh>
|
||||
|
||||
namespace OpenMesh
|
||||
{
|
||||
|
||||
TriConnectivity::FaceHandle
|
||||
TriConnectivity::add_face(const VertexHandle* _vertex_handles, uint _vhs_size)
|
||||
{
|
||||
// need at least 3 vertices
|
||||
if (_vhs_size < 3) return InvalidFaceHandle;
|
||||
|
||||
/// face is triangle -> ok
|
||||
if (_vhs_size == 3)
|
||||
return PolyConnectivity::add_face(_vertex_handles, _vhs_size);
|
||||
|
||||
/// face is not a triangle -> triangulate
|
||||
else
|
||||
{
|
||||
//omlog() << "triangulating " << _vhs_size << "_gon\n";
|
||||
|
||||
VertexHandle vhandles[3];
|
||||
vhandles[0] = _vertex_handles[0];
|
||||
|
||||
FaceHandle fh;
|
||||
unsigned int i(1);
|
||||
--_vhs_size;
|
||||
|
||||
while (i < _vhs_size)
|
||||
{
|
||||
vhandles[1] = _vertex_handles[i];
|
||||
vhandles[2] = _vertex_handles[++i];
|
||||
fh = PolyConnectivity::add_face(vhandles, 3);
|
||||
}
|
||||
|
||||
return fh;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool TriConnectivity::is_collapse_ok(HalfedgeHandle v0v1)
|
||||
{
|
||||
HalfedgeHandle v1v0(opposite_halfedge_handle(v0v1));
|
||||
VertexHandle v0(to_vertex_handle(v1v0));
|
||||
VertexHandle v1(to_vertex_handle(v0v1));
|
||||
|
||||
// are vertices already deleted ?
|
||||
if (status(v0).deleted() || status(v1).deleted())
|
||||
return false;
|
||||
|
||||
|
||||
VertexHandle vl, vr;
|
||||
HalfedgeHandle h1, h2;
|
||||
|
||||
|
||||
// the edges v1-vl and vl-v0 must not be both boundary edges
|
||||
if (!is_boundary(v0v1))
|
||||
{
|
||||
vl = to_vertex_handle(next_halfedge_handle(v0v1));
|
||||
|
||||
h1 = next_halfedge_handle(v0v1);
|
||||
h2 = next_halfedge_handle(h1);
|
||||
if (is_boundary(opposite_halfedge_handle(h1)) &&
|
||||
is_boundary(opposite_halfedge_handle(h2)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// the edges v0-vr and vr-v1 must not be both boundary edges
|
||||
if (!is_boundary(v1v0))
|
||||
{
|
||||
vr = to_vertex_handle(next_halfedge_handle(v1v0));
|
||||
|
||||
h1 = next_halfedge_handle(v1v0);
|
||||
h2 = next_halfedge_handle(h1);
|
||||
if (is_boundary(opposite_halfedge_handle(h1)) &&
|
||||
is_boundary(opposite_halfedge_handle(h2)))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// if vl and vr are equal or both invalid -> fail
|
||||
if (vl == vr) return false;
|
||||
|
||||
|
||||
VertexVertexIter vv_it;
|
||||
|
||||
|
||||
// test intersection of the one-rings of v0 and v1
|
||||
for (vv_it = vv_iter(v0); vv_it; ++vv_it)
|
||||
status(vv_it).set_tagged(false);
|
||||
|
||||
for (vv_it = vv_iter(v1); vv_it; ++vv_it)
|
||||
status(vv_it).set_tagged(true);
|
||||
|
||||
for (vv_it = vv_iter(v0); vv_it; ++vv_it)
|
||||
if (status(vv_it).tagged() && vv_it.handle() != vl && vv_it.handle() != vr)
|
||||
return false;
|
||||
|
||||
|
||||
|
||||
// edge between two boundary vertices should be a boundary edge
|
||||
if ( is_boundary(v0) && is_boundary(v1) &&
|
||||
!is_boundary(v0v1) && !is_boundary(v1v0))
|
||||
return false;
|
||||
|
||||
// passed all tests
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
TriConnectivity::HalfedgeHandle
|
||||
TriConnectivity::vertex_split(VertexHandle v0, VertexHandle v1,
|
||||
VertexHandle vl, VertexHandle vr)
|
||||
{
|
||||
HalfedgeHandle v1vl, vlv1, vrv1, v0v1;
|
||||
|
||||
// build loop from halfedge v1->vl
|
||||
if (vl.is_valid())
|
||||
{
|
||||
v1vl = find_halfedge(v1, vl);
|
||||
assert(v1vl.is_valid());
|
||||
vlv1 = insert_loop(v1vl);
|
||||
}
|
||||
|
||||
// build loop from halfedge vr->v1
|
||||
if (vr.is_valid())
|
||||
{
|
||||
vrv1 = find_halfedge(vr, v1);
|
||||
assert(vrv1.is_valid());
|
||||
insert_loop(vrv1);
|
||||
}
|
||||
|
||||
// handle boundary cases
|
||||
if (!vl.is_valid())
|
||||
vlv1 = prev_halfedge_handle(halfedge_handle(v1));
|
||||
if (!vr.is_valid())
|
||||
vrv1 = prev_halfedge_handle(halfedge_handle(v1));
|
||||
|
||||
|
||||
// split vertex v1 into edge v0v1
|
||||
v0v1 = insert_edge(v0, vlv1, vrv1);
|
||||
|
||||
|
||||
return v0v1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
TriConnectivity::HalfedgeHandle
|
||||
TriConnectivity::insert_loop(HalfedgeHandle _hh)
|
||||
{
|
||||
HalfedgeHandle h0(_hh);
|
||||
HalfedgeHandle o0(opposite_halfedge_handle(h0));
|
||||
|
||||
VertexHandle v0(to_vertex_handle(o0));
|
||||
VertexHandle v1(to_vertex_handle(h0));
|
||||
|
||||
HalfedgeHandle h1 = new_edge(v1, v0);
|
||||
HalfedgeHandle o1 = opposite_halfedge_handle(h1);
|
||||
|
||||
FaceHandle f0 = face_handle(h0);
|
||||
FaceHandle f1 = new_face();
|
||||
|
||||
// halfedge -> halfedge
|
||||
set_next_halfedge_handle(prev_halfedge_handle(h0), o1);
|
||||
set_next_halfedge_handle(o1, next_halfedge_handle(h0));
|
||||
set_next_halfedge_handle(h1, h0);
|
||||
set_next_halfedge_handle(h0, h1);
|
||||
|
||||
// halfedge -> face
|
||||
set_face_handle(o1, f0);
|
||||
set_face_handle(h0, f1);
|
||||
set_face_handle(h1, f1);
|
||||
|
||||
// face -> halfedge
|
||||
set_halfedge_handle(f1, h0);
|
||||
if (f0.is_valid())
|
||||
set_halfedge_handle(f0, o1);
|
||||
|
||||
|
||||
// vertex -> halfedge
|
||||
adjust_outgoing_halfedge(v0);
|
||||
adjust_outgoing_halfedge(v1);
|
||||
|
||||
return h1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
TriConnectivity::HalfedgeHandle
|
||||
TriConnectivity::insert_edge(VertexHandle _vh, HalfedgeHandle _h0, HalfedgeHandle _h1)
|
||||
{
|
||||
assert(_h0.is_valid() && _h1.is_valid());
|
||||
|
||||
VertexHandle v0 = _vh;
|
||||
VertexHandle v1 = to_vertex_handle(_h0);
|
||||
|
||||
assert( v1 == to_vertex_handle(_h1));
|
||||
|
||||
HalfedgeHandle v0v1 = new_edge(v0, v1);
|
||||
HalfedgeHandle v1v0 = opposite_halfedge_handle(v0v1);
|
||||
|
||||
|
||||
|
||||
// vertex -> halfedge
|
||||
set_halfedge_handle(v0, v0v1);
|
||||
set_halfedge_handle(v1, v1v0);
|
||||
|
||||
|
||||
// halfedge -> halfedge
|
||||
set_next_halfedge_handle(v0v1, next_halfedge_handle(_h0));
|
||||
set_next_halfedge_handle(_h0, v0v1);
|
||||
set_next_halfedge_handle(v1v0, next_halfedge_handle(_h1));
|
||||
set_next_halfedge_handle(_h1, v1v0);
|
||||
|
||||
|
||||
// halfedge -> vertex
|
||||
for (VertexIHalfedgeIter vih_it(vih_iter(v0)); vih_it; ++vih_it)
|
||||
set_vertex_handle(vih_it.handle(), v0);
|
||||
|
||||
|
||||
// halfedge -> face
|
||||
set_face_handle(v0v1, face_handle(_h0));
|
||||
set_face_handle(v1v0, face_handle(_h1));
|
||||
|
||||
|
||||
// face -> halfedge
|
||||
if (face_handle(v0v1).is_valid())
|
||||
set_halfedge_handle(face_handle(v0v1), v0v1);
|
||||
if (face_handle(v1v0).is_valid())
|
||||
set_halfedge_handle(face_handle(v1v0), v1v0);
|
||||
|
||||
|
||||
// vertex -> halfedge
|
||||
adjust_outgoing_halfedge(v0);
|
||||
adjust_outgoing_halfedge(v1);
|
||||
|
||||
|
||||
return v0v1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool TriConnectivity::is_flip_ok(EdgeHandle _eh) const
|
||||
{
|
||||
// boundary edges cannot be flipped
|
||||
if (is_boundary(_eh)) return false;
|
||||
|
||||
|
||||
HalfedgeHandle hh = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle oh = halfedge_handle(_eh, 1);
|
||||
|
||||
|
||||
// check if the flipped edge is already present
|
||||
// in the mesh
|
||||
|
||||
VertexHandle ah = to_vertex_handle(next_halfedge_handle(hh));
|
||||
VertexHandle bh = to_vertex_handle(next_halfedge_handle(oh));
|
||||
|
||||
if (ah == bh) // this is generally a bad sign !!!
|
||||
return false;
|
||||
|
||||
for (ConstVertexVertexIter vvi(*this, ah); vvi; ++vvi)
|
||||
if (vvi.handle() == bh)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void TriConnectivity::flip(EdgeHandle _eh)
|
||||
{
|
||||
// CAUTION : Flipping a halfedge may result in
|
||||
// a non-manifold mesh, hence check for yourself
|
||||
// whether this operation is allowed or not!
|
||||
assert(is_flip_ok(_eh));//let's make it sure it is actually checked
|
||||
assert(!is_boundary(_eh));
|
||||
|
||||
HalfedgeHandle a0 = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle b0 = halfedge_handle(_eh, 1);
|
||||
|
||||
HalfedgeHandle a1 = next_halfedge_handle(a0);
|
||||
HalfedgeHandle a2 = next_halfedge_handle(a1);
|
||||
|
||||
HalfedgeHandle b1 = next_halfedge_handle(b0);
|
||||
HalfedgeHandle b2 = next_halfedge_handle(b1);
|
||||
|
||||
VertexHandle va0 = to_vertex_handle(a0);
|
||||
VertexHandle va1 = to_vertex_handle(a1);
|
||||
|
||||
VertexHandle vb0 = to_vertex_handle(b0);
|
||||
VertexHandle vb1 = to_vertex_handle(b1);
|
||||
|
||||
FaceHandle fa = face_handle(a0);
|
||||
FaceHandle fb = face_handle(b0);
|
||||
|
||||
set_vertex_handle(a0, va1);
|
||||
set_vertex_handle(b0, vb1);
|
||||
|
||||
set_next_halfedge_handle(a0, a2);
|
||||
set_next_halfedge_handle(a2, b1);
|
||||
set_next_halfedge_handle(b1, a0);
|
||||
|
||||
set_next_halfedge_handle(b0, b2);
|
||||
set_next_halfedge_handle(b2, a1);
|
||||
set_next_halfedge_handle(a1, b0);
|
||||
|
||||
set_face_handle(a1, fb);
|
||||
set_face_handle(b1, fa);
|
||||
|
||||
set_halfedge_handle(fa, a0);
|
||||
set_halfedge_handle(fb, b0);
|
||||
|
||||
if (halfedge_handle(va0) == b0)
|
||||
set_halfedge_handle(va0, a1);
|
||||
if (halfedge_handle(vb0) == a0)
|
||||
set_halfedge_handle(vb0, b1);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void TriConnectivity::split(EdgeHandle _eh, VertexHandle _vh)
|
||||
{
|
||||
HalfedgeHandle h0 = halfedge_handle(_eh, 0);
|
||||
HalfedgeHandle o0 = halfedge_handle(_eh, 1);
|
||||
|
||||
VertexHandle v2 = to_vertex_handle(o0);
|
||||
|
||||
HalfedgeHandle e1 = new_edge(_vh, v2);
|
||||
HalfedgeHandle t1 = opposite_halfedge_handle(e1);
|
||||
|
||||
FaceHandle f0 = face_handle(h0);
|
||||
FaceHandle f3 = face_handle(o0);
|
||||
|
||||
set_halfedge_handle(_vh, h0);
|
||||
set_vertex_handle(o0, _vh);
|
||||
|
||||
if (!is_boundary(h0))
|
||||
{
|
||||
HalfedgeHandle h1 = next_halfedge_handle(h0);
|
||||
HalfedgeHandle h2 = next_halfedge_handle(h1);
|
||||
|
||||
VertexHandle v1 = to_vertex_handle(h1);
|
||||
|
||||
HalfedgeHandle e0 = new_edge(_vh, v1);
|
||||
HalfedgeHandle t0 = opposite_halfedge_handle(e0);
|
||||
|
||||
FaceHandle f1 = new_face();
|
||||
set_halfedge_handle(f0, h0);
|
||||
set_halfedge_handle(f1, h2);
|
||||
|
||||
set_face_handle(h1, f0);
|
||||
set_face_handle(t0, f0);
|
||||
set_face_handle(h0, f0);
|
||||
|
||||
set_face_handle(h2, f1);
|
||||
set_face_handle(t1, f1);
|
||||
set_face_handle(e0, f1);
|
||||
|
||||
set_next_halfedge_handle(h0, h1);
|
||||
set_next_halfedge_handle(h1, t0);
|
||||
set_next_halfedge_handle(t0, h0);
|
||||
|
||||
set_next_halfedge_handle(e0, h2);
|
||||
set_next_halfedge_handle(h2, t1);
|
||||
set_next_halfedge_handle(t1, e0);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_next_halfedge_handle(prev_halfedge_handle(h0), t1);
|
||||
set_next_halfedge_handle(t1, h0);
|
||||
// halfedge handle of _vh already is h0
|
||||
}
|
||||
|
||||
|
||||
if (!is_boundary(o0))
|
||||
{
|
||||
HalfedgeHandle o1 = next_halfedge_handle(o0);
|
||||
HalfedgeHandle o2 = next_halfedge_handle(o1);
|
||||
|
||||
VertexHandle v3 = to_vertex_handle(o1);
|
||||
|
||||
HalfedgeHandle e2 = new_edge(_vh, v3);
|
||||
HalfedgeHandle t2 = opposite_halfedge_handle(e2);
|
||||
|
||||
FaceHandle f2 = new_face();
|
||||
set_halfedge_handle(f2, o1);
|
||||
set_halfedge_handle(f3, o0);
|
||||
|
||||
set_face_handle(o1, f2);
|
||||
set_face_handle(t2, f2);
|
||||
set_face_handle(e1, f2);
|
||||
|
||||
set_face_handle(o2, f3);
|
||||
set_face_handle(o0, f3);
|
||||
set_face_handle(e2, f3);
|
||||
|
||||
set_next_halfedge_handle(e1, o1);
|
||||
set_next_halfedge_handle(o1, t2);
|
||||
set_next_halfedge_handle(t2, e1);
|
||||
|
||||
set_next_halfedge_handle(o0, e2);
|
||||
set_next_halfedge_handle(e2, o2);
|
||||
set_next_halfedge_handle(o2, o0);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_next_halfedge_handle(e1, next_halfedge_handle(o0));
|
||||
set_next_halfedge_handle(o0, e1);
|
||||
set_halfedge_handle(_vh, e1);
|
||||
}
|
||||
|
||||
if (halfedge_handle(v2) == h0)
|
||||
set_halfedge_handle(v2, t1);
|
||||
}
|
||||
|
||||
}// namespace OpenMesh
|
||||
130
Core/Mesh/TriConnectivity.hh
Normal file
130
Core/Mesh/TriConnectivity.hh
Normal file
@@ -0,0 +1,130 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2004 by Computer Graphics Group, RWTH Aachen *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* License *
|
||||
* *
|
||||
* This library 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, version 2.1. *
|
||||
* *
|
||||
* This library 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 Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
|
||||
#ifndef OPENMESH_TRICONNECTIVITY_HH
|
||||
#define OPENMESH_TRICONNECTIVITY_HH
|
||||
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
class TriConnectivity : public PolyConnectivity
|
||||
{
|
||||
public:
|
||||
|
||||
TriConnectivity() {}
|
||||
virtual ~TriConnectivity() {}
|
||||
|
||||
inline static bool is_triangles()
|
||||
{ return true; }
|
||||
|
||||
/** assign_connectivity() methods. See ArrayKernel::assign_connectivity()
|
||||
for more details. When the source connectivity is not triangles, in
|
||||
addition "fan" connectivity triangulation is performed*/
|
||||
inline void assign_connectivity(const TriConnectivity& _other)
|
||||
{ PolyConnectivity::assign_connectivity(_other); }
|
||||
|
||||
inline void assign_connectivity(const PolyConnectivity& _other)
|
||||
{
|
||||
PolyConnectivity::assign_connectivity(_other);
|
||||
triangulate();
|
||||
}
|
||||
|
||||
/** \name Addding items to a mesh
|
||||
*/
|
||||
//@{
|
||||
/** Override OpenMesh::Mesh::PolyMeshT::add_face(). Faces that aren't
|
||||
triangles will be triangulated and added. In this case an
|
||||
invalid face handle will be returned. */
|
||||
FaceHandle add_face(const std::vector<VertexHandle>& _vhandles)
|
||||
{ return add_face(&_vhandles.front(), _vhandles.size()); }
|
||||
|
||||
FaceHandle add_face(const VertexHandle* _vhandles, uint _vhs_size);
|
||||
|
||||
FaceHandle add_face(VertexHandle _vh0, VertexHandle _vh1, VertexHandle _vh2)
|
||||
{
|
||||
VertexHandle vhs[3] = { _vh0, _vh1, _vh2 };
|
||||
return PolyConnectivity::add_face(vhs, 3);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
/** Returns the opposite vertex to the halfedge _heh in the face
|
||||
referenced by _heh returns InvalidVertexHandle if the _heh is
|
||||
boundary */
|
||||
inline VertexHandle opposite_vh(HalfedgeHandle _heh) const
|
||||
{
|
||||
return is_boundary(_heh) ? InvalidVertexHandle :
|
||||
to_vertex_handle(next_halfedge_handle(_heh));
|
||||
}
|
||||
|
||||
/** Returns the opposite vertex to the opposite halfedge of _heh in
|
||||
the face referenced by it returns InvalidVertexHandle if the
|
||||
opposite halfedge is boundary */
|
||||
VertexHandle opposite_he_opposite_vh(HalfedgeHandle _heh) const
|
||||
{ return opposite_vh(opposite_halfedge_handle(_heh)); }
|
||||
|
||||
/** \name Topology modifying operators
|
||||
*/
|
||||
//@{
|
||||
|
||||
|
||||
/** Returns whether collapsing halfedge _heh is ok or would lead to
|
||||
topological inconsistencies.
|
||||
\attention This method need the Attributes::Status attribute and
|
||||
changes the \em tagged bit. */
|
||||
bool is_collapse_ok(HalfedgeHandle _heh);
|
||||
|
||||
/// Vertex Split: inverse operation to collapse().
|
||||
HalfedgeHandle vertex_split(VertexHandle v0, VertexHandle v1,
|
||||
VertexHandle vl, VertexHandle vr);
|
||||
|
||||
/// Check whether flipping _eh is topologically correct.
|
||||
bool is_flip_ok(EdgeHandle _eh) const;
|
||||
|
||||
/** Flip edge _eh.
|
||||
Check for topological correctness first using is_flip_ok(). */
|
||||
void flip(EdgeHandle _eh);
|
||||
|
||||
/// Edge split (= 2-to-4 split)
|
||||
void split(EdgeHandle _eh, VertexHandle _vh);
|
||||
|
||||
/// Face split (= 1-to-3 split, calls corresponding PolyMeshT function).
|
||||
inline void split(FaceHandle _fh, VertexHandle _vh)
|
||||
{ PolyConnectivity::split(_fh, _vh); }
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
/// Helper for vertex split
|
||||
HalfedgeHandle insert_loop(HalfedgeHandle _hh);
|
||||
/// Helper for vertex split
|
||||
HalfedgeHandle insert_edge(VertexHandle _vh,
|
||||
HalfedgeHandle _h0, HalfedgeHandle _h1);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif//OPENMESH_TRICONNECTIVITY_HH
|
||||
60
Core/Mesh/TriMeshT.cc
Normal file
60
Core/Mesh/TriMeshT.cc
Normal file
@@ -0,0 +1,60 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS TriMeshT - IMPLEMENTATION
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#define OPENMESH_TRIMESH_C
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/Mesh/TriMeshT.hh>
|
||||
#include <OpenMesh/Core/System/omstream.hh>
|
||||
#include <vector>
|
||||
|
||||
|
||||
//== NAMESPACES ==============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== IMPLEMENTATION ==========================================================
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
195
Core/Mesh/TriMeshT.hh
Normal file
195
Core/Mesh/TriMeshT.hh
Normal file
@@ -0,0 +1,195 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.1.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS TriMeshT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_TRIMESH_HH
|
||||
#define OPENMESH_TRIMESH_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Mesh/PolyMeshT.hh>
|
||||
#include <vector>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class TriMeshT TriMeshT.hh <OpenMesh/Mesh/TriMeshT.hh>
|
||||
|
||||
Base type for a triangle mesh.
|
||||
|
||||
Base type for a triangle mesh, parameterized by a mesh kernel. The
|
||||
mesh inherits all methods from the kernel class and the
|
||||
more general polygonal mesh PolyMeshT. Therefore it provides
|
||||
the same types for items, handles, iterators and so on.
|
||||
|
||||
\param Kernel: template argument for the mesh kernel
|
||||
\note You should use the predefined mesh-kernel combinations in
|
||||
\ref mesh_types_group
|
||||
\see \ref mesh_type
|
||||
\see OpenMesh::PolyMeshT
|
||||
*/
|
||||
|
||||
template <class Kernel>
|
||||
class TriMeshT : public PolyMeshT<Kernel>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// self
|
||||
typedef TriMeshT<Kernel> This;
|
||||
typedef PolyMeshT<Kernel> PolyMesh;
|
||||
|
||||
//@{
|
||||
/// Determine whether this is a PolyMeshT or TriMeshT
|
||||
enum { IsPolyMesh = 0 };
|
||||
enum { IsTriMesh = 1 };
|
||||
static bool is_polymesh() { return false; }
|
||||
static bool is_trimesh() { return true; }
|
||||
//@}
|
||||
|
||||
//--- items ---
|
||||
|
||||
typedef typename PolyMesh::Scalar Scalar;
|
||||
typedef typename PolyMesh::Point Point;
|
||||
typedef typename PolyMesh::Normal Normal;
|
||||
typedef typename PolyMesh::Color Color;
|
||||
typedef typename PolyMesh::TexCoord1D TexCoord1D;
|
||||
typedef typename PolyMesh::TexCoord2D TexCoord2D;
|
||||
typedef typename PolyMesh::TexCoord3D TexCoord3D;
|
||||
typedef typename PolyMesh::Vertex Vertex;
|
||||
typedef typename PolyMesh::Halfedge Halfedge;
|
||||
typedef typename PolyMesh::Edge Edge;
|
||||
typedef typename PolyMesh::Face Face;
|
||||
|
||||
|
||||
//--- handles ---
|
||||
|
||||
typedef typename PolyMesh::VertexHandle VertexHandle;
|
||||
typedef typename PolyMesh::HalfedgeHandle HalfedgeHandle;
|
||||
typedef typename PolyMesh::EdgeHandle EdgeHandle;
|
||||
typedef typename PolyMesh::FaceHandle FaceHandle;
|
||||
|
||||
|
||||
//--- iterators ---
|
||||
|
||||
typedef typename PolyMesh::VertexIter VertexIter;
|
||||
typedef typename PolyMesh::ConstVertexIter ConstVertexIter;
|
||||
typedef typename PolyMesh::EdgeIter EdgeIter;
|
||||
typedef typename PolyMesh::ConstEdgeIter ConstEdgeIter;
|
||||
typedef typename PolyMesh::FaceIter FaceIter;
|
||||
typedef typename PolyMesh::ConstFaceIter ConstFaceIter;
|
||||
|
||||
|
||||
|
||||
//--- circulators ---
|
||||
|
||||
typedef typename PolyMesh::VertexVertexIter VertexVertexIter;
|
||||
typedef typename PolyMesh::VertexOHalfedgeIter VertexOHalfedgeIter;
|
||||
typedef typename PolyMesh::VertexIHalfedgeIter VertexIHalfedgeIter;
|
||||
typedef typename PolyMesh::VertexEdgeIter VertexEdgeIter;
|
||||
typedef typename PolyMesh::VertexFaceIter VertexFaceIter;
|
||||
typedef typename PolyMesh::FaceVertexIter FaceVertexIter;
|
||||
typedef typename PolyMesh::FaceHalfedgeIter FaceHalfedgeIter;
|
||||
typedef typename PolyMesh::FaceEdgeIter FaceEdgeIter;
|
||||
typedef typename PolyMesh::FaceFaceIter FaceFaceIter;
|
||||
typedef typename PolyMesh::ConstVertexVertexIter ConstVertexVertexIter;
|
||||
typedef typename PolyMesh::ConstVertexOHalfedgeIter ConstVertexOHalfedgeIter;
|
||||
typedef typename PolyMesh::ConstVertexIHalfedgeIter ConstVertexIHalfedgeIter;
|
||||
typedef typename PolyMesh::ConstVertexEdgeIter ConstVertexEdgeIter;
|
||||
typedef typename PolyMesh::ConstVertexFaceIter ConstVertexFaceIter;
|
||||
typedef typename PolyMesh::ConstFaceVertexIter ConstFaceVertexIter;
|
||||
typedef typename PolyMesh::ConstFaceHalfedgeIter ConstFaceHalfedgeIter;
|
||||
typedef typename PolyMesh::ConstFaceEdgeIter ConstFaceEdgeIter;
|
||||
typedef typename PolyMesh::ConstFaceFaceIter ConstFaceFaceIter;
|
||||
|
||||
// --- constructor/destructor
|
||||
|
||||
/// Default constructor
|
||||
TriMeshT() : PolyMesh() {}
|
||||
/// Destructor
|
||||
virtual ~TriMeshT() {}
|
||||
|
||||
//--- halfedge collapse / vertex split ---
|
||||
|
||||
/// Vertex Split: inverse operation to collapse().
|
||||
inline HalfedgeHandle vertex_split(Point _v0_point, VertexHandle _v1,
|
||||
VertexHandle _vl, VertexHandle _vr)
|
||||
{ return PolyMesh::vertex_split(add_vertex(_v0_point), _v1, _vl, _vr); }
|
||||
|
||||
inline HalfedgeHandle vertex_split(VertexHandle _v0, VertexHandle _v1,
|
||||
VertexHandle _vl, VertexHandle _vr)
|
||||
{ return PolyMesh::vertex_split(_v0, _v1, _vl, _vr); }
|
||||
|
||||
/// Edge split (= 2-to-4 split)
|
||||
inline void split(EdgeHandle _eh, const Point& _p)
|
||||
{ PolyMesh::split(_eh, add_vertex(_p)); }
|
||||
|
||||
inline void split(EdgeHandle _eh, VertexHandle _vh)
|
||||
{ PolyMesh::split(_eh, _vh); }
|
||||
|
||||
/// Face split (= 1-to-3 split, calls corresponding PolyMeshT function).
|
||||
|
||||
/// Face split (= 1-to-3 split, calls corresponding PolyMeshT function).
|
||||
inline void split(FaceHandle _fh, const Point& _p)
|
||||
{ PolyMesh::split(_fh, _p); }
|
||||
|
||||
inline void split(FaceHandle _fh, VertexHandle _vh)
|
||||
{ PolyMesh::split(_fh, _vh); }
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_TRIMESH_C)
|
||||
#define OPENMESH_TRIMESH_TEMPLATES
|
||||
#include "TriMeshT.cc"
|
||||
#endif
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_TRIMESH_HH defined
|
||||
//=============================================================================
|
||||
89
Core/Mesh/TriMesh_ArrayKernelT.hh
Normal file
89
Core/Mesh/TriMesh_ArrayKernelT.hh
Normal file
@@ -0,0 +1,89 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// OpenMesh
|
||||
// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen
|
||||
// www.openmesh.org
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// License
|
||||
//
|
||||
// This library 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, version 2.1.
|
||||
//
|
||||
// This library 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 Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Revision: 1801 $
|
||||
// $Date: 2008-05-19 11:53:56 +0200 (Mo, 19. Mai 2008) $
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// CLASS TriMesh_ArrayKernelT
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#ifndef OPENMESH_TRIMESH_ARRAY_KERNEL_HH
|
||||
#define OPENMESH_TRIMESH_ARRAY_KERNEL_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Mesh/TriConnectivity.hh>
|
||||
#include <OpenMesh/Core/Mesh/Traits.hh>
|
||||
#include <OpenMesh/Core/Mesh/FinalMeshItemsT.hh>
|
||||
#include <OpenMesh/Core/Mesh/AttribKernelT.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMeshT.hh>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/// Helper class to create a TriMesh-type based on ArrayKernelT
|
||||
template <class Traits>
|
||||
struct TriMesh_ArrayKernel_GeneratorT
|
||||
{
|
||||
typedef FinalMeshItemsT<Traits, true> MeshItems;
|
||||
typedef AttribKernelT<MeshItems, TriConnectivity> AttribKernel;
|
||||
typedef TriMeshT<AttribKernel> Mesh;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** \ingroup mesh_types_group
|
||||
Triangle mesh based on the ArrayKernel.
|
||||
\see OpenMesh::TriMeshT
|
||||
\see OpenMesh::ArrayKernelT
|
||||
*/
|
||||
template <class Traits = DefaultTraits>
|
||||
class TriMesh_ArrayKernelT
|
||||
: public TriMesh_ArrayKernel_GeneratorT<Traits>::Mesh
|
||||
{};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_TRIMESH_ARRAY_KERNEL_HH
|
||||
//=============================================================================
|
||||
73
Core/Mesh/gen/circulators_header.hh
Normal file
73
Core/Mesh/gen/circulators_header.hh
Normal file
@@ -0,0 +1,73 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2001-2003 by Computer Graphics Group, RWTH Aachen *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* License *
|
||||
* *
|
||||
* This library 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, version 2.1. *
|
||||
* *
|
||||
* This library 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 Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
#ifndef OPENMESH_CIRCULATORS_HH
|
||||
#define OPENMESH_CIRCULATORS_HH
|
||||
//=============================================================================
|
||||
//
|
||||
// Vertex and Face circulators for PolyMesh/TriMesh
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Iterators {
|
||||
|
||||
|
||||
//== FORWARD DECLARATIONS =====================================================
|
||||
|
||||
|
||||
template <class Mesh> class VertexVertexIterT;
|
||||
template <class Mesh> class VertexIHalfedgeIterT;
|
||||
template <class Mesh> class VertexOHalfedgeIterT;
|
||||
template <class Mesh> class VertexEdgeIterT;
|
||||
template <class Mesh> class VertexFaceIterT;
|
||||
|
||||
template <class Mesh> class ConstVertexVertexIterT;
|
||||
template <class Mesh> class ConstVertexIHalfedgeIterT;
|
||||
template <class Mesh> class ConstVertexOHalfedgeIterT;
|
||||
template <class Mesh> class ConstVertexEdgeIterT;
|
||||
template <class Mesh> class ConstVertexFaceIterT;
|
||||
|
||||
template <class Mesh> class FaceVertexIterT;
|
||||
template <class Mesh> class FaceHalfedgeIterT;
|
||||
template <class Mesh> class FaceEdgeIterT;
|
||||
template <class Mesh> class FaceFaceIterT;
|
||||
|
||||
template <class Mesh> class ConstFaceVertexIterT;
|
||||
template <class Mesh> class ConstFaceHalfedgeIterT;
|
||||
template <class Mesh> class ConstFaceEdgeIterT;
|
||||
template <class Mesh> class ConstFaceFaceIterT;
|
||||
|
||||
|
||||
|
||||
190
Core/Mesh/gen/circulators_template.hh
Normal file
190
Core/Mesh/gen/circulators_template.hh
Normal file
@@ -0,0 +1,190 @@
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class CirculatorT CirculatorsT.hh <OpenMesh/Mesh/Iterators/CirculatorsT.hh>
|
||||
Circulator.
|
||||
*/
|
||||
|
||||
template <class Mesh>
|
||||
class CirculatorT
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
//--- Typedefs ---
|
||||
|
||||
typedef typename Mesh::HalfedgeHandle HalfedgeHandle;
|
||||
|
||||
typedef TargetType value_type;
|
||||
typedef TargetHandle value_handle;
|
||||
|
||||
#if IsConst
|
||||
typedef const Mesh& mesh_ref;
|
||||
typedef const Mesh* mesh_ptr;
|
||||
typedef const TargetType& reference;
|
||||
typedef const TargetType* pointer;
|
||||
#else
|
||||
typedef Mesh& mesh_ref;
|
||||
typedef Mesh* mesh_ptr;
|
||||
typedef TargetType& reference;
|
||||
typedef TargetType* pointer;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/// Default constructor
|
||||
CirculatorT() : mesh_(0), active_(false) {}
|
||||
|
||||
|
||||
/// Construct with mesh and a SourceHandle
|
||||
CirculatorT(mesh_ref _mesh, SourceHandle _start) :
|
||||
mesh_(&_mesh),
|
||||
start_(_mesh.halfedge_handle(_start)),
|
||||
heh_(start_),
|
||||
active_(false)
|
||||
{ post_init; }
|
||||
|
||||
|
||||
/// Construct with mesh and start halfedge
|
||||
CirculatorT(mesh_ref _mesh, HalfedgeHandle _heh) :
|
||||
mesh_(&_mesh),
|
||||
start_(_heh),
|
||||
heh_(_heh),
|
||||
active_(false)
|
||||
{ post_init; }
|
||||
|
||||
|
||||
/// Copy constructor
|
||||
CirculatorT(const CirculatorT& _rhs) :
|
||||
mesh_(_rhs.mesh_),
|
||||
start_(_rhs.start_),
|
||||
heh_(_rhs.heh_),
|
||||
active_(_rhs.active_)
|
||||
{ post_init; }
|
||||
|
||||
|
||||
/// Assignment operator
|
||||
CirculatorT& operator=(const CirculatorT<Mesh>& _rhs)
|
||||
{
|
||||
mesh_ = _rhs.mesh_;
|
||||
start_ = _rhs.start_;
|
||||
heh_ = _rhs.heh_;
|
||||
active_ = _rhs.active_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#if IsConst
|
||||
/// construct from non-const circulator type
|
||||
CirculatorT(const NonConstCircT<Mesh>& _rhs) :
|
||||
mesh_(_rhs.mesh_),
|
||||
start_(_rhs.start_),
|
||||
heh_(_rhs.heh_),
|
||||
active_(_rhs.active_)
|
||||
{ post_init; }
|
||||
|
||||
|
||||
/// assign from non-const circulator
|
||||
CirculatorT& operator=(const NonConstCircT<Mesh>& _rhs)
|
||||
{
|
||||
mesh_ = _rhs.mesh_;
|
||||
start_ = _rhs.start_;
|
||||
heh_ = _rhs.heh_;
|
||||
active_ = _rhs.active_;
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
friend class ConstCircT<Mesh>;
|
||||
#endif
|
||||
|
||||
|
||||
/// Equal ?
|
||||
bool operator==(const CirculatorT& _rhs) const {
|
||||
return ((mesh_ == _rhs.mesh_) &&
|
||||
(start_ == _rhs.start_) &&
|
||||
(heh_ == _rhs.heh_) &&
|
||||
(active_ == _rhs.active_));
|
||||
}
|
||||
|
||||
|
||||
/// Not equal ?
|
||||
bool operator!=(const CirculatorT& _rhs) const {
|
||||
return !operator==(_rhs);
|
||||
}
|
||||
|
||||
|
||||
/// Pre-Increment (next cw target)
|
||||
CirculatorT& operator++() {
|
||||
assert(mesh_);
|
||||
active_ = true;
|
||||
increment;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/// Pre-Decrement (next ccw target)
|
||||
CirculatorT& operator--() {
|
||||
assert(mesh_);
|
||||
active_ = true;
|
||||
decrement;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/** Get the current halfedge. There are \c Vertex*Iters and \c
|
||||
Face*Iters. For both the current state is defined by the
|
||||
current halfedge. This is what this method returns.
|
||||
*/
|
||||
HalfedgeHandle current_halfedge_handle() const {
|
||||
return heh_;
|
||||
}
|
||||
|
||||
|
||||
/// Return the handle of the current target.
|
||||
TargetHandle handle() const {
|
||||
assert(mesh_);
|
||||
return get_handle;
|
||||
}
|
||||
|
||||
|
||||
/// Cast to the handle of the current target.
|
||||
operator TargetHandle() const {
|
||||
assert(mesh_);
|
||||
return get_handle;
|
||||
}
|
||||
|
||||
|
||||
/// Return a reference to the current target.
|
||||
reference operator*() const {
|
||||
assert(mesh_);
|
||||
return mesh_->deref(handle());
|
||||
}
|
||||
|
||||
|
||||
/// Return a pointer to the current target.
|
||||
pointer operator->() const {
|
||||
assert(mesh_);
|
||||
return &mesh_->deref(handle());
|
||||
}
|
||||
|
||||
|
||||
/** Returns whether the circulator is still valid.
|
||||
After one complete round around a vertex/face the circulator becomes
|
||||
invalid, i.e. this function will return \c false. Nevertheless you
|
||||
can continue circulating. This method just tells you whether you
|
||||
have completed the first round.
|
||||
*/
|
||||
operator bool() const {
|
||||
return heh_.is_valid() && ((start_ != heh_) || (!active_));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
mesh_ptr mesh_;
|
||||
HalfedgeHandle start_, heh_;
|
||||
bool active_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
6
Core/Mesh/gen/footer.hh
Normal file
6
Core/Mesh/gen/footer.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
//=============================================================================
|
||||
} // namespace Iterators
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif
|
||||
//=============================================================================
|
||||
175
Core/Mesh/gen/generate.sh
Normal file
175
Core/Mesh/gen/generate.sh
Normal file
@@ -0,0 +1,175 @@
|
||||
#!/bin/bash
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# generate_iterator( TargetType, n_elements, has_element_status )
|
||||
function generate_iterator
|
||||
{
|
||||
NonConstIter=$1"IterT"
|
||||
ConstIter="Const"$NonConstIter
|
||||
TargetType="typename Mesh::"$1
|
||||
TargetHandle="typename Mesh::"$1"Handle"
|
||||
|
||||
|
||||
cat iterators_template.hh \
|
||||
| sed -e "s/IteratorT/$NonConstIter/; s/IteratorT/$NonConstIter/;
|
||||
s/NonConstIterT/$NonConstIter/;
|
||||
s/ConstIterT/$ConstIter/;
|
||||
s/TargetType/$TargetType/;
|
||||
s/TargetHandle/$TargetHandle/;
|
||||
s/IsConst/0/;
|
||||
s/n_elements/$2/;
|
||||
s/has_element_status/$3/;"
|
||||
|
||||
|
||||
cat iterators_template.hh \
|
||||
| sed -e "s/IteratorT/$ConstIter/; s/IteratorT/$ConstIter/;
|
||||
s/NonConstIterT/$NonConstIter/;
|
||||
s/ConstIterT/$ConstIter/;
|
||||
s/TargetType/$TargetType/;
|
||||
s/TargetHandle/$TargetHandle/;
|
||||
s/IsConst/1/;
|
||||
s/n_elements/$2/;
|
||||
s/has_element_status/$3/;"
|
||||
}
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# generate_circulator( NonConstName, SourceType, TargetType,
|
||||
# post_init,
|
||||
# increment, decrement,
|
||||
# get_handle,
|
||||
# [Name] )
|
||||
function generate_circulator
|
||||
{
|
||||
NonConstCirc=$1
|
||||
ConstCirc="Const"$NonConstCirc
|
||||
SourceHandle="typename Mesh::"$2"Handle"
|
||||
TargetHandle="typename Mesh::"$3"Handle"
|
||||
TargetType="typename Mesh::"$3
|
||||
|
||||
|
||||
cat circulators_template.hh \
|
||||
| sed -e "s/CirculatorT/$NonConstCirc/; s/CirculatorT/$NonConstCirc/;
|
||||
s/NonConstCircT/$NonConstCirc/;
|
||||
s/ConstCircT/$ConstCirc/;
|
||||
s/SourceHandle/$SourceHandle/;
|
||||
s/TargetHandle/$TargetHandle/;
|
||||
s/TargetType/$TargetType/;
|
||||
s/IsConst/0/;
|
||||
s/post_init/$4/;
|
||||
s/increment/$5/;
|
||||
s/decrement/$6/;
|
||||
s/get_handle/$7/;"
|
||||
|
||||
|
||||
cat circulators_template.hh \
|
||||
| sed -e "s/CirculatorT/$ConstCirc/; s/CirculatorT/$ConstCirc/;
|
||||
s/NonConstCircT/$NonConstCirc/;
|
||||
s/ConstCircT/$ConstCirc/;
|
||||
s/SourceHandle/$SourceHandle/;
|
||||
s/TargetHandle/$TargetHandle/;
|
||||
s/TargetType/$TargetType/;
|
||||
s/IsConst/1/;
|
||||
s/post_init/$4/;
|
||||
s/increment/$5/;
|
||||
s/decrement/$6/;
|
||||
s/get_handle/$7/;"
|
||||
}
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
### Generate IteratorsT.hh
|
||||
|
||||
cat iterators_header.hh > IteratorsT.hh
|
||||
|
||||
generate_iterator Vertex n_vertices has_vertex_status >> IteratorsT.hh
|
||||
generate_iterator Halfedge n_halfedges has_halfedge_status >> IteratorsT.hh
|
||||
generate_iterator Edge n_edges has_edge_status >> IteratorsT.hh
|
||||
generate_iterator Face n_faces has_face_status >> IteratorsT.hh
|
||||
|
||||
cat footer.hh >> IteratorsT.hh
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
### Generate CirculatorsT.hh
|
||||
|
||||
cat circulators_header.hh > CirculatorsT.hh
|
||||
|
||||
|
||||
generate_circulator VertexVertexIterT Vertex Vertex \
|
||||
" " \
|
||||
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
|
||||
"mesh_->to_vertex_handle(heh_);" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator VertexOHalfedgeIterT Vertex Halfedge \
|
||||
" " \
|
||||
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
|
||||
"heh_" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator VertexIHalfedgeIterT Vertex Halfedge \
|
||||
" " \
|
||||
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
|
||||
"mesh_->opposite_halfedge_handle(heh_)" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator VertexEdgeIterT Vertex Edge \
|
||||
" " \
|
||||
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
|
||||
"mesh_->edge_handle(heh_)" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator VertexFaceIterT Vertex Face \
|
||||
"if (heh_.is_valid() \&\& !handle().is_valid()) operator++();" \
|
||||
"do heh_=mesh_->cw_rotated_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
|
||||
"do heh_=mesh_->ccw_rotated_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
|
||||
"mesh_->face_handle(heh_)" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
|
||||
generate_circulator FaceVertexIterT Face Vertex \
|
||||
" " \
|
||||
"heh_=mesh_->next_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->prev_halfedge_handle(heh_);" \
|
||||
"mesh_->to_vertex_handle(heh_)" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator FaceHalfedgeIterT Face Halfedge \
|
||||
" " \
|
||||
"heh_=mesh_->next_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->prev_halfedge_handle(heh_);" \
|
||||
"heh_" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator FaceEdgeIterT Face Edge \
|
||||
" " \
|
||||
"heh_=mesh_->next_halfedge_handle(heh_);" \
|
||||
"heh_=mesh_->prev_halfedge_handle(heh_);" \
|
||||
"mesh_->edge_handle(heh_)" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
generate_circulator FaceFaceIterT Face Face \
|
||||
"if (heh_.is_valid() \&\& !handle().is_valid()) operator++();" \
|
||||
"do heh_=mesh_->next_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
|
||||
"do heh_=mesh_->prev_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
|
||||
"mesh_->face_handle(mesh_->opposite_halfedge_handle(heh_))" \
|
||||
>> CirculatorsT.hh
|
||||
|
||||
|
||||
cat footer.hh >> CirculatorsT.hh
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
62
Core/Mesh/gen/iterators_header.hh
Normal file
62
Core/Mesh/gen/iterators_header.hh
Normal file
@@ -0,0 +1,62 @@
|
||||
/*===========================================================================*\
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (C) 2001-2003 by Computer Graphics Group, RWTH Aachen *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* License *
|
||||
* *
|
||||
* This library 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, version 2.1. *
|
||||
* *
|
||||
* This library 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 Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
|
||||
* *
|
||||
\*===========================================================================*/
|
||||
#ifndef OPENMESH_ITERATORS_HH
|
||||
#define OPENMESH_ITERATORS_HH
|
||||
//=============================================================================
|
||||
//
|
||||
// Iterators for PolyMesh/TriMesh
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Attributes/Status.hh>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
namespace Iterators {
|
||||
|
||||
|
||||
//== FORWARD DECLARATIONS =====================================================
|
||||
|
||||
|
||||
template <class Mesh> class VertexIterT;
|
||||
template <class Mesh> class ConstVertexIterT;
|
||||
template <class Mesh> class HalfedgeIterT;
|
||||
template <class Mesh> class ConstHalfedgeIterT;
|
||||
template <class Mesh> class EdgeIterT;
|
||||
template <class Mesh> class ConstEdgeIterT;
|
||||
template <class Mesh> class FaceIterT;
|
||||
template <class Mesh> class ConstFaceIterT;
|
||||
|
||||
|
||||
|
||||
|
||||
162
Core/Mesh/gen/iterators_template.hh
Normal file
162
Core/Mesh/gen/iterators_template.hh
Normal file
@@ -0,0 +1,162 @@
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
/** \class IteratorT IteratorsT.hh <OpenMesh/Mesh/Iterators/IteratorsT.hh>
|
||||
Linear iterator.
|
||||
*/
|
||||
|
||||
template <class Mesh>
|
||||
class IteratorT
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
//--- Typedefs ---
|
||||
|
||||
typedef TargetType value_type;
|
||||
typedef TargetHandle value_handle;
|
||||
|
||||
#if IsConst
|
||||
typedef const value_type& reference;
|
||||
typedef const value_type* pointer;
|
||||
typedef const Mesh* mesh_ptr;
|
||||
typedef const Mesh& mesh_ref;
|
||||
#else
|
||||
typedef value_type& reference;
|
||||
typedef value_type* pointer;
|
||||
typedef Mesh* mesh_ptr;
|
||||
typedef Mesh& mesh_ref;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/// Default constructor.
|
||||
IteratorT()
|
||||
: mesh_(0), skip_bits_(0)
|
||||
{}
|
||||
|
||||
|
||||
/// Construct with mesh and a target handle.
|
||||
IteratorT(mesh_ref _mesh, value_handle _hnd, bool _skip=false)
|
||||
: mesh_(&_mesh), hnd_(_hnd), skip_bits_(0)
|
||||
{
|
||||
if (_skip) enable_skipping();
|
||||
}
|
||||
|
||||
|
||||
/// Copy constructor
|
||||
IteratorT(const IteratorT& _rhs)
|
||||
: mesh_(_rhs.mesh_), hnd_(_rhs.hnd_), skip_bits_(_rhs.skip_bits_)
|
||||
{}
|
||||
|
||||
|
||||
/// Assignment operator
|
||||
IteratorT& operator=(const IteratorT<Mesh>& _rhs)
|
||||
{
|
||||
mesh_ = _rhs.mesh_;
|
||||
hnd_ = _rhs.hnd_;
|
||||
skip_bits_ = _rhs.skip_bits_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#if IsConst
|
||||
|
||||
/// Construct from a non-const iterator
|
||||
IteratorT(const NonConstIterT<Mesh>& _rhs)
|
||||
: mesh_(_rhs.mesh_), hnd_(_rhs.hnd_), skip_bits_(_rhs.skip_bits_)
|
||||
{}
|
||||
|
||||
|
||||
/// Assignment from non-const iterator
|
||||
IteratorT& operator=(const NonConstIterT<Mesh>& _rhs)
|
||||
{
|
||||
mesh_ = _rhs.mesh_;
|
||||
hnd_ = _rhs.hnd_;
|
||||
skip_bits_ = _rhs.skip_bits_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#else
|
||||
friend class ConstIterT<Mesh>;
|
||||
#endif
|
||||
|
||||
|
||||
/// Standard dereferencing operator.
|
||||
reference operator*() const { return mesh_->deref(hnd_); }
|
||||
|
||||
/// Standard pointer operator.
|
||||
pointer operator->() const { return &(mesh_->deref(hnd_)); }
|
||||
|
||||
/// Get the handle of the item the iterator refers to.
|
||||
value_handle handle() const { return hnd_; }
|
||||
|
||||
/// Cast to the handle of the item the iterator refers to.
|
||||
operator value_handle() const { return hnd_; }
|
||||
|
||||
/// Are two iterators equal? Only valid if they refer to the same mesh!
|
||||
bool operator==(const IteratorT& _rhs) const
|
||||
{ return ((mesh_ == _rhs.mesh_) && (hnd_ == _rhs.hnd_)); }
|
||||
|
||||
/// Not equal?
|
||||
bool operator!=(const IteratorT& _rhs) const
|
||||
{ return !operator==(_rhs); }
|
||||
|
||||
/// Standard pre-increment operator
|
||||
IteratorT& operator++()
|
||||
{ hnd_.__increment(); if (skip_bits_) skip_fwd(); return *this; }
|
||||
|
||||
/// Standard pre-decrement operator
|
||||
IteratorT& operator--()
|
||||
{ hnd_.__decrement(); if (skip_bits_) skip_bwd(); return *this; }
|
||||
|
||||
|
||||
/// Turn on skipping: automatically skip deleted/hidden elements
|
||||
void enable_skipping()
|
||||
{
|
||||
if (mesh_ && mesh_->has_element_status())
|
||||
{
|
||||
Attributes::StatusInfo status;
|
||||
status.set_deleted(true);
|
||||
status.set_hidden(true);
|
||||
skip_bits_ = status.bits();
|
||||
skip_fwd();
|
||||
}
|
||||
else skip_bits_ = 0;
|
||||
}
|
||||
|
||||
|
||||
/// Turn on skipping: automatically skip deleted/hidden elements
|
||||
void disable_skipping() { skip_bits_ = 0; }
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void skip_fwd()
|
||||
{
|
||||
assert(mesh_ && skip_bits_);
|
||||
while ((hnd_.idx() < (signed) mesh_->n_elements()) &&
|
||||
(mesh_->status(hnd_).bits() & skip_bits_))
|
||||
hnd_.__increment();
|
||||
}
|
||||
|
||||
|
||||
void skip_bwd()
|
||||
{
|
||||
assert(mesh_ && skip_bits_);
|
||||
while ((hnd_.idx() >= 0) &&
|
||||
(mesh_->status(hnd_).bits() & skip_bits_))
|
||||
hnd_.__decrement();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
mesh_ptr mesh_;
|
||||
value_handle hnd_;
|
||||
unsigned int skip_bits_;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user