vcglib/vcg/simplex/face/pos.h

509 lines
16 KiB
C++

/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright(C) 2004 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/** \file face/pos.h
* Definition of vcg:face::Pos class.
* This file contain the definition of vcg::face::Pos class and the derived vcg::face::PosN class.
*/
#ifndef __VCG_FACE_POS
#define __VCG_FACE_POS
#include <assert.h>
namespace vcg {
namespace face {
/** \addtogroup face */
/*@{*/
// Needed Prototypes (pos is include before topology)
template <class FaceType>
bool IsBorder(FaceType const & f, const int j );
template <class FaceType>
bool IsManifold(FaceType const & f, const int j );
/** Templated over the class face, it stores a \em position over a face in a mesh.
It contain a pointer to the current face,
the index of one edge and a pointer to one of the vertices of the edge.
See also the JumpingPos in jumping_pos.h for an iterator that loops
around the faces of a vertex without requiring the VF topology.
*/
template <class FaceType>
class Pos
{
public:
/// The vertex type
typedef typename FaceType::VertexType VertexType;
///The Pos type
typedef Pos<FaceType> PosType;
/// The scalar type
typedef typename VertexType::ScalarType ScalarType;
/// Pointer to the face of the half-edge
typename FaceType::FaceType *f;
/// Index of the edge
int z;
/// Pointer to the vertex
VertexType *v;
/// Default constructor
Pos() : f(0), z(-1), v(0) {}
/// Constructor which associates the half-edge element with a face, its edge and its vertex
/// \note that the input must be consistent, e.g. it should hold that \c vp==fp->V0(zp) or \c vp==fp->V1(zp)
Pos(FaceType * const fp, int const zp, VertexType * const vp)
{
f=fp; z=zp; v=vp;
assert((vp==fp->V0(zp))||(vp==fp->V1(zp)));
}
Pos(FaceType * const fp, int const zp){f=fp; z=zp; v=f->V(zp);}
Pos(FaceType * const fp, VertexType * const vp)
{
f = fp;
v = vp;
for(int i = 0; i < f->VN(); ++i)
if (f->V(i) == v) { z = f->Prev(i); break;}
}
// Official Access functions functions
VertexType *& V(){ return v; }
int & E(){ return z; }
FaceType *& F(){ return f; }
VertexType * V() const { return v; }
int E() const { return z; }
FaceType * F() const { return f; }
// Returns the face index of the vertex inside the face.
// Note that this is DIFFERENT from using the z member that denotes the edge index inside the face.
// It should holds that Vind != (z+1)%3 && Vind == z || Vind = z+2%3
int VInd() const
{
for(int i = 0; i < f->VN(); ++i) if(v==f->V(i)) return i;
assert(0);
return -1;
}
/// Operator to compare two half-edge
inline bool operator == ( PosType const & p ) const {
return (f==p.f && z==p.z && v==p.v);
}
/// Operator to compare two half-edge
inline bool operator != ( PosType const & p ) const {
return (f!=p.f || z!=p.z || v!=p.v);
}
/// Operator to order half-edge; it's compare at the first the face pointers, then the index of the edge and finally the vertex pointers
inline bool operator <= ( PosType const & p) const {
return (f!=p.f)?(f<p.f):
(z!=p.z)?(z<p.z):
(v<=p.v);
}
/// Operator to order half-edge; it's compare at the first the face pointers, then the index of the edge and finally the vertex pointers
inline bool operator < ( PosType const & p) const {
if ((*this)==p)return false;
return ((*this)<=p);
}
/// Assignment operator
inline PosType & operator = ( const PosType & h ){
f=h.f;
z=h.z;
v=h.v;
return *this;
}
/// Set to null the half-edge
void SetNull(){
f=0;
v=0;
z=-1;
}
/// Check if the half-edge is null
bool IsNull() const {
return f==0 || v==0 || z<0;
}
//Cambia Faccia lungo z
// e' uguale a FlipF solo che funziona anche per non manifold.
/// Change face via z
void NextF()
{
FaceType * t = f;
f = t->FFp(z);
z = t->FFi(z);
}
// Paolo Cignoni 19/6/99
// Si muove sulla faccia adiacente a f, lungo uno spigolo che
// NON e' j, e che e' adiacente a v
// in questo modo si scandiscono tutte le facce incidenti in un
// vertice f facendo Next() finche' non si ritorna all'inizio
// Nota che sul bordo rimbalza, cioe' se lo spigolo !=j e' di bordo
// restituisce sempre la faccia f ma con nj che e' il nuovo spigolo di bordo
// vecchi parametri: FaceType * & f, VertexType * v, int & j
/// It moves on the adjacent face incident to v, via a different edge that j
void NextE()
{
assert( f->V(z)==v || f->V(f->Next(z))==v ); // L'edge j deve contenere v
FlipE();
FlipF();
assert( f->V(z)==v || f->V(f->Next(z))==v );
}
// Cambia edge mantenendo la stessa faccia e lo stesso vertice
/// Changes edge maintaining the same face and the same vertex
void FlipE()
{
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V((z+0)%f->VN())==v));
if(f->V(f->Next(z))==v) z=f->Next(z);
else z= f->Prev(z);
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V((z))==v));
}
// Cambia Faccia mantenendo lo stesso vertice e lo stesso edge
// Vale che he.flipf.flipf= he
// Se l'he e' di bordo he.flipf()==he
// Si puo' usare SOLO se l'edge e' 2manifold altrimenti
// si deve usare nextf
/// Changes face maintaining the same vertex and the same edge
void FlipF()
{
assert( f->FFp(z)->FFp(f->FFi(z))==f ); // two manifoldness check
// Check that pos vertex is one of the current z-th edge and it is different from the vert opposite to the edge.
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V((z))==v));
FaceType *nf=f->FFp(z);
int nz=f->FFi(z);
assert(nf->V(nf->Prev(nz))!=v && (nf->V(nf->Next(nz))==v || nf->V((nz))==v));
f=nf;
z=nz;
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v));
}
/// Changes vertex maintaining the same face and the same edge
void FlipV()
{
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v));
if(f->V(f->Next(z))==v)
v=f->V(z);
else
v=f->V(f->Next(z));
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v));
}
/// return the vertex that it should have if we make FlipV;
VertexType *VFlip() const
{
assert(f->cV(f->Prev(z))!=v && (f->cV(f->Next(z))==v || f->cV(z)==v));
if(f->cV(f->Next(z))==v) return f->cV(z);
else return f->cV(f->Next(z));
}
/// return the face that it should have if we make FlipF;
FaceType *FFlip() const
{
// assert( f->FFp(z)->FFp(f->FFi(z))==f );
// assert(f->V(f->Prev(z))!=v);
// assert(f->V(f->Next(z))==v || f->V((z+0)%f->VN())==v);
FaceType *nf=f->FFp(z);
return nf;
}
// Trova il prossimo half-edge di bordo (nhe)
// tale che
// --nhe.f adiacente per vertice a he.f
// --nhe.v adiacente per edge di bordo a he.v
// l'idea e' che se he e' un half edge di bordo
// si puo scorrere tutto un bordo facendo
//
// hei=he;
// do
// hei.Nextb()
// while(hei!=he);
/// Finds the next half-edge border
void NextB( )
{
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v));
assert(f->FFp(z)==f); // f is border along j
// Si deve cambiare faccia intorno allo stesso vertice v
//finche' non si trova una faccia di bordo.
do
NextE();
while(!IsBorder());
// L'edge j e' di bordo e deve contenere v
assert(IsBorder() &&( f->V(z)==v || f->V(f->Next(z))==v ));
FlipV();
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v));
assert(f->FFp(z)==f); // f is border along j
}
/// Finds the next half-edge border
void NextNotFaux( )
{
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v));
//assert(f->FFp(z)==f); // f is border along j
// Si deve cambiare faccia intorno allo stesso vertice v
//finche' non si trova una faccia di bordo.
do
{
FlipE();
if (IsFaux()) FlipF();
}
while(IsFaux());
// L'edge j e' di bordo e deve contenere v
assert((!IsFaux()) &&( f->V(z)==v || f->V(f->Next(z))==v ));
FlipV();
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v));
//assert(f->FFp(z)==f); // f is border along j
}
/// Finds the next Crease half-edge border
/// TODO change crease flag with something more generic (per edge)
void NextCrease( )
{
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v));
assert(IsCrease()); // f is border along j
// Si deve cambiare faccia intorno allo stesso vertice v
//finche' non si trova una faccia di bordo.
do
{
FlipE();
if (!IsCrease()) FlipF();
}
while(!IsCrease());
// L'edge j e' di bordo e deve contenere v
assert(IsCrease() &&( f->V(z)==v || f->V(f->Next(z))==v ));
FlipV();
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v));
}
/// Checks if the half-edge is of border
bool IsBorder()const
{
return face::IsBorder(*f,z);
}
/// Checks if the half-edge is of crease
bool IsCrease() const
{
return f->IsCrease(z);
}
bool IsFaux() const
{
return (f->IsF(z));
}
bool IsManifold()
{
return face::IsManifold(*f,z);
}
/*!
* Returns the number of vertices incident on the vertex pos is currently pointing to.
*/
int NumberOfIncidentVertices()
{
int count = 0;
bool on_border = false;
CheckIncidentFaces(count, on_border);
if(on_border) return (count/2)+1;
else return count;
}
/*!
* Returns the number of faces incident on the vertex pos is currently pointing to.
*/
int NumberOfIncidentFaces()
{
int count = 0;
bool on_border = false;
CheckIncidentFaces(count, on_border);
if(on_border) return count/2;
else return count;
}
/*!
* Returns the number of faces incident on the edge the pos is currently pointing to.
* useful to compute the complexity of a non manifold edge
*/
int NumberOfFacesOnEdge() const
{
int count = 0;
PosType ht = *this;
do
{
ht.NextF();
++count;
}
while (ht!=*this);
return count;
}
/** Function to inizialize an half-edge.
@param fp Puntatore alla faccia
@param zp Indice dell'edge
@param vp Puntatore al vertice
*/
void Set(FaceType * const fp, int const zp, VertexType * const vp)
{
f=fp;z=zp;v=vp;
assert(f->V(f->Prev(z))!=v && (f->V(f->Next(z))==v || f->V(z)==v));
}
void Set(FaceType * const pFace, VertexType * const pVertex)
{
f = pFace;
v = pVertex;
for(int i = 0; i < f->VN(); ++i) if(f->V(i) == v ) {z = f->Prev(i);break;}
}
void Assert()
#ifdef _DEBUG
{
FaceType ht=*this;
ht.FlipF();
ht.FlipF();
assert(ht==*this);
ht.FlipE();
ht.FlipE();
assert(ht==*this);
ht.FlipV();
ht.FlipV();
assert(ht==*this);
}
#else
{}
#endif
protected:
void CheckIncidentFaces(int & count, bool & on_border)
{
PosType ht = *this;
do
{
++count;
ht.NextE();
if(ht.IsBorder()) on_border=true;
} while (ht != *this);
}
};
/** Class VFIterator.
This class is used as an iterator over the VF adjacency.
It allow to easily traverse all the faces around a given vertex v;
The faces are traversed in no particular order. No Manifoldness requirement.
typical example:
VertexPointer v;
vcg::face::VFIterator<FaceType> vfi(v);
for (;!vfi.End();++vfi)
vfi.F()->ClearV();
// Alternative
vcg::face::VFIterator<FaceType> vfi(f, 1);
while (!vfi.End()){
vfi.F()->ClearV();
++vfi;
}
See also the JumpingPos in jumping_pos.h for an iterator that loops
around the faces of a vertex using FF topology and without requiring the VF topology.
*/
template <typename FaceType>
class VFIterator
{
public:
/// The vertex type
typedef typename FaceType::VertexType VertexType;
/// The Base face type
typedef FaceType VFIFaceType;
/// The vector type
typedef typename VertexType::CoordType CoordType;
/// The scalar type
typedef typename VertexType::ScalarType ScalarType;
/// Pointer to the face of the half-edge
FaceType *f;
/// Index of the vertex
int z;
/// Default constructor
VFIterator() : f(0), z(-1) {}
/// Constructor which associates the half-edge elementet with a face and its vertex
VFIterator(FaceType * _f, const int & _z){f = _f; z = _z; assert(z>=0 && "VFAdj must be initialized");}
/// Constructor which takes a pointer to vertex
VFIterator(VertexType * _v){f = _v->VFp(); z = _v->VFi(); assert(z>=0 && "VFAdj must be initialized");}
VFIFaceType *& F() { return f;}
int & I() { return z;}
// Access to the vertex. Having a VFIterator vfi, it corresponds to
// vfi.V() = vfi.F()->V(vfi.I())
inline VertexType *V() const { return f->V(z);}
inline VertexType * const & V0() const { return f->V0(z);}
inline VertexType * const & V1() const { return f->V1(z);}
inline VertexType * const & V2() const { return f->V2(z);}
bool End() const {return f==0;}
void operator++() {
FaceType* t = f;
f = t->VFp(z);
z = t->VFi(z);
}
};
/*@}*/
} // end namespace
} // end namespace
#endif