first working implementationof "EAR HOLE FILLING".
This commit is contained in:
parent
d878081824
commit
2daa4cdd9b
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue