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:
Jan Möbius
2009-02-06 13:37:46 +00:00
parent c3321ebdd9
commit 97f515985d
417 changed files with 76182 additions and 0 deletions

17
Core/Mesh/ACGMakefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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
View 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

File diff suppressed because it is too large Load Diff

View 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

View 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
View 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
View 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
//=============================================================================

View 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
View 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
View 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
//=============================================================================

View 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

View 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
View 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
View 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
//=============================================================================

View 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
//=============================================================================

View 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;

View 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
View File

@@ -0,0 +1,6 @@
//=============================================================================
} // namespace Iterators
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

175
Core/Mesh/gen/generate.sh Normal file
View 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
#------------------------------------------------------------------------------

View 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;

View 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_;
};