first working implementationof "EAR HOLE FILLING".
This commit is contained in:
parent
d878081824
commit
2daa4cdd9b
|
@ -21,9 +21,12 @@
|
||||||
* *
|
* *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
History
|
History
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
$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
|
Revision 1.3 2006/09/27 15:33:32 giec
|
||||||
It close one simple hole . . .
|
It close one simple hole . . .
|
||||||
|
|
||||||
|
@ -43,11 +46,11 @@ Questa Classe serve per gestire la non duplicazione degli edge durante la chiusu
|
||||||
di un buco.
|
di un buco.
|
||||||
*/
|
*/
|
||||||
namespace vcg {
|
namespace vcg {
|
||||||
namespace tri {
|
namespace tri {
|
||||||
|
|
||||||
template<class MESH>
|
template<class MESH>
|
||||||
class SimpleEdge
|
class SimpleEdge
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typename MESH::VertexType v[2];
|
typename MESH::VertexType v[2];
|
||||||
SimpleEdge()
|
SimpleEdge()
|
||||||
|
@ -88,12 +91,12 @@ class SimpleEdge
|
||||||
else return false;
|
else return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class MESH>
|
template<class MESH>
|
||||||
class HoleInfo
|
class HoleInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HoleInfo(){}
|
HoleInfo(){}
|
||||||
HoleInfo(face::Pos<typename MESH::FaceType> const &pHole, int const pHoleSize, vcg::Box3<typename MESH::ScalarType> &pHoleBB)
|
HoleInfo(face::Pos<typename MESH::FaceType> const &pHole, int const pHoleSize, vcg::Box3<typename MESH::ScalarType> &pHoleBB)
|
||||||
{
|
{
|
||||||
|
@ -101,9 +104,25 @@ public:
|
||||||
size=pHoleSize;
|
size=pHoleSize;
|
||||||
bb=pHoleBB;
|
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;
|
typename face::Pos<typename MESH::FaceType> p;
|
||||||
int size;
|
int size;
|
||||||
vcg::Box3<typename MESH::ScalarType> bb;
|
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;}
|
||||||
bool operator > (const HoleInfo & hh) const {return size > hh.size;}
|
bool operator > (const HoleInfo & hh) const {return size > hh.size;}
|
||||||
|
@ -112,7 +131,7 @@ public:
|
||||||
bool operator >= (const HoleInfo & hh) const {return size >= hh.size;}
|
bool operator >= (const HoleInfo & hh) const {return size >= hh.size;}
|
||||||
bool operator <= (const HoleInfo & hh) const {return size <= hh.size;}
|
bool operator <= (const HoleInfo & hh) const {return size <= hh.size;}
|
||||||
|
|
||||||
typename MESH::ScalarType Perimeter()
|
typename MESH::ScalarType Perimeter()
|
||||||
{
|
{
|
||||||
MESH::ScalarType sum=0;
|
MESH::ScalarType sum=0;
|
||||||
face::Pos<typename MESH::FaceType> ip = p;
|
face::Pos<typename MESH::FaceType> ip = p;
|
||||||
|
@ -158,11 +177,11 @@ typename MESH::ScalarType Perimeter()
|
||||||
|
|
||||||
return EV.size();
|
return EV.size();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class MESH>
|
template<class MESH>
|
||||||
void FindHole(MESH &m, face::Pos<typename MESH::FaceType> ep, HoleInfo<MESH> &h)
|
void FindHole(MESH &m, face::Pos<typename MESH::FaceType> ep, HoleInfo<MESH> &h)
|
||||||
{
|
{
|
||||||
if(!ep.IsBorder()) return;
|
if(!ep.IsBorder()) return;
|
||||||
|
|
||||||
int holesize = 0;
|
int holesize = 0;
|
||||||
|
@ -180,11 +199,11 @@ void FindHole(MESH &m, face::Pos<typename MESH::FaceType> ep, HoleInfo<MESH> &h)
|
||||||
}
|
}
|
||||||
while (ep != init);
|
while (ep != init);
|
||||||
h=HoleInfo<MESH>(ep,holesize,hbox);
|
h=HoleInfo<MESH>(ep,holesize,hbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class MESH,class STL_CONTAINER_HOLES>
|
template<class MESH,class STL_CONTAINER_HOLES>
|
||||||
void FindHole(MESH &m, STL_CONTAINER_HOLES & H)
|
void FindHole(MESH &m, STL_CONTAINER_HOLES & H)
|
||||||
{
|
{
|
||||||
MESH::FaceIterator pf;
|
MESH::FaceIterator pf;
|
||||||
int holesize;
|
int holesize;
|
||||||
for (pf=m.face.begin(); pf!=m.face.end(); ++pf)
|
for (pf=m.face.begin(); pf!=m.face.end(); ++pf)
|
||||||
|
@ -220,11 +239,11 @@ void FindHole(MESH &m, STL_CONTAINER_HOLES & H)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Un ear e' identificato da due hedge pos.
|
Un ear e' identificato da due hedge pos.
|
||||||
|
|
||||||
i vertici dell'ear sono
|
i vertici dell'ear sono
|
||||||
e0.FlipV().v
|
e0.FlipV().v
|
||||||
|
@ -234,22 +253,22 @@ Un ear e' identificato da due hedge pos.
|
||||||
Vale che e1== e0.NextB();
|
Vale che e1== e0.NextB();
|
||||||
e che e1.FlipV() == e0;
|
e che e1.FlipV() == e0;
|
||||||
|
|
||||||
Situazioni ear non manifold, e degeneri (buco triangolare)
|
Situazioni ear non manifold, e degeneri (buco triangolare)
|
||||||
|
|
||||||
|
|
||||||
T XXXXXXXXXXXXX A /XXXXX B en/XXXXX
|
T XXXXXXXXXXXXX A /XXXXX B en/XXXXX
|
||||||
/XXXXXXXXXXXXXXX /XXXXXX /XXXXXX
|
/XXXXXXXXXXXXXXX /XXXXXX /XXXXXX
|
||||||
XXXXXXep==en XXX ep\ /en XXXX /e1 XXXX
|
XXXXXXep==en XXX ep\ /en XXXX /e1 XXXX
|
||||||
XXXXXX ----/| XX ------ ----/| XX ------ ----/|XXX
|
XXXXXX ----/| XX ------ ----/| XX ------ ----/|XXX
|
||||||
XXXXXX| /e1 XX XXXXXX| /e1 XX XXXXXX| o/e0 XX
|
XXXXXX| /e1 XX XXXXXX| /e1 XX XXXXXX| o/e0 XX
|
||||||
XXXXXX| /XXXXXX XXXXXX| /XXXXXX XXXXXX| /XXXXXX
|
XXXXXX| /XXXXXX XXXXXX| /XXXXXX XXXXXX| /XXXXXX
|
||||||
XXX e0|o/XXXXXXX XXX e0|o/XXXXXXX XXX ep| /XXXXXXX
|
XXX e0|o/XXXXXXX XXX e0|o/XXXXXXX XXX ep| /XXXXXXX
|
||||||
XXX \|/XXXXXXXX XXX \|/XXXXXXXX XXX \|/XXXXXXXX
|
XXX \|/XXXXXXXX XXX \|/XXXXXXXX XXX \|/XXXXXXXX
|
||||||
XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
|
XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
|
||||||
|
|
||||||
*/
|
*/
|
||||||
template<class MSH_TYPE> class TrivialEar
|
template<class MSH_TYPE> class TrivialEar
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
face::Pos<typename MSH_TYPE::FaceType> e0; //
|
face::Pos<typename MSH_TYPE::FaceType> e0; //
|
||||||
face::Pos<typename MSH_TYPE::FaceType> e1; //
|
face::Pos<typename MSH_TYPE::FaceType> e1; //
|
||||||
|
@ -315,7 +334,7 @@ template<class MSH_TYPE> class TrivialEar
|
||||||
face::Pos<typename MSH_TYPE::FaceType> en=e1; en.NextB(); // he successivo a e1
|
face::Pos<typename MSH_TYPE::FaceType> en=e1; en.NextB(); // he successivo a e1
|
||||||
|
|
||||||
// caso ear degenere per buco triangolare
|
// 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
|
// Caso ear non manifold a
|
||||||
if(ep.v==en.v) return true;
|
if(ep.v==en.v) return true;
|
||||||
// Caso ear non manifold b
|
// Caso ear non manifold b
|
||||||
|
@ -403,89 +422,111 @@ template<class MSH_TYPE> class TrivialEar
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Funzione principale per chiudier un buco in maniera topologicamente corretta.
|
// Funzione principale per chiudier un buco in maniera topologicamente corretta.
|
||||||
// Gestisce situazioni non manifold ragionevoli
|
// Gestisce situazioni non manifold ragionevoli
|
||||||
// (tutte eccetto quelle piu' di 2 facce per 1 edge).
|
// (tutte eccetto quelle piu' di 2 facce per 1 edge).
|
||||||
// Controlla che non si generino nuove situazioni non manifold chiudendo orecchie
|
// Controlla che non si generino nuove situazioni non manifold chiudendo orecchie
|
||||||
// che sottendono un edge che gia'esiste.
|
// che sottendono un edge che gia'esiste.
|
||||||
//
|
template<class MESH>
|
||||||
// Attenzione: se per riaggiungere facce deve riallocare il vettore non funge!!!!
|
tri::HoleInfo<MESH> getHoleInfo(MESH &m, face::Pos<typename MESH::FaceType> sp,
|
||||||
//
|
face::Pos<typename MESH::FaceType> fp,
|
||||||
template<class MESH, class EAR>
|
int UBIT)
|
||||||
typename MESH::FaceIterator CloseHole(MESH &m, HoleInfo <MESH> &h)
|
{
|
||||||
{
|
int holesize=0;
|
||||||
|
|
||||||
std::vector<SimpleEdge<MESH> > ES;
|
Box3<MESH::ScalarType> hbox;
|
||||||
//set<SimpleEdge<MESH> > ES; // vettore con tutti gli edge adiacenti al buco.
|
hbox.Add(sp.v->cP());
|
||||||
|
|
||||||
h.CollectEdges(ES);
|
do
|
||||||
vector<EAR> H; // Heap delle ear da chiudere
|
{
|
||||||
H.reserve(h.size);
|
sp.f->SetUserBit(UBIT);
|
||||||
|
hbox.Add(sp.v->cP());
|
||||||
|
++holesize;
|
||||||
|
sp.NextB();
|
||||||
|
assert(sp.IsBorder());
|
||||||
|
}while(sp != fp);
|
||||||
|
|
||||||
|
int tmp = ((int)(sp.f - &(*(m.face.begin()))));
|
||||||
|
return tri::HoleInfo<MESH>(sp,holesize,hbox, tmp );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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{
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
std::vector<MESH::FacePointer *> app;
|
||||||
app.push_back( &h.p.f );
|
app.push_back( &h.p.f );
|
||||||
MESH::FaceIterator f = tri::Allocator<MESH>::AddFaces(m, h.size-2, app);
|
|
||||||
h.CollectEdges(ES);
|
|
||||||
|
|
||||||
assert(h.p.IsBorder());
|
assert(h.p.IsBorder());
|
||||||
|
MESH::FaceIterator f = tri::Allocator<MESH>::AddFaces(m, h.size-2, app);
|
||||||
|
|
||||||
face::Pos<typename MESH::FaceType> ep=h.p;
|
h.Refresh(m); //rinfresco il puntatore tramite l'indice precedentemente salvato.
|
||||||
|
|
||||||
do {
|
assert(h.p.IsBorder());//test fondamentale altrimenti qualcosa s'e' rotto!
|
||||||
H.push_back(EAR(ep));
|
|
||||||
ep.f->SetS();
|
|
||||||
ep.NextB();
|
|
||||||
|
|
||||||
assert(ep.IsBorder());
|
std::vector<MESH::VertexType > vv; //vettore di vertici
|
||||||
} while(ep!=h.p);
|
|
||||||
|
|
||||||
|
std::vector<EAR > H; //vettore di orecchie
|
||||||
|
|
||||||
make_heap(H.begin(),H.end());
|
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;
|
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;
|
EAR en0,en1;
|
||||||
|
|
||||||
MESH::FaceIterator firstf = f;
|
MESH::VertexType vfit = *H.back().e0.v;
|
||||||
|
std::vector<MESH::VertexType >::iterator it;
|
||||||
//SimpleEdge<MESH> se();
|
it = vv.begin();
|
||||||
while(cnt > 2 && !H.empty())
|
while( it != vv.end() && (vfit.P() != ((MESH::VertexType )(*it)).P() ) )
|
||||||
{
|
|
||||||
//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)) )
|
|
||||||
{it++; }
|
{it++; }
|
||||||
//per far funzionare il test sottostante.
|
|
||||||
|
MESH::FaceIterator Fadd = f;
|
||||||
|
|
||||||
if(H.back().IsUpToDate())
|
if(H.back().IsUpToDate())
|
||||||
{
|
{
|
||||||
|
if(H.back().Degen() && it != vv.end()){
|
||||||
if(H.back().Degen() && it != ES.end()){
|
|
||||||
// Nota che nel caso di ear degeneri si DEVE permettere la creazione di un edge che gia'esiste
|
// Nota che nel caso di ear degeneri si DEVE permettere la creazione di un edge che gia'esiste
|
||||||
printf("\n -> Evitata orecchia brutta!");
|
printf("\n -> Evitata orecchia brutta!");
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if(it == ES.end())
|
|
||||||
{
|
|
||||||
//H.back().Close(en0,en1,&*f);
|
|
||||||
int i = H.size();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
if(H.back().Close(en0,en1,&*f))
|
if(H.back().Close(en0,en1,&*f))
|
||||||
{
|
{
|
||||||
//ES.insert(se);
|
//ES.insert(se);
|
||||||
ES.push_back(se);
|
/* ES.push_back(se);
|
||||||
if(!en0.IsNull()){
|
if(!en0.IsNull()){
|
||||||
H.push_back(en0);
|
H.push_back(en0);
|
||||||
push_heap( H.begin(), H.end());
|
push_heap( H.begin(), H.end());
|
||||||
|
@ -493,51 +534,115 @@ typename MESH::FaceIterator CloseHole(MESH &m, HoleInfo <MESH> &h)
|
||||||
if(!en1.IsNull()){
|
if(!en1.IsNull()){
|
||||||
H.push_back(en1);
|
H.push_back(en1);
|
||||||
push_heap( H.begin(), H.end());
|
push_heap( H.begin(), H.end());
|
||||||
}
|
}*/
|
||||||
--cnt;
|
--cnt;
|
||||||
|
tmp = f;
|
||||||
++f;
|
++f;
|
||||||
|
fitted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if((cnt == 3) && ( H.back().e0.IsBorder() ) )
|
if(cnt == 3 && !fitted)
|
||||||
{
|
{//ultimo buco o unico buco
|
||||||
//dovrebbe mancare un triangolo da tappare
|
|
||||||
if(H.back().Close(en0,en1,&*f))
|
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;
|
--cnt;
|
||||||
|
tmp = f;
|
||||||
++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();
|
H.pop_back();
|
||||||
}
|
}
|
||||||
|
}//fine del while principale
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Delete the unused faces (caused by non 1-manifold vertexes)
|
|
||||||
while(f!=m.face.end())
|
while(f!=m.face.end())
|
||||||
{
|
{
|
||||||
(*f).SetD();
|
(*f).SetD();
|
||||||
++f;
|
++f;
|
||||||
m.fn--;
|
m.fn--;
|
||||||
}
|
}
|
||||||
return firstf;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
}
|
||||||
Trivial Ear con preferred Normal
|
|
||||||
*/
|
|
||||||
template<class MSH_TYPE> class TrivialEarN : public TrivialEar<MSH_TYPE>
|
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
|
||||||
|
*/
|
||||||
|
template<class MSH_TYPE> class TrivialEarN : public TrivialEar<MSH_TYPE>
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TrivialEarN(){}
|
TrivialEarN(){}
|
||||||
|
@ -565,14 +670,14 @@ template<class MSH_TYPE> class TrivialEarN : public TrivialEar<MSH_TYPE>
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 2d Triangulation Code */
|
/* 2d Triangulation Code */
|
||||||
class Triangulate2D
|
class Triangulate2D
|
||||||
{
|
{
|
||||||
|
|
||||||
static double Area(const vector<Point2d> &contour)
|
static double Area(const vector<Point2d> &contour)
|
||||||
{
|
{
|
||||||
int n = contour.size();
|
int n = contour.size();
|
||||||
|
|
||||||
double A=0.0f;
|
double A=0.0f;
|
||||||
|
@ -581,18 +686,18 @@ static double Area(const vector<Point2d> &contour)
|
||||||
A+= contour[p].X()*contour[q].Y() - contour[q].X()*contour[p].Y();
|
A+= contour[p].X()*contour[q].Y() - contour[q].X()*contour[p].Y();
|
||||||
}
|
}
|
||||||
return A*0.5f;
|
return A*0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
InsideTriangle decides if a point P is Inside of the triangle
|
InsideTriangle decides if a point P is Inside of the triangle
|
||||||
defined by A, B, C.
|
defined by A, B, C.
|
||||||
*/
|
*/
|
||||||
static bool InsideTriangle(double Ax, double Ay,
|
static bool InsideTriangle(double Ax, double Ay,
|
||||||
double Bx, double By,
|
double Bx, double By,
|
||||||
double Cx, double Cy,
|
double Cx, double Cy,
|
||||||
double Px, double Py)
|
double Px, double Py)
|
||||||
|
|
||||||
{
|
{
|
||||||
double ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
|
double ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
|
||||||
double cCROSSap, bCROSScp, aCROSSbp;
|
double cCROSSap, bCROSScp, aCROSSbp;
|
||||||
|
|
||||||
|
@ -608,10 +713,10 @@ static bool InsideTriangle(double Ax, double Ay,
|
||||||
bCROSScp = bx*cpy - by*cpx;
|
bCROSScp = bx*cpy - by*cpx;
|
||||||
|
|
||||||
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
|
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool Snip(const vector<Point2d> &contour,int u,int v,int w,int n,int *V)
|
static bool Snip(const vector<Point2d> &contour,int u,int v,int w,int n,int *V)
|
||||||
{
|
{
|
||||||
int p;
|
int p;
|
||||||
double Ax, Ay, Bx, By, Cx, Cy, Px, Py;
|
double Ax, Ay, Bx, By, Cx, Cy, Px, Py;
|
||||||
const double epsilon =1e-2;
|
const double epsilon =1e-2;
|
||||||
|
@ -636,10 +741,10 @@ static bool Snip(const vector<Point2d> &contour,int u,int v,int w,int n,int *V)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
static bool Process(const vector<Point2d> &contour,vector<int> &result)
|
static bool Process(const vector<Point2d> &contour,vector<int> &result)
|
||||||
{
|
{
|
||||||
/* allocate and initialize list of Vertices in polygon */
|
/* allocate and initialize list of Vertices in polygon */
|
||||||
|
|
||||||
int n = contour.size();
|
int n = contour.size();
|
||||||
|
@ -709,9 +814,9 @@ static bool Process(const vector<Point2d> &contour,vector<int> &result)
|
||||||
delete V;
|
delete V;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
} // end namespace
|
} // end namespace
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue