first working implementationof "EAR HOLE FILLING".

This commit is contained in:
Paolo Cignoni 2006-10-06 15:28:14 +00:00
parent d878081824
commit 2daa4cdd9b
1 changed files with 685 additions and 580 deletions

View File

@ -24,6 +24,9 @@
History
$Log: not supported by cvs2svn $
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 . . .
@ -101,9 +104,25 @@ public:
size=pHoleSize;
bb=pHoleBB;
}
HoleInfo(face::Pos<typename MESH::FaceType> const &pHole, int const pHoleSize, vcg::Box3<typename MESH::ScalarType> &pHoleBB, int FI)
{
p=pHole;
size=pHoleSize;
bb=pHoleBB;
faceindex = FI;
}
typename face::Pos<typename MESH::FaceType> p;
int size;
vcg::Box3<typename MESH::ScalarType> bb;
int faceindex;
void Refresh(MESH &m)
{
p.f = (MESH::FacePointer)(faceindex + &(*(m.face.begin())));
}
bool operator < (const HoleInfo & hh) const {return size < hh.size;}
bool operator > (const HoleInfo & hh) const {return size > hh.size;}
@ -315,7 +334,7 @@ template<class MSH_TYPE> class TrivialEar
face::Pos<typename MSH_TYPE::FaceType> en=e1; en.NextB(); // he successivo a e1
// caso ear degenere per buco triangolare
if(ep==en) return true;
if(ep==en) return true;//provo a togliere sto controllo
// Caso ear non manifold a
if(ep.v==en.v) return true;
// Caso ear non manifold b
@ -413,79 +432,101 @@ template<class MSH_TYPE> class TrivialEar
// (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.
//
// Attenzione: se per riaggiungere facce deve riallocare il vettore non funge!!!!
//
template<class MESH, class EAR>
typename MESH::FaceIterator CloseHole(MESH &m, HoleInfo <MESH> &h)
template<class MESH>
tri::HoleInfo<MESH> getHoleInfo(MESH &m, face::Pos<typename MESH::FaceType> sp,
face::Pos<typename MESH::FaceType> fp,
int UBIT)
{
int holesize=0;
std::vector<SimpleEdge<MESH> > ES;
//set<SimpleEdge<MESH> > ES; // vettore con tutti gli edge adiacenti al buco.
Box3<MESH::ScalarType> hbox;
hbox.Add(sp.v->cP());
h.CollectEdges(ES);
vector<EAR> H; // Heap delle ear da chiudere
H.reserve(h.size);
std::vector<MESH::FacePointer *> app;
app.push_back( &h.p.f );
MESH::FaceIterator f = tri::Allocator<MESH>::AddFaces(m, h.size-2, app);
h.CollectEdges(ES);
do
{
sp.f->SetUserBit(UBIT);
hbox.Add(sp.v->cP());
++holesize;
sp.NextB();
assert(sp.IsBorder());
}while(sp != fp);
assert(h.p.IsBorder());
int tmp = ((int)(sp.f - &(*(m.face.begin()))));
return tri::HoleInfo<MESH>(sp,holesize,hbox, tmp );
}
face::Pos<typename MESH::FaceType> ep=h.p;
template<class MESH,class EAR , class VECTOR_EAR>
void refreshHole(MESH &m, VECTOR_EAR &ve, face::Pos<typename MESH::FaceType> &fp, std::vector<typename MESH::VertexType > &vv)
{
face::Pos<typename MESH::FaceType> ff = fp;
do{
H.push_back(EAR(ep));
ep.f->SetS();
ep.NextB();
ve.push_back(EAR(fp));
vv.push_back(*fp.v);
fp.NextB();//semmai da provare a sostituire il codice della NextB();
assert(fp.IsBorder());
}while(fp!=ff);
assert(ep.IsBorder());
} while(ep!=h.p);
}
make_heap(H.begin(),H.end());
template <class MESH, class EAR>
void fillHoleEar(MESH &m, tri::HoleInfo<MESH> &h ,int UBIT)
{
//Aggiungo le facce e aggiorno il puntatore alla faccia!
std::vector<MESH::FacePointer *> app;
app.push_back( &h.p.f );
assert(h.p.IsBorder());
MESH::FaceIterator f = tri::Allocator<MESH>::AddFaces(m, h.size-2, app);
h.Refresh(m); //rinfresco il puntatore tramite l'indice precedentemente salvato.
assert(h.p.IsBorder());//test fondamentale altrimenti qualcosa s'e' rotto!
std::vector<MESH::VertexType > vv; //vettore di vertici
std::vector<EAR > H; //vettore di orecchie
H.reserve(h.size);
//prendo le informazioni sul buco
refreshHole<MESH,EAR, std::vector<EAR> >(m,H,h.p,vv);
bool fitted = false;
int cnt=h.size;
MESH::FaceIterator tmp;
while( cnt > 2 && !H.empty() ) //finche' il buco non e' chiuso o non ci sono piu' orecchie da analizzare
{
//ordino il vettore di orecchie
//sort(H.begin(), H.end(), greater<EAR>() );//descending
sort(H.begin(), H.end(), less<EAR>() ); //ascending
EAR en0,en1;
MESH::FaceIterator firstf = f;
//SimpleEdge<MESH> se();
while(cnt > 2 && !H.empty())
{
//pop_heap(H.begin(),H.end());
SimpleEdge<MESH> se( *(H.back().e0.VFlip()) , *(H.back().e1.v));
// se.v = p.v;
// se.v[1] = p.v[1];
//Sostituito la funzione find con la ricerca manuale
std::vector<SimpleEdge<MESH> >::iterator it;
it = ES.begin();
while( it != ES.end() &&
se != ((SimpleEdge<MESH> )(*it)) )
MESH::VertexType vfit = *H.back().e0.v;
std::vector<MESH::VertexType >::iterator it;
it = vv.begin();
while( it != vv.end() && (vfit.P() != ((MESH::VertexType )(*it)).P() ) )
{it++; }
//per far funzionare il test sottostante.
MESH::FaceIterator Fadd = f;
if(H.back().IsUpToDate())
{
if(H.back().Degen() && it != ES.end()){
if(H.back().Degen() && it != vv.end()){
// Nota che nel caso di ear degeneri si DEVE permettere la creazione di un edge che gia'esiste
printf("\n -> Evitata orecchia brutta!");
}
else {
if(it == ES.end())
{
//H.back().Close(en0,en1,&*f);
int i = H.size();
}
else
{
if(H.back().Close(en0,en1,&*f))
{
//ES.insert(se);
ES.push_back(se);
/* ES.push_back(se);
if(!en0.IsNull()){
H.push_back(en0);
push_heap( H.begin(), H.end());
@ -493,45 +534,109 @@ typename MESH::FaceIterator CloseHole(MESH &m, HoleInfo <MESH> &h)
if(!en1.IsNull()){
H.push_back(en1);
push_heap( H.begin(), H.end());
}
}*/
--cnt;
tmp = f;
++f;
fitted = true;
}
}
}
if((cnt == 3) && ( H.back().e0.IsBorder() ) )
{
//dovrebbe mancare un triangolo da tappare
if(cnt == 3 && !fitted)
{//ultimo buco o unico buco
if(H.back().Close(en0,en1,&*f))
{
ES.push_back(se);
if(!en0.IsNull()){
H.push_back(en0);
push_heap( H.begin(), H.end());
}
if(!en1.IsNull()){
H.push_back(en1);
push_heap( H.begin(), H.end());
}
--cnt;
tmp = f;
++f;
fitted = true;
}
}
if(fitted && cnt >2)
{
face::Pos<typename MESH::FaceType> ff( &(*tmp) ,2);
//ho inserito il triangolo e devo aggiornare le strutture dati
H.clear();
vv.clear();
tmp->SetUserBit(UBIT);
//ri-prendo le informazioni sul buco
refreshHole<MESH,EAR, std::vector<EAR> >(m,H,ff,vv);
fitted = false;
}
else
{
//non ho messo il triangolo quindi tolgo l'orecchio e continuo
H.pop_back();
}
}//fine del while principale
//Delete the unused faces (caused by non 1-manifold vertexes)
while(f!=m.face.end())
{
(*f).SetD();
++f;
m.fn--;
}
return firstf;
};
}
template<class MESH>
void holeFillingEar(MESH &m, int sizeHole,bool Selected = false)
{
MESH::FaceIterator fi;
std::vector<tri::HoleInfo<MESH> > vinfo;
int UBIT = fi->LastBitFlag();
for(fi = m.face.begin(); fi!=m.face.end(); ++fi)
{
if(!(*fi).IsD())
{
if(Selected && !(*fi).IsS())
{
//se devo considerare solo i triangoli selezionati e
//quello che sto considerando non lo e' lo marchio e vado avanti
(*fi).SetUserBit(UBIT);
}
else
{
if( !(*fi).IsUserBit(UBIT) )
{
(*fi).SetUserBit(UBIT);
for(int j =0; j<3 ; ++j)
{
if( (*fi).IsB(j) )
{//Trovato una faccia di bordo non ancora visitata.
face::Pos<typename MESH::FaceType> sp(&*fi, j, (*fi).V(j));
// if(!(*fi).IsR())return;
tri::HoleInfo<MESH> HI = getHoleInfo<MESH>(m,sp,sp, UBIT);
//ho recuperato l'inofrmazione su tutto il buco
vinfo.push_back(HI);
}
}//for sugli edge del triangolo
}//se e' gia stato visitato
}//S & !S
}//!IsD()
}//for principale!!!
std::vector<tri::HoleInfo<MESH> >::iterator ith;
tri::HoleInfo<MESH> app;
for(ith = vinfo.begin(); ith!= vinfo.end(); ++ith)
{
app=(tri::HoleInfo<MESH>)*ith;
if(app.size < sizeHole){
//app.Refresh(m);//non so se serve
fillHoleEar<MESH, typename tri::TrivialEar<MESH> >(m, app,UBIT);
}
}
for(fi = m.face.begin(); fi!=m.face.end(); ++fi)
{
if(!(*fi).IsD())
(*fi).ClearUserBit(UBIT);
}
}
/*
Trivial Ear con preferred Normal