corrected a few overloading error in the execute flipping members

This commit is contained in:
Paolo Cignoni 2014-07-13 06:23:46 +00:00
parent 8f35e48f43
commit 7b226f290c
1 changed files with 460 additions and 460 deletions

View File

@ -58,286 +58,286 @@ public:
*/ */
template <class TRIMESH_TYPE, class MYTYPE, template <class TRIMESH_TYPE, class MYTYPE,
typename TRIMESH_TYPE::ScalarType (*QualityFunc)( typename TRIMESH_TYPE::ScalarType (*QualityFunc)(
Point3<typename TRIMESH_TYPE::ScalarType> const & p0, Point3<typename TRIMESH_TYPE::ScalarType> const & p0,
Point3<typename TRIMESH_TYPE::ScalarType> const & p1, Point3<typename TRIMESH_TYPE::ScalarType> const & p1,
Point3<typename TRIMESH_TYPE::ScalarType> const & p2) = Quality> Point3<typename TRIMESH_TYPE::ScalarType> const & p2) = Quality>
class PlanarEdgeFlip : class PlanarEdgeFlip :
public LocalOptimization< TRIMESH_TYPE>::LocModType public LocalOptimization< TRIMESH_TYPE>::LocModType
{ {
protected: protected:
typedef typename TRIMESH_TYPE::FaceType FaceType; typedef typename TRIMESH_TYPE::FaceType FaceType;
typedef typename TRIMESH_TYPE::FacePointer FacePointer; typedef typename TRIMESH_TYPE::FacePointer FacePointer;
typedef typename TRIMESH_TYPE::FaceIterator FaceIterator; typedef typename TRIMESH_TYPE::FaceIterator FaceIterator;
typedef typename TRIMESH_TYPE::VertexType VertexType; typedef typename TRIMESH_TYPE::VertexType VertexType;
typedef typename TRIMESH_TYPE::ScalarType ScalarType; typedef typename TRIMESH_TYPE::ScalarType ScalarType;
typedef typename TRIMESH_TYPE::VertexPointer VertexPointer; typedef typename TRIMESH_TYPE::VertexPointer VertexPointer;
typedef typename TRIMESH_TYPE::CoordType CoordType; typedef typename TRIMESH_TYPE::CoordType CoordType;
typedef vcg::face::Pos<FaceType> PosType; typedef vcg::face::Pos<FaceType> PosType;
typedef typename LocalOptimization<TRIMESH_TYPE>::HeapElem HeapElem; typedef typename LocalOptimization<TRIMESH_TYPE>::HeapElem HeapElem;
typedef typename LocalOptimization<TRIMESH_TYPE>::HeapType HeapType; typedef typename LocalOptimization<TRIMESH_TYPE>::HeapType HeapType;
/*! /*!
* the pos of the flipping * the pos of the flipping
*/ */
PosType _pos; PosType _pos;
/*! /*!
* priority in the heap * priority in the heap
*/ */
ScalarType _priority; ScalarType _priority;
/*! /*!
* Mark for updating * Mark for updating
*/ */
int _localMark; int _localMark;
/*! /*!
* mark for up_dating * mark for up_dating
*/ */
static int& GlobalMark() static int& GlobalMark()
{ {
static int im = 0; static int im = 0;
return im; return im;
} }
static void Insert(HeapType& heap, PosType& p, int mark, BaseParameterClass *pp) static void Insert(HeapType& heap, PosType& p, int mark, BaseParameterClass *pp)
{ {
if(!p.IsBorder() && p.F()->IsW() && p.FFlip()->IsW()) { if(!p.IsBorder() && p.F()->IsW() && p.FFlip()->IsW()) {
MYTYPE* newflip = new MYTYPE(p, mark,pp); MYTYPE* newflip = new MYTYPE(p, mark,pp);
heap.push_back(HeapElem(newflip)); heap.push_back(HeapElem(newflip));
std::push_heap(heap.begin(), heap.end()); std::push_heap(heap.begin(), heap.end());
} }
} }
public: public:
/*! /*!
* Default constructor * Default constructor
*/ */
inline PlanarEdgeFlip() inline PlanarEdgeFlip()
{ {
} }
/*! /*!
* Constructor with <I>pos</I> type * Constructor with <I>pos</I> type
*/ */
inline PlanarEdgeFlip(PosType pos, int mark,BaseParameterClass *pp) inline PlanarEdgeFlip(PosType pos, int mark,BaseParameterClass *pp)
{ {
_pos = pos; _pos = pos;
_localMark = mark; _localMark = mark;
_priority = this->ComputePriority(pp); _priority = this->ComputePriority(pp);
} }
/*! /*!
* Copy Constructor * Copy Constructor
*/ */
inline PlanarEdgeFlip(const PlanarEdgeFlip &par) inline PlanarEdgeFlip(const PlanarEdgeFlip &par)
{ {
_pos = par.GetPos(); _pos = par.GetPos();
_localMark = par.GetMark(); _localMark = par.GetMark();
_priority = par.Priority(); _priority = par.Priority();
} }
/*! /*!
*/ */
~PlanarEdgeFlip() ~PlanarEdgeFlip()
{ {
} }
/*! /*!
* Parameter * Parameter
*/ */
inline PosType GetPos() const inline PosType GetPos() const
{ {
return _pos; return _pos;
} }
inline int GetMark()const inline int GetMark()const
{ {
return _localMark; return _localMark;
} }
/*! /*!
* Return the LocalOptimization type * Return the LocalOptimization type
*/ */
ModifierType IsOfType() ModifierType IsOfType()
{ {
return TriEdgeFlipOp; return TriEdgeFlipOp;
} }
/*! /*!
* Check if the pos is updated * Check if the pos is updated
*/ */
bool IsUpToDate() const bool IsUpToDate() const
{ {
int lastMark = _pos.F()->cV(0)->IMark(); int lastMark = _pos.F()->cV(0)->IMark();
lastMark = std::max<int>(lastMark, _pos.F()->V(1)->IMark()); lastMark = std::max<int>(lastMark, _pos.F()->V(1)->IMark());
lastMark = std::max<int>(lastMark, _pos.F()->V(2)->IMark()); lastMark = std::max<int>(lastMark, _pos.F()->V(2)->IMark());
return ( _localMark >= lastMark ); return ( _localMark >= lastMark );
} }
/*! /*!
* *
Check if this flipping operation can be performed. Check if this flipping operation can be performed.
It is a topological and geometrical check. It is a topological and geometrical check.
*/ */
virtual bool IsFeasible(BaseParameterClass *_pp) virtual bool IsFeasible(BaseParameterClass *_pp)
{ {
PlanarEdgeFlipParameter *pp=(PlanarEdgeFlipParameter *)_pp; PlanarEdgeFlipParameter *pp=(PlanarEdgeFlipParameter *)_pp;
if(!vcg::face::CheckFlipEdge(*this->_pos.F(), this->_pos.E())) if(!vcg::face::CheckFlipEdge(*this->_pos.F(), this->_pos.E()))
return false; return false;
if( math::ToDeg( Angle(_pos.FFlip()->cN(), _pos.F()->cN()) ) > pp->CoplanarAngleThresholdDeg ) if( math::ToDeg( Angle(_pos.FFlip()->cN(), _pos.F()->cN()) ) > pp->CoplanarAngleThresholdDeg )
return false; return false;
CoordType v0, v1, v2, v3; CoordType v0, v1, v2, v3;
int i = _pos.E(); int i = _pos.E();
v0 = _pos.F()->P0(i); v0 = _pos.F()->P0(i);
v1 = _pos.F()->P1(i); v1 = _pos.F()->P1(i);
v2 = _pos.F()->P2(i); v2 = _pos.F()->P2(i);
v3 = _pos.F()->FFp(i)->P2(_pos.F()->FFi(i)); v3 = _pos.F()->FFp(i)->P2(_pos.F()->FFi(i));
// Take the parallelogram formed by the adjacent faces of edge // Take the parallelogram formed by the adjacent faces of edge
// If a corner of the parallelogram on extreme of edge to flip is >= 180 // If a corner of the parallelogram on extreme of edge to flip is >= 180
// the flip produce two identical faces - avoid this // the flip produce two identical faces - avoid this
if( (Angle(v2 - v0, v1 - v0) + Angle(v3 - v0, v1 - v0) >= M_PI) || if( (Angle(v2 - v0, v1 - v0) + Angle(v3 - v0, v1 - v0) >= M_PI) ||
(Angle(v2 - v1, v0 - v1) + Angle(v3 - v1, v0 - v1) >= M_PI)) (Angle(v2 - v1, v0 - v1) + Angle(v3 - v1, v0 - v1) >= M_PI))
return false; return false;
// if any of two faces adj to edge in non writable, the flip is unfeasible // if any of two faces adj to edge in non writable, the flip is unfeasible
if(!_pos.F()->IsW() || !_pos.F()->FFp(i)->IsW()) if(!_pos.F()->IsW() || !_pos.F()->FFp(i)->IsW())
return false; return false;
return true; return true;
} }
/*! /*!
* Compute the priority of this optimization * Compute the priority of this optimization
*/ */
/* /*
1 1
/|\ /|\
/ | \ / | \
2 | 3 2 | 3
\ | / \ | /
\|/ \|/
0 0
*/ */
ScalarType ComputePriority(BaseParameterClass *) ScalarType ComputePriority(BaseParameterClass *)
{ {
CoordType v0, v1, v2, v3; CoordType v0, v1, v2, v3;
int i = _pos.E(); int i = _pos.E();
v0 = _pos.F()->P0(i); v0 = _pos.F()->P0(i);
v1 = _pos.F()->P1(i); v1 = _pos.F()->P1(i);
v2 = _pos.F()->P2(i); v2 = _pos.F()->P2(i);
v3 = _pos.F()->FFp(i)->P2(_pos.F()->FFi(i)); v3 = _pos.F()->FFp(i)->P2(_pos.F()->FFi(i));
ScalarType Qa = QualityFunc(v0, v1, v2); ScalarType Qa = QualityFunc(v0, v1, v2);
ScalarType Qb = QualityFunc(v0, v3, v1); ScalarType Qb = QualityFunc(v0, v3, v1);
ScalarType QaAfter = QualityFunc(v1, v2, v3); ScalarType QaAfter = QualityFunc(v1, v2, v3);
ScalarType QbAfter = QualityFunc(v0, v3, v2); ScalarType QbAfter = QualityFunc(v0, v3, v2);
// < 0 if the average quality of faces improves after flip // < 0 if the average quality of faces improves after flip
_priority = (Qa + Qb - QaAfter - QbAfter) / (ScalarType)2.0; _priority = (Qa + Qb - QaAfter - QbAfter) / (ScalarType)2.0;
return _priority; return _priority;
} }
/*! /*!
* Return the priority of this optimization * Return the priority of this optimization
*/ */
virtual ScalarType Priority() const virtual ScalarType Priority() const
{ {
return _priority; return _priority;
} }
/*! /*!
* Execute the flipping of the edge * Execute the flipping of the edge
*/ */
void Execute(TRIMESH_TYPE &m, BaseParameterClass *) void Execute(TRIMESH_TYPE &m, BaseParameterClass *)
{ {
int i = _pos.E(); int i = _pos.E();
int j = _pos.F()->FFi(i); int j = _pos.F()->FFi(i);
FacePointer f1 = _pos.F(); FacePointer f1 = _pos.F();
FacePointer f2 = _pos.F()->FFp(i); FacePointer f2 = _pos.F()->FFp(i);
vcg::face::FlipEdge(*_pos.F(), _pos.E()); vcg::face::FlipEdge(*_pos.F(), _pos.E());
// avoid texture coordinates swap after flip // avoid texture coordinates swap after flip
if(tri::HasPerWedgeTexCoord(m)) { if(tri::HasPerWedgeTexCoord(m)) {
f2->WT((j + 1) % 3) = f1->WT((i + 2) % 3); f2->WT((j + 1) % 3) = f1->WT((i + 2) % 3);
f1->WT((i + 1) % 3) = f2->WT((j + 2) % 3); f1->WT((i + 1) % 3) = f2->WT((j + 2) % 3);
} }
} }
/*! /*!
*/ */
const char* Info(TRIMESH_TYPE &m) const char* Info(TRIMESH_TYPE &m)
{ {
static char dump[60]; static char dump[60];
sprintf(dump,"%lu -> %lu %g\n", tri::Index(m,_pos.F()->V(0)), tri::Index(m,_pos.F()->V(1)),-_priority); sprintf(dump,"%lu -> %lu %g\n", tri::Index(m,_pos.F()->V(0)), tri::Index(m,_pos.F()->V(1)),-_priority);
return dump; return dump;
} }
/*! /*!
*/ */
static void Init(TRIMESH_TYPE &mesh, HeapType &heap, BaseParameterClass *pp) static void Init(TRIMESH_TYPE &mesh, HeapType &heap, BaseParameterClass *pp)
{ {
heap.clear(); heap.clear();
FaceIterator fi; FaceIterator fi;
for(fi = mesh.face.begin(); fi != mesh.face.end(); ++fi) { for(fi = mesh.face.begin(); fi != mesh.face.end(); ++fi) {
if(!(*fi).IsD() && (*fi).IsW()) { if(!(*fi).IsD() && (*fi).IsW()) {
for(unsigned int i = 0; i < 3; i++) { for(unsigned int i = 0; i < 3; i++) {
if( !(*fi).IsB(i) && !((*fi).FFp(i)->IsD()) && (*fi).FFp(i)->IsW() ) { if( !(*fi).IsB(i) && !((*fi).FFp(i)->IsD()) && (*fi).FFp(i)->IsW() ) {
if((*fi).V1(i) - (*fi).V0(i) > 0) { if((*fi).V1(i) - (*fi).V0(i) > 0) {
PosType p(&*fi, i); PosType p(&*fi, i);
Insert(heap, p, IMark(mesh),pp); Insert(heap, p, IMark(mesh),pp);
} }
//heap.push_back( HeapElem( new MYTYPE(PosType(&*fi, i), mesh.IMark() )) ); //heap.push_back( HeapElem( new MYTYPE(PosType(&*fi, i), mesh.IMark() )) );
} //endif } //endif
} //endfor } //endfor
} }
} //endfor } //endfor
} }
/*! /*!
*/ */
virtual void UpdateHeap(HeapType &heap, BaseParameterClass *pp) virtual void UpdateHeap(HeapType &heap, BaseParameterClass *pp)
{ {
GlobalMark()++; GlobalMark()++;
// after flip, the new edge just created is the next edge // after flip, the new edge just created is the next edge
int flipped = (_pos.E() + 1) % 3; int flipped = (_pos.E() + 1) % 3;
PosType pos(_pos.F(), flipped); PosType pos(_pos.F(), flipped);
pos.F()->V(0)->IMark() = GlobalMark(); pos.F()->V(0)->IMark() = GlobalMark();
pos.F()->V(1)->IMark() = GlobalMark(); pos.F()->V(1)->IMark() = GlobalMark();
pos.F()->V(2)->IMark() = GlobalMark(); pos.F()->V(2)->IMark() = GlobalMark();
pos.F()->FFp(flipped)->V2(pos.F()->FFi(flipped))->IMark() = GlobalMark(); pos.F()->FFp(flipped)->V2(pos.F()->FFi(flipped))->IMark() = GlobalMark();
pos.FlipF(); pos.FlipE(); pos.FlipF(); pos.FlipE();
Insert(heap, pos, GlobalMark(),pp); Insert(heap, pos, GlobalMark(),pp);
pos.FlipV(); pos.FlipE(); pos.FlipV(); pos.FlipE();
Insert(heap, pos, GlobalMark(),pp); Insert(heap, pos, GlobalMark(),pp);
pos.FlipV(); pos.FlipE(); pos.FlipV(); pos.FlipE();
pos.FlipF(); pos.FlipE(); pos.FlipF(); pos.FlipE();
Insert(heap, pos, GlobalMark(),pp); Insert(heap, pos, GlobalMark(),pp);
pos.FlipV(); pos.FlipE(); pos.FlipV(); pos.FlipE();
Insert(heap, pos, GlobalMark(),pp); Insert(heap, pos, GlobalMark(),pp);
} }
}; // end of PlanarEdgeFlip class }; // end of PlanarEdgeFlip class
@ -345,63 +345,63 @@ template <class TRIMESH_TYPE, class MYTYPE>
class TriEdgeFlip : public PlanarEdgeFlip<TRIMESH_TYPE, MYTYPE> class TriEdgeFlip : public PlanarEdgeFlip<TRIMESH_TYPE, MYTYPE>
{ {
protected: protected:
typedef typename TRIMESH_TYPE::FaceType FaceType; typedef typename TRIMESH_TYPE::FaceType FaceType;
typedef typename TRIMESH_TYPE::ScalarType ScalarType; typedef typename TRIMESH_TYPE::ScalarType ScalarType;
typedef typename TRIMESH_TYPE::CoordType CoordType; typedef typename TRIMESH_TYPE::CoordType CoordType;
typedef vcg::face::Pos<FaceType> PosType; typedef vcg::face::Pos<FaceType> PosType;
public: public:
/*! /*!
* Default constructor * Default constructor
*/ */
inline TriEdgeFlip() {} inline TriEdgeFlip() {}
/*! /*!
* Constructor with <I>pos</I> type * Constructor with <I>pos</I> type
*/ */
inline TriEdgeFlip(const PosType pos, int mark, BaseParameterClass *pp) inline TriEdgeFlip(const PosType pos, int mark, BaseParameterClass *pp)
{ {
this->_pos = pos; this->_pos = pos;
this->_localMark = mark; this->_localMark = mark;
this->_priority = ComputePriority(pp); this->_priority = ComputePriority(pp);
} }
/*! /*!
* Copy Constructor * Copy Constructor
*/ */
inline TriEdgeFlip(const TriEdgeFlip &par) inline TriEdgeFlip(const TriEdgeFlip &par)
{ {
this->_pos = par.GetPos(); this->_pos = par.GetPos();
this->_localMark = par.GetMark(); this->_localMark = par.GetMark();
this->_priority = par.Priority(); this->_priority = par.Priority();
} }
ScalarType ComputePriority(BaseParameterClass *) ScalarType ComputePriority(BaseParameterClass *)
{ {
/* /*
1 1
/|\ /|\
/ | \ / | \
2 | 3 2 | 3
\ | / \ | /
\|/ \|/
0 0
*/ */
CoordType v0, v1, v2, v3; CoordType v0, v1, v2, v3;
int i = this->_pos.E(); int i = this->_pos.E();
v0 = this->_pos.F()->P0(i); v0 = this->_pos.F()->P0(i);
v1 = this->_pos.F()->P1(i); v1 = this->_pos.F()->P1(i);
v2 = this->_pos.F()->P2(i); v2 = this->_pos.F()->P2(i);
v3 = this->_pos.F()->FFp(i)->P2(this->_pos.F()->FFi(i)); v3 = this->_pos.F()->FFp(i)->P2(this->_pos.F()->FFi(i));
// if the sum of angles in v2 e v3 is > 180, then the triangle // if the sum of angles in v2 e v3 is > 180, then the triangle
// pair is not a delaunay triangulation // pair is not a delaunay triangulation
ScalarType alpha = math::Abs(Angle(v0 - v2, v1 - v2)); ScalarType alpha = math::Abs(Angle(v0 - v2, v1 - v2));
ScalarType beta = math::Abs(Angle(v0 - v3, v1 - v3)); ScalarType beta = math::Abs(Angle(v0 - v3, v1 - v3));
this->_priority = 180 - math::ToDeg((alpha + beta)); this->_priority = 180 - math::ToDeg((alpha + beta));
return this->_priority; return this->_priority;
} }
}; };
@ -411,203 +411,203 @@ template <class TRIMESH_TYPE, class MYTYPE>
class TopoEdgeFlip : public PlanarEdgeFlip<TRIMESH_TYPE, MYTYPE> class TopoEdgeFlip : public PlanarEdgeFlip<TRIMESH_TYPE, MYTYPE>
{ {
protected: protected:
typedef typename TRIMESH_TYPE::VertexPointer VertexPointer; typedef typename TRIMESH_TYPE::VertexPointer VertexPointer;
typedef typename TRIMESH_TYPE::FaceType FaceType; typedef typename TRIMESH_TYPE::FaceType FaceType;
typedef typename TRIMESH_TYPE::FacePointer FacePointer; typedef typename TRIMESH_TYPE::FacePointer FacePointer;
typedef typename TRIMESH_TYPE::ScalarType ScalarType; typedef typename TRIMESH_TYPE::ScalarType ScalarType;
typedef typename TRIMESH_TYPE::CoordType CoordType; typedef typename TRIMESH_TYPE::CoordType CoordType;
typedef vcg::face::Pos<FaceType> PosType; typedef vcg::face::Pos<FaceType> PosType;
typedef typename LocalOptimization<TRIMESH_TYPE>::HeapElem HeapElem; typedef typename LocalOptimization<TRIMESH_TYPE>::HeapElem HeapElem;
typedef typename LocalOptimization<TRIMESH_TYPE>::HeapType HeapType; typedef typename LocalOptimization<TRIMESH_TYPE>::HeapType HeapType;
typedef typename TRIMESH_TYPE::FaceIterator FaceIterator; typedef typename TRIMESH_TYPE::FaceIterator FaceIterator;
typedef typename TRIMESH_TYPE::VertexIterator VertexIterator; typedef typename TRIMESH_TYPE::VertexIterator VertexIterator;
public: public:
/*! /*!
* Default constructor * Default constructor
*/ */
inline TopoEdgeFlip() {} inline TopoEdgeFlip() {}
/*! /*!
* Constructor with <I>pos</I> type * Constructor with <I>pos</I> type
*/ */
inline TopoEdgeFlip(const PosType pos, int mark, BaseParameterClass *pp) inline TopoEdgeFlip(const PosType pos, int mark, BaseParameterClass *pp)
{ {
this->_pos = pos; this->_pos = pos;
this->_localMark = mark; this->_localMark = mark;
this->_priority = ComputePriority(pp); this->_priority = ComputePriority(pp);
} }
/*! /*!
* Copy Constructor * Copy Constructor
*/ */
inline TopoEdgeFlip(const TopoEdgeFlip &par) inline TopoEdgeFlip(const TopoEdgeFlip &par)
{ {
this->_pos = par.GetPos(); this->_pos = par.GetPos();
this->_localMark = par.GetMark(); this->_localMark = par.GetMark();
this->_priority = par.Priority(); this->_priority = par.Priority();
} }
ScalarType ComputePriority(BaseParameterClass *) ScalarType ComputePriority(BaseParameterClass *)
{ {
/* /*
1 1
/|\ /|\
/ | \ / | \
2 | 3 2 | 3
\ | / \ | /
\|/ \|/
0 0
*/ */
VertexPointer v0, v1, v2, v3; VertexPointer v0, v1, v2, v3;
int i = this->_pos.E(); int i = this->_pos.E();
v0 = this->_pos.F()->V0(i); v0 = this->_pos.F()->V0(i);
v1 = this->_pos.F()->V1(i); v1 = this->_pos.F()->V1(i);
v2 = this->_pos.F()->V2(i); v2 = this->_pos.F()->V2(i);
v3 = this->_pos.F()->FFp(i)->V2(this->_pos.F()->FFi(i)); v3 = this->_pos.F()->FFp(i)->V2(this->_pos.F()->FFi(i));
// This kind of flip minimize the variance of number of incident faces // This kind of flip minimize the variance of number of incident faces
// on the vertices of two faces involved in the flip // on the vertices of two faces involved in the flip
ScalarType avg = (v0->Q() + v1->Q() + v2->Q() + v3->Q()) / 4.0; ScalarType avg = (v0->Q() + v1->Q() + v2->Q() + v3->Q()) / 4.0;
ScalarType varbefore = (powf(v0->Q() - avg, 2.0) + ScalarType varbefore = (powf(v0->Q() - avg, 2.0) +
powf(v1->Q() - avg, 2.0) + powf(v1->Q() - avg, 2.0) +
powf(v2->Q() - avg, 2.0) + powf(v2->Q() - avg, 2.0) +
powf(v3->Q() - avg, 2.0)) / 4.0; powf(v3->Q() - avg, 2.0)) / 4.0;
ScalarType varafter = (powf(v0->Q() - 1 - avg, 2.0) + ScalarType varafter = (powf(v0->Q() - 1 - avg, 2.0) +
powf(v1->Q() - 1 - avg, 2.0) + powf(v1->Q() - 1 - avg, 2.0) +
powf(v2->Q() + 1 - avg, 2.0) + powf(v2->Q() + 1 - avg, 2.0) +
powf(v3->Q() + 1 - avg, 2.0)) / 4.0; powf(v3->Q() + 1 - avg, 2.0)) / 4.0;
this->_priority = varafter - varbefore; this->_priority = varafter - varbefore;
return this->_priority; return this->_priority;
} }
/*! /*!
* Execute the flipping of the edge * Execute the flipping of the edge
*/ */
void Execute(TRIMESH_TYPE &m) void Execute(TRIMESH_TYPE &m, BaseParameterClass *)
{ {
int i = this->_pos.E(); int i = this->_pos.E();
FacePointer f1 = this->_pos.F(); FacePointer f1 = this->_pos.F();
FacePointer f2 = f1->FFp(i); FacePointer f2 = f1->FFp(i);
int j = f1->FFi(i); int j = f1->FFi(i);
// update the number of faces adjacent to vertices // update the number of faces adjacent to vertices
f1->V0(i)->Q()--; f1->V0(i)->Q()--;
f1->V1(i)->Q()--; f1->V1(i)->Q()--;
f1->V2(i)->Q()++; f1->V2(i)->Q()++;
f2->V2(j)->Q()++; f2->V2(j)->Q()++;
// do the flip // do the flip
vcg::face::FlipEdge(*this->_pos.F(), this->_pos.E()); vcg::face::FlipEdge(*this->_pos.F(), this->_pos.E());
// avoid texture coordinates swap after flip // avoid texture coordinates swap after flip
if (tri::HasPerWedgeTexCoord(m)) { if (tri::HasPerWedgeTexCoord(m)) {
f2->WT((j + 1) % 3) = f1->WT((i + 2) % 3); f2->WT((j + 1) % 3) = f1->WT((i + 2) % 3);
f1->WT((i + 1) % 3) = f2->WT((j + 2) % 3); f1->WT((i + 1) % 3) = f2->WT((j + 2) % 3);
} }
} }
static void Init(TRIMESH_TYPE &m, HeapType &heap,BaseParameterClass *pp) static void Init(TRIMESH_TYPE &m, HeapType &heap,BaseParameterClass *pp)
{ {
// reset quality field for each vertex // reset quality field for each vertex
VertexIterator vi; VertexIterator vi;
for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
if(!(*vi).IsD()) if(!(*vi).IsD())
(*vi).Q() = 0; (*vi).Q() = 0;
// for each vertex, put the number of incident faces in quality field // for each vertex, put the number of incident faces in quality field
FaceIterator fi; FaceIterator fi;
for(fi = m.face.begin(); fi != m.face.end(); ++fi) for(fi = m.face.begin(); fi != m.face.end(); ++fi)
if(!(*fi).IsD()) if(!(*fi).IsD())
for(int i = 0; i < 3; i++) for(int i = 0; i < 3; i++)
(*fi).V(i)->Q()++; (*fi).V(i)->Q()++;
TriEdgeFlip<TRIMESH_TYPE, MYTYPE>::Init(m, heap, pp); TriEdgeFlip<TRIMESH_TYPE, MYTYPE>::Init(m, heap, pp);
} }
void UpdateHeap(HeapType &heap) void UpdateHeap(HeapType &heap, BaseParameterClass *pp)
{ {
this->GlobalMark()++; this->GlobalMark()++;
VertexPointer v0, v1, v2, v3; VertexPointer v0, v1, v2, v3;
int flipped = (this->_pos.E() + 1) % 3; int flipped = (this->_pos.E() + 1) % 3;
FacePointer f1 = this->_pos.F(); FacePointer f1 = this->_pos.F();
FacePointer f2 = this->_pos.F()->FFp(flipped); FacePointer f2 = this->_pos.F()->FFp(flipped);
v0 = f1->V0(flipped); v0 = f1->V0(flipped);
v1 = f1->V1(flipped); v1 = f1->V1(flipped);
v2 = f1->V2(flipped); v2 = f1->V2(flipped);
v3 = f2->V2(f1->FFi(flipped)); v3 = f2->V2(f1->FFi(flipped));
v0->IMark() = this->GlobalMark(); v0->IMark() = this->GlobalMark();
v1->IMark() = this->GlobalMark(); v1->IMark() = this->GlobalMark();
v2->IMark() = this->GlobalMark(); v2->IMark() = this->GlobalMark();
v3->IMark() = this->GlobalMark(); v3->IMark() = this->GlobalMark();
// edges of the first face, except the flipped edge // edges of the first face, except the flipped edge
for(int i = 0; i < 3; i++) if(i != flipped) { for(int i = 0; i < 3; i++) if(i != flipped) {
PosType newpos(f1, i); PosType newpos(f1, i);
Insert(heap, newpos, this->GlobalMark()); this->Insert(heap, newpos, this->GlobalMark(),pp);
} }
// edges of the second face, except the flipped edge // edges of the second face, except the flipped edge
for(int i = 0; i < 3; i++) if(i != f1->FFi(flipped)) { for(int i = 0; i < 3; i++) if(i != f1->FFi(flipped)) {
PosType newpos(f2, i); PosType newpos(f2, i);
Insert(heap, newpos, this->GlobalMark()); this->Insert(heap, newpos, this->GlobalMark(),pp);
} }
// every edge with v0, v1 v3 of f1 // every edge with v0, v1 v3 of f1
for(int i = 0; i < 3; i++) { for(int i = 0; i < 3; i++) {
PosType startpos(f1, i); PosType startpos(f1, i);
PosType pos(startpos); PosType pos(startpos);
do { // go to the first border (if there is one) do { // go to the first border (if there is one)
pos.NextE(); pos.NextE();
} while(pos != startpos && !pos.IsBorder()); } while(pos != startpos && !pos.IsBorder());
// if a border is reached, set startpos here // if a border is reached, set startpos here
if(pos.IsBorder()) if(pos.IsBorder())
startpos = pos; startpos = pos;
do { do {
VertexPointer v = pos.VFlip(); VertexPointer v = pos.VFlip();
if(v != v0 && v != v1 && v != v2 && v != v3) if(v != v0 && v != v1 && v != v2 && v != v3)
Insert(heap, pos, this->GlobalMark()); this->Insert(heap, pos, this->GlobalMark(),pp);
pos.NextE(); pos.NextE();
} while(pos != startpos && !pos.IsBorder()); } while(pos != startpos && !pos.IsBorder());
} }
PosType startpos(f2, (f1->FFi(flipped) + 2) % 3); PosType startpos(f2, (f1->FFi(flipped) + 2) % 3);
PosType pos(startpos); PosType pos(startpos);
do { // go to the first border (if there is one) do { // go to the first border (if there is one)
pos.NextE(); pos.NextE();
} while(pos != startpos && !pos.IsBorder()); } while(pos != startpos && !pos.IsBorder());
// if a border is reached, set startpos here // if a border is reached, set startpos here
if(pos.IsBorder()) if(pos.IsBorder())
startpos = pos; startpos = pos;
do { do {
VertexPointer v = pos.VFlip(); VertexPointer v = pos.VFlip();
if(v != v0 && v != v1 && v != v2 && v != v3) if(v != v0 && v != v1 && v != v2 && v != v3)
Insert(heap, pos, this->GlobalMark()); this->Insert(heap, pos, this->GlobalMark(),pp);
pos.NextE(); pos.NextE();
} while(pos != startpos && !pos.IsBorder()); } while(pos != startpos && !pos.IsBorder());
} }
}; };