Heavily changed the whole hole filling class, now much shorter, more readable and hopefully more robust.

Still to better balance shape vs diedral angle quality measure.
This commit is contained in:
Paolo Cignoni 2012-07-31 09:13:48 +00:00
parent 0edde01197
commit f3ef64cc0c
1 changed files with 428 additions and 556 deletions

View File

@ -19,120 +19,6 @@
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log: not supported by cvs2svn $
Revision 1.34 2007/01/31 15:25:49 giec
Remove some usless code in Minimum Weight Triangulation.
Revision 1.33 2007/01/31 11:46:12 giec
Bug fix
Revision 1.32 2007/01/18 18:15:14 cignoni
added missing typenames
Revision 1.31 2007/01/18 11:17:43 giec
The minimum weight algorithm keep the topology consistent.
Revision 1.30 2007/01/10 12:07:54 giec
Bugfixed ComputeDihedralAngle function
Revision 1.29 2006/12/27 15:09:52 giec
Bug fix on ComputeDihedralAngle function
Revision 1.28 2006/12/12 11:14:51 cignoni
Commented some variant of the quality measure of weighted ears
Revision 1.27 2006/12/07 00:40:18 cignoni
Added many this-> for gcc compiling
Revision 1.26 2006/12/06 13:03:59 cignoni
Corrected bugs on selfintersection
Revision 1.25 2006/12/06 00:12:53 cignoni
Heavily restructured and corrected. Now a single Close ear function
Corrected Hole search function, and management of double non manifold vertex in a hole
Changed priority strategy in the heap, now a mix of quality and dihedral angle.
Changed but still untested IntersectionEar
Revision 1.24 2006/12/01 21:24:16 cignoni
Corrected bug in the search of holes. Removed output prints
Revision 1.23 2006/12/01 08:53:55 cignoni
Corrected pop_heap vs pop_back issue in heap usage
Revision 1.22 2006/12/01 00:11:17 cignoni
Added Callback, Corrected some spelling errors (adiacense -> adjacency).
Added Validity Check function for hole loops
Revision 1.21 2006/11/30 11:49:20 cignoni
small gcc compiling issues
Revision 1.20 2006/11/29 16:21:45 cignoni
Made static exposed funtions of the class
Revision 1.19 2006/11/29 15:25:22 giec
Removed limit.
Revision 1.18 2006/11/29 15:18:49 giec
Code refactory and bugfix.
Revision 1.17 2006/11/24 10:42:39 mariolatronico
Now compiles on gcc under linux.
Revision 1.16 2006/11/22 13:43:28 giec
Code refactory and added minimum weight triangolation.
Revision 1.15 2006/11/13 10:11:38 giec
Clear some useless code
Revision 1.14 2006/11/07 15:13:56 zifnab1974
Necessary changes for compilation with gcc 3.4.6. Especially the hash function is a problem
Revision 1.13 2006/11/07 11:47:11 cignoni
gcc compiling issues
Revision 1.12 2006/11/07 07:56:43 cignoni
Added missing std::
Revision 1.11 2006/11/06 16:12:29 giec
Leipa ear now compute max dihedral angle.
Revision 1.10 2006/10/31 11:30:41 ganovelli
changed access throught iterator with static call to comply 2005 compiler
Revision 1.9 2006/10/20 07:44:45 cignoni
Added missing std::
Revision 1.8 2006/10/18 15:06:47 giec
New policy for compute quality in TrivialEar.
Bugfixed LeipaEar.
Added new algorithm "selfintersection" with test for self intersection.
Revision 1.7 2006/10/10 09:12:02 giec
Bugfix and added a new type of ear (Liepa like)
Revision 1.6 2006/10/09 10:07:07 giec
Optimized version of "EAR HOLE FILLING", the Ear is selected according to its dihedral angle.
Revision 1.5 2006/10/06 15:28:14 giec
first working implementationof "EAR HOLE FILLING".
Revision 1.4 2006/10/02 12:06:40 giec
BugFix
Revision 1.3 2006/09/27 15:33:32 giec
It close one simple hole . . .
Revision 1.2 2006/09/27 09:29:53 giec
Frist working release whit a few bugs.
It almost fills the hole ...
Revision 1.1 2006/09/25 09:17:44 cignoni
First Non working Version
****************************************************************************/
#ifndef __VCG_TRI_UPDATE_HOLE
#define __VCG_TRI_UPDATE_HOLE
@ -140,21 +26,29 @@ First Non working Version
#include <wrap/callback.h>
#include <vcg/math/base.h>
#include <vcg/complex/algorithms/clean.h>
#include <vcg/space/point3.h>
#include <vector>
#include <float.h>
// This file contains three Ear Classes
// - TrivialEar
// - MinimumWeightEar
// - SelfIntersectionEar
// and a static class Hole for filling holes that is templated on the ear class
namespace vcg {
namespace tri {
/*
Un ear e' identificato da due hedge pos.
i vertici dell'ear sono
An ear is identified by TWO pos.
The Three vertexes of an Ear are:
e0.VFlip().v
e0.v
e1.v
Vale che e1== e0.NextB();
e che e1.FlipV() == e0;
Invariants:
e1 == e0.NextB();
e1.FlipV() == e0;
Situazioni ear non manifold, e degeneri (buco triangolare)
T XXXXXXXXXXXXX A /XXXXX B en/XXXXX
@ -167,9 +61,9 @@ namespace vcg {
XXX \|/XXXXXXXX XXX \|/XXXXXXXX XXX \|/XXXXXXXX
XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
*/
template<class MESH> class TrivialEar
{
public:
template<class MESH> class TrivialEar
{
public:
typedef typename MESH::FaceType FaceType;
typedef typename MESH::FacePointer FacePointer;
typedef typename face::Pos<FaceType> PosType;
@ -180,6 +74,8 @@ namespace vcg {
PosType e1;
CoordType n; // the normal of the face defined by the ear
const char * Dump() {return 0;}
// The following members are useful to consider the Ear as a generic <triangle>
// with p0 the 'center' of the ear.
const CoordType &cP(int i) const {return P(i);}
const CoordType &P(int i) const {
switch(i) {
@ -192,8 +88,7 @@ namespace vcg {
}
ScalarType quality;
ScalarType angle;
//std::vector<typename MESH::FaceType>* vf;
ScalarType angleRad;
TrivialEar(){}
TrivialEar(const PosType & ep)
{
@ -211,17 +106,17 @@ namespace vcg {
// the angle computation takes into account the case of reversed ears
void ComputeAngle()
{
angle=Angle(cP(2)-cP(0), cP(1)-cP(0));
angleRad=Angle(cP(2)-cP(0), cP(1)-cP(0));
ScalarType flipAngle = n.dot(e0.v->N());
if(flipAngle<0) angle = (2.0 *(float)M_PI) - angle;
if(flipAngle<0) angleRad = (2.0 *(ScalarType)M_PI) - angleRad;
}
virtual inline bool operator < ( const TrivialEar & c ) const { return quality < c.quality; }
bool IsNull(){return e0.IsNull() || e1.IsNull();}
void SetNull(){e0.SetNull();e1.SetNull();}
virtual void ComputeQuality() { quality = QualityFace(*this) ; };
bool IsUpToDate() {return ( e0.IsBorder() && e1.IsBorder());};
virtual void ComputeQuality() { quality = QualityFace(*this) ; }
bool IsUpToDate() {return ( e0.IsBorder() && e1.IsBorder());}
// An ear is degenerated if both of its two endpoints are non manifold.
bool IsDegen(const int nonManifoldBit)
{
@ -229,7 +124,7 @@ namespace vcg {
return true;
else return false;
}
bool IsConcave() const {return(angle > (float)M_PI);}
bool IsConcave() const {return(angleRad > (float)M_PI);}
virtual bool Close(PosType &np0, PosType &np1, FaceType * f)
{
@ -248,27 +143,15 @@ namespace vcg {
(*f).V(2) = e1.v;
ComputeNormal(*f);
(*f).FFp(0) = e0.f;
(*f).FFi(0) = e0.z;
(*f).FFp(1) = e1.f;
(*f).FFi(1) = e1.z;
(*f).FFp(2) = f;
(*f).FFi(2) = 2;
e0.f->FFp(e0.z)=f;
e0.f->FFi(e0.z)=0;
e1.f->FFp(e1.z)=f;
e1.f->FFi(e1.z)=1;
face::FFAttachManifold(f,0,e0.f,e0.z);
face::FFAttachManifold(f,1,e1.f,e1.z);
face::FFSetBorder(f,2);
// caso ear degenere per buco triangolare
if(ep==en)
{
//printf("Closing the last triangle");
f->FFp(2)=en.f;
f->FFi(2)=en.z;
en.f->FFp(en.z)=f;
en.f->FFi(en.z)=2;
face::FFAttachManifold(f,2,en.f,en.z);
np0.SetNull();
np1.SetNull();
}
@ -278,10 +161,7 @@ namespace vcg {
//printf("Ear Non manif A\n");
PosType enold=en;
en.NextB();
f->FFp(2)=enold.f;
f->FFi(2)=enold.z;
enold.f->FFp(enold.z)=f;
enold.f->FFi(enold.z)=2;
face::FFAttachManifold(f,2,enold.f,enold.z);
np0=ep;
np1=en;
}
@ -291,10 +171,7 @@ namespace vcg {
//printf("Ear Non manif B\n");
PosType epold=ep;
ep.FlipV(); ep.NextB(); ep.FlipV();
f->FFp(2)=epold.f;
f->FFi(2)=epold.z;
epold.f->FFp(epold.z)=f;
epold.f->FFi(epold.z)=2;
face::FFAttachManifold(f,2,epold.f,epold.z);
np0=ep; // assign the two new
np1=en; // pos that denote the ears
}
@ -306,13 +183,14 @@ namespace vcg {
return true;
}
};
//Ear with FillHoleMinimumWeight's quality policy
template<class MESH> class MinimumWeightEar : public TrivialEar<MESH>
{
public:
static float &DiedralWeight() { static float _dw=1.0; return _dw;}
}; // end TrivialEar Class
//Ear with FillHoleMinimumWeight's quality policy
template<class MESH> class MinimumWeightEar : public TrivialEar<MESH>
{
public:
static float &DiedralWeight() { static float _dw=0.1; return _dw;}
typedef TrivialEar<MESH> TE;
typename MESH::ScalarType dihedralRad;
typename MESH::ScalarType aspectRatio;
@ -324,7 +202,6 @@ namespace vcg {
}
MinimumWeightEar(){}
//MinimumWeightEar(const PosType & ep) : TrivialEar<MESH>(ep)
MinimumWeightEar(const typename face::Pos<typename MESH::FaceType>& ep) : TrivialEar<MESH>(ep)
{
ComputeQuality();
@ -338,13 +215,12 @@ namespace vcg {
virtual inline bool operator < ( const MinimumWeightEar & c ) const
{
if(TE::IsConcave() == c.IsConcave())
{
return (pow((float)dihedralRad,(float)DiedralWeight())/aspectRatio) > (pow((float)c.dihedralRad,(float)DiedralWeight())/c.aspectRatio);
}
if(TE::IsConcave()) return true;
// assert(c.IsConcave());
return false;
if(TE::IsConcave() && ! c.IsConcave() ) return true;
if(!TE::IsConcave() && c.IsConcave() ) return false;
return aspectRatio - (dihedralRad/M_PI)*DiedralWeight() < c.aspectRatio -(c.dihedralRad/M_PI)*DiedralWeight();
// return (pow((float)dihedralRad,(float)DiedralWeight())/aspectRatio) > (pow((float)c.dihedralRad,(float)DiedralWeight())/c.aspectRatio);
}
// the real core of the whole hole filling strategy.
@ -358,11 +234,13 @@ namespace vcg {
aspectRatio = QualityFace(*this);
}
};
//Ear for selfintersection algorithm
template<class MESH> class SelfIntersectionEar : public MinimumWeightEar<MESH>
{
public:
}; // end class MinimumWeightEar
//Ear for selfintersection algorithm
template<class MESH> class SelfIntersectionEar : public MinimumWeightEar<MESH>
{
public:
typedef typename MESH::FaceType FaceType;
typedef typename MESH::FacePointer FacePointer;
typedef typename face::Pos<FaceType> PosType;
@ -382,59 +260,48 @@ namespace vcg {
{
PosType ep=this->e0; ep.FlipV(); ep.NextB(); ep.FlipV(); // he precedente a e0
PosType en=this->e1; en.NextB(); // he successivo a e1
// bool triangularHole = false;
// if(en==ep || en-) triangularHole=true;
//costruisco la faccia e poi testo, o copio o butto via.
(*f).V(0) = this->e0.VFlip();
(*f).V(1) = this->e0.v;
(*f).V(2) = this->e1.v;
face::FFSetBorder(f,0);
face::FFSetBorder(f,1);
face::FFSetBorder(f,2);
(*f).FFp(0) = this->e0.f;
(*f).FFi(0) = this->e0.z;
(*f).FFp(1) = this->e1.f;
(*f).FFi(1) = this->e1.z;
(*f).FFp(2) = f;
(*f).FFi(2) = 2;
int a1, a2;
a1= this->e0.z;
a2= this->e1.z;
this->e0.f->FFp(this->e0.z)=f;
this->e0.f->FFi(this->e0.z)=0;
this->e1.f->FFp(this->e1.z)=f;
this->e1.f->FFi(this->e1.z)=1;
typename std::vector< FacePointer >::iterator it;
for(it = this->AdjacencyRing().begin();it!= this->AdjacencyRing().end();++it)
{
if(!(*it)->IsD())
if( tri::Clean<MESH>::TestFaceFaceIntersection(&(*f),*it))
{
this->e0.f->FFp(this->e0.z)= this->e0.f;
this->e0.f->FFi(this->e0.z)=a1;
this->e1.f->FFp(this->e1.z)= this->e1.f;
this->e1.f->FFi(this->e1.z)=a2;
if( tri::Clean<MESH>::TestFaceFaceIntersection(f,*it))
return false;
// We must also check that the newly created face does not have any edge in common with other existing surrounding faces
// Only the two faces of the ear can share an edge with the new face
if(face::CountSharedVertex(f,*it)==2)
{
int e0,e1;
bool ret=face::FindSharedEdge(f,*it,e0,e1);
assert(ret);
if(!face::IsBorder(**it,e1))
return false;
}
}
//return ((TrivialEar<MESH> *)this)->Close(np0,np1,f);
this->e0.f->FFp(this->e0.z)= this->e0.f;
this->e0.f->FFi(this->e0.z)=a1;
this->e1.f->FFp(this->e1.z)=this->e1.f;
this->e1.f->FFi(this->e1.z)=a2;
}
bool ret=TrivialEar<MESH>::Close(np0,np1,f);
if(ret) AdjacencyRing().push_back(f);
return ret;
}
};
}; // end class SelfIntersectionEar
// Funzione principale per chiudier un buco in maniera topologicamente corretta.
// Gestisce situazioni non manifold ragionevoli
// (tutte eccetto quelle piu' di 2 facce per 1 edge).
// Controlla che non si generino nuove situazioni non manifold chiudendo orecchie
// che sottendono un edge che gia'esiste.
// Funzione principale per chiudier un buco in maniera topologicamente corretta.
// Gestisce situazioni non manifold ragionevoli
// (tutte eccetto quelle piu' di 2 facce per 1 edge).
// Controlla che non si generino nuove situazioni non manifold chiudendo orecchie
// che sottendono un edge che gia'esiste.
template <class MESH>
class Hole
@ -500,16 +367,39 @@ public:
}
};
class EdgeToBeAvoided
{
VertexPointer v0,v1;
EdgeToBeAvoided(VertexPointer _v0, VertexPointer _v1):v0(_v0),v1(_v1)
{
if(v0>v1) swap(v0,v1);
}
bool operator < (const EdgeToBeAvoided &e)
{
if(this->v0!=e.v0) return this->v0<e.v0;
return this->v1<e.v1;
}
};
/// Main Single Hole Filling Function
/// Given a specific hole (identified by the Info h) it fills it
/// It also update a vector of face pointers
/// It uses an heap to choose the best ear to be closed
template<class EAR>
static void FillHoleEar(MESH &m, Info &h ,int UBIT, std::vector<FacePointer *> &app,std::vector<FaceType > *vf =0)
static void FillHoleEar(MESH &m, // The mesh to be filled
Info &h, // the particular hole to be filled
std::vector<FacePointer *> &facePointersToBeUpdated)
{
//Aggiungo le facce e aggiorno il puntatore alla faccia!
FaceIterator f = tri::Allocator<MESH>::AddFaces(m, h.size-2, app);
FaceIterator f = tri::Allocator<MESH>::AddFaces(m, h.size-2, facePointersToBeUpdated);
assert(h.p.f >= &*m.face.begin());
assert(h.p.f <= &m.face.back());
assert(h.p.IsBorder());//test fondamentale altrimenti qualcosa s'e' rotto!
std::vector< EAR > H;
H.reserve(h.size);
assert(h.p.IsBorder());
std::vector< EAR > EarHeap;
EarHeap.reserve(h.size);
int nmBit= VertexType::NewBitFlag(); // non manifoldness bit
//First loops around the hole to mark non manifold vertices.
@ -530,8 +420,8 @@ template<class EAR>
PosType fp = h.p;
do{
EAR app = EAR(fp);
H.push_back( app );
EAR appEar = EAR(fp);
EarHeap.push_back( appEar );
//printf("Adding ear %s ",app.Dump());
fp.NextB();
assert(fp.IsBorder());
@ -539,60 +429,56 @@ template<class EAR>
int cnt=h.size;
make_heap(H.begin(), H.end());
make_heap(EarHeap.begin(), EarHeap.end());
//finche' il buco non e' chiuso o non ci sono piu' orecchie da analizzare.
while( cnt > 2 && !H.empty() )
while( cnt > 2 && !EarHeap.empty() )
{
//printf("Front of the heap is %s", H.front().Dump());
pop_heap(H.begin(), H.end()); // retrieve the MAXIMUM value and put in the back;
PosType ep0,ep1;
EAR BestEar=H.back();
H.pop_back();
pop_heap(EarHeap.begin(), EarHeap.end()); // retrieve the MAXIMUM value and put in the back;
EAR BestEar=EarHeap.back();
EarHeap.pop_back();
if(BestEar.IsUpToDate() && !BestEar.IsDegen(nmBit))
{
if((*f).HasPolyInfo()) (*f).Alloc(3);
PosType ep0,ep1;
if(BestEar.Close(ep0,ep1,&*f))
{
if(!ep0.IsNull()){
H.push_back(EAR(ep0));
push_heap( H.begin(), H.end());
EarHeap.push_back(EAR(ep0));
push_heap( EarHeap.begin(), EarHeap.end());
}
if(!ep1.IsNull()){
H.push_back(EAR(ep1));
push_heap( H.begin(), H.end());
EarHeap.push_back(EAR(ep1));
push_heap( EarHeap.begin(), EarHeap.end());
}
--cnt;
f->SetUserBit(UBIT);
if(vf != 0) (*vf).push_back(*f);
++f;
}
}//is update()
}//fine del while principale.
//tolgo le facce non utilizzate.
while(f!=m.face.end())
{
(*f).SetD();
++f;
m.fn--;
while(f!=m.face.end()){
tri::Allocator<MESH>::DeleteFace(m,*f);
f++;
}
VertexType::DeleteBitFlag(nmBit); // non manifoldness bit
}
template<class EAR>
static int EarCuttingFill(MESH &m, int sizeHole, const int UBIT, bool Selected = false, CallBackPos *cb=0)
static int EarCuttingFill(MESH &m, int sizeHole, bool Selected = false, CallBackPos *cb=0)
{
std::vector< Info > vinfo;
// int UBIT = GetInfo(m, Selected,vinfo);
GetInfo(m, Selected,vinfo);
typename std::vector<Info >::iterator ith;
//Info app;
int indCb=0;
int holeCnt=0;
std::vector<FacePointer *> vfp;
std::vector<FacePointer *> facePtrToBeUpdated;
for(ith = vinfo.begin(); ith!= vinfo.end(); ++ith)
vfp.push_back( &(*ith).p.f );
facePtrToBeUpdated.push_back( &(*ith).p.f );
for(ith = vinfo.begin(); ith!= vinfo.end(); ++ith)
{
@ -600,30 +486,22 @@ template<class EAR>
if(cb) (*cb)(indCb*10/vinfo.size(),"Closing Holes");
if((*ith).size < sizeHole){
holeCnt++;
FillHoleEar< EAR >(m, *ith,UBIT,vfp);
FillHoleEar< EAR >(m, *ith,facePtrToBeUpdated);
}
}
FaceIterator fi;
for(fi = m.face.begin(); fi!=m.face.end(); ++fi)
{
if(!(*fi).IsD())
(*fi).ClearUserBit(UBIT);
}
return holeCnt;
}
// it returns the number of created holes.
/// Main Hole Filling function.
/// Given a mesh search for all the holes smaller than a given size and fill them
/// It returns the number of filled holes.
template<class EAR>
static int EarCuttingIntersectionFill(MESH &m, int sizeHole, const int UBIT, CallBackPos *cb=0)
static int EarCuttingIntersectionFill(MESH &m, const int maxSizeHole, bool Selected, CallBackPos *cb=0)
{
std::vector<Info > vinfo;
// int UBIT = GetInfo(m, Selected,vinfo);
std::vector<FaceType > vf;
PosType sp;
PosType ap;
typename std::vector<Info >::iterator ith;
GetInfo(m, Selected,vinfo);
typename std::vector<Info>::iterator ith;
// collect the face pointer that has to be updated by the various addfaces
std::vector<FacePointer *> vfpOrig;
@ -636,12 +514,12 @@ template<class EAR>
{
indCb++;
if(cb) (*cb)(indCb*10/vinfo.size(),"Closing Holes");
if((*ith).size < sizeHole){
std::vector<FacePointer *> vfp;
if((*ith).size < maxSizeHole){
std::vector<FacePointer *> facePtrToBeUpdated;
holeCnt++;
vfp=vfpOrig;
facePtrToBeUpdated=vfpOrig;
EAR::AdjacencyRing().clear();
//Loops around the hole to collect the races .
//Loops around the hole to collect the faces that have to be tested for intersection.
PosType ip = (*ith).p;
do
{
@ -657,25 +535,20 @@ template<class EAR>
typename std::vector<FacePointer>::iterator fpi;
for(fpi=EAR::AdjacencyRing().begin();fpi!=EAR::AdjacencyRing().end();++fpi)
vfp.push_back( &*fpi );
facePtrToBeUpdated.push_back( &*fpi );
FillHoleEar<EAR >(m, *ith,UBIT,vfp,&vf);
FillHoleEar<EAR >(m, *ith,facePtrToBeUpdated);
EAR::AdjacencyRing().clear();
}
}
FaceIterator fi;
for(fi = m.face.begin(); fi!=m.face.end(); ++fi)
{
if(!(*fi).IsD())
(*fi).ClearUserBit(UBIT);
}
return holeCnt;
}
static void GetInfo(MESH &m, const int UBIT, bool Selected ,std::vector<Info >& VHI)
static void GetInfo(MESH &m, bool Selected ,std::vector<Info >& VHI)
{
tri::UpdateFlags<MESH>::FaceClearV(m);
for(FaceIterator fi = m.face.begin(); fi!=m.face.end(); ++fi)
{
if(!(*fi).IsD())
@ -684,15 +557,15 @@ template<class EAR>
{
//se devo considerare solo i triangoli selezionati e
//quello che sto considerando non lo e' lo marchio e vado avanti
(*fi).SetUserBit(UBIT);
(*fi).SetV();
}
else
{
for(int j =0; j<3 ; ++j)
{
if( face::IsBorder(*fi,j) && !(*fi).IsUserBit(UBIT) )
if( face::IsBorder(*fi,j) && !(*fi).IsV() )
{//Trovato una faccia di bordo non ancora visitata.
(*fi).SetUserBit(UBIT);
(*fi).SetV();
PosType sp(&*fi, j, (*fi).V(j));
PosType fp=sp;
int holesize=0;
@ -700,14 +573,14 @@ template<class EAR>
Box3Type hbox;
hbox.Add(sp.v->cP());
//printf("Looping %i : (face %i edge %i) \n", VHI.size(),sp.f-&*m.face.begin(),sp.z);
sp.f->SetUserBit(UBIT);
sp.f->SetV();
do
{
sp.f->SetUserBit(UBIT);
sp.f->SetV();
hbox.Add(sp.v->cP());
++holesize;
sp.NextB();
sp.f->SetUserBit(UBIT);
sp.f->SetV();
assert(sp.IsBorder());
}while(sp != fp);
@ -915,15 +788,14 @@ template<class EAR>
triangulate(m,f,k,j,vi,vv);
}
static void MinimumWeightFill(MESH &m, const int UBIT, int holeSize, bool Selected)
static void MinimumWeightFill(MESH &m, int holeSize, bool Selected)
{
FaceIterator fi;
std::vector<PosType > vvi;
std::vector<FacePointer * > vfp;
std::vector<Info > vinfo;
typename std::vector<Info >::iterator VIT;
GetInfo(m, UBIT, Selected,vinfo);
GetInfo(m, Selected,vinfo);
for(VIT = vinfo.begin(); VIT != vinfo.end();++VIT)
{
@ -983,6 +855,6 @@ template<class EAR>
};//close class Hole
} // end namespace
}
} // end namespace tri
} // end namespace vcg
#endif