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