made it as a static class

This commit is contained in:
ganovelli 2004-07-09 10:24:06 +00:00
parent 44daf54e0f
commit cd84a47864
1 changed files with 228 additions and 206 deletions

View File

@ -79,136 +79,7 @@ class EdgeCollapse
}; };
private: private:
vector<TetraType*> To_Del;
Topology _Topo;
UpdateNormals _UN;
//typedef pair <VertexType*,VertexType*> VertPair;
typedef pair <int,int> FacePair; typedef pair <int,int> FacePair;
///select the 2 faces that does not share the edge
FacePair _FindNoEdgeFace(TetraType *t,int edge)
{
//as first I find the 2 faces on the opposite sides of the egde
int fa0=Tetra::FofE(edge,0);
int fa1=Tetra::FofE(edge,1);
//then find the faces that remain
int fa2=(fa0+1)%4;
while ((fa2==fa0)||(fa2==fa1))
{
fa2=(fa2+1)%4;
}
int fa3=(fa2+1)%4;
while ((fa3==fa0)||(fa3==fa1)||(fa3==fa2))
{
fa3=(fa3+1)%4;
}
return FacePair(fa2,fa3);
}
#ifdef _DEBUG
void _AssertingVolume(TetraType *t)
{
assert(t->ComputeVolume() >0);
}
#endif
///collpse de edge specified by pos (the first vertex on edge remain)
void _Collapse(PosType p,CoordType NewP)
{
VertexType *Vrem=(p.T()->V(Tetra::VofE(p.E(),0)));
VertexType *Vdel=(p.T()->V(Tetra::VofE(p.E(),1)));
//Vrem->P()=(Vrem->P()*alfa)+(Vdel->P()*(1.f-alfa));
Vrem->P()=NewP;
PosLType pos(p.T(),p.F(),p.E(),p.V());
pos.Reset();
To_Del.reserve(40);
To_Del.clear();
while (!pos.LoopEnd())
{
//get the two faces that doesn't share the edge
FacePair fp=_FindNoEdgeFace(pos.T(),pos.E());
int fa0=fp.first;
int fa1=fp.second;
//now set the T-T topology on that faces
TetraType *tleft=pos.T()->TTp(fa0);
TetraType *tright=pos.T()->TTp(fa1);
int ileft=pos.T()->TTi(fa0);
int iright=pos.T()->TTi(fa1);
//in this case I cannot do the collapse
assert (!((pos.T()==tleft)&&(pos.T()==tright)));
//case no one is extern face
if ((!pos.T()->IsBorderF(fa0))&&(!pos.T()->IsBorderF(fa1)))
//connect the 2 tetrahedrons
_Topo._AttachTTTopology(tleft,ileft,tright,iright);
else
//case f2 is an extern face
if (pos.T()->IsBorderF(fa0))
{
tright->TTp(iright)=tright;
tright->TTi(iright)=iright;
}
else //case fa1 is an extern face
//if ((pos.T()->IsBorderF(fa3))
{
tleft->TTp(ileft)=tleft;
tleft->TTi(ileft)=ileft;
}
//end setting T-T topology
//setting the V-T topology
//i remove the tetrahedrons that have the edge
// to collapse
_Topo.DetachVTTopology(pos.T());
//end setting the V-T topology
To_Del.push_back(pos.T());
pos.NextT();
tm.tn--;
}
//delting old tetrahedrons
vector<TetraType*>::iterator ti;
for (ti=To_Del.begin();ti<To_Del.end();ti++)
(*ti)->SetD();
//now I cycle on the tetrahedron that had the old vertex
//reassegning the new one.
VTIterator< TetraType> VTi(Vdel->VTb(),Vdel->VTi());
while (!VTi.End())
{
TetraType *T_Change=VTi.Vt();
int index=VTi.Vi();
//VTi++;
//assegning the vertex that remain
T_Change->V(index)=Vrem;
_Topo.DetachVTTopology(Vdel,T_Change);
_Topo.InsertVTTopology(Vrem,index,T_Change);
//that's cause i restart everytime in the chain
//from the vertex
VTi.Vt()=Vdel->VTb();
VTi.Vi()=Vdel->VTi();
#ifdef _DEBUG
_AssertingVolume(T_Change);
#endif
}
if (Vdel->IsB())
Vrem->SetB();
//set as deleted the vertex
Vdel->SetD();
tm.vn--;
}
struct Face struct Face
{ {
VertexType* v[3]; VertexType* v[3];
@ -253,51 +124,6 @@ struct Edge{
} }
}; };
map<Edge,char> EdgeMark;
map<Face,char> FaceMark;
VertexType _dummyV;
void orMarkE(Edge E,char M)
{
map<Edge,char>::iterator EI;
EI=EdgeMark.find(E);
if (EI==EdgeMark.end())
EdgeMark.insert (pair<Edge,char>(E,M));
else
(*EI).second|=M;
}
bool isMarkedE(Edge E,char M)
{
map<Edge,char>::iterator EI;
EI=EdgeMark.find(E);
if (EI==EdgeMark.end())
return false;
else return ((*EI).second & M);
}
void orMarkF(Face F,char M)
{
map<Face,char>::iterator FI;
FI=FaceMark.find(F);
if (FI==FaceMark.end())
FaceMark.insert (pair<Face,char>(F,M));
else
(*FI).second|=M;
}
bool isMarkedF(Face F,char M)
{
map<Face,char>::iterator FI;
FI=FaceMark.find(F);
if (FI==FaceMark.end())
return false;
else return ((*FI).second & M);
}
///this structure is used to find the sets that are used in link conditions and more
struct TetraSets struct TetraSets
{ {
std::vector <TetraType*> v0; std::vector <TetraType*> v0;
@ -319,20 +145,211 @@ struct TetraSets
} }
}; };
TetraSets _Sets;
static map<Edge,char> & _EdgeMark(){
static map<Edge,char> em;
return em;
};
static map<Face,char> & _FaceMark(){
static map<Face,char> fm;
return fm;
}
static VertexType &_DummyV(){
static VertexType _dv;
return _dv;
}
static TetraSets &_Sets(){
static TetraSets _s;
return _s;
}
///select the 2 faces that does not share the edge
static FacePair _FindNoEdgeFace(TetraType *t,int edge)
{
//as first I find the 2 faces on the opposite sides of the egde
int fa0=Tetra::FofE(edge,0);
int fa1=Tetra::FofE(edge,1);
//then find the faces that remain
int fa2=(fa0+1)%4;
while ((fa2==fa0)||(fa2==fa1))
{
fa2=(fa2+1)%4;
}
int fa3=(fa2+1)%4;
while ((fa3==fa0)||(fa3==fa1)||(fa3==fa2))
{
fa3=(fa3+1)%4;
}
return FacePair(fa2,fa3);
}
#ifdef _DEBUG
static void _AssertingVolume(TetraType *t)
{
assert(t->ComputeVolume() >0);
}
#endif
///collpse de edge specified by pos (the first vertex on edge remain)
static int _Collapse(PosType p,CoordType NewP)
{
int n_deleted=0;
vector<TetraType*> To_Del;
VertexType *Vrem=(p.T()->V(Tetra::VofE(p.E(),0)));
VertexType *Vdel=(p.T()->V(Tetra::VofE(p.E(),1)));
//Vrem->P()=(Vrem->P()*alfa)+(Vdel->P()*(1.f-alfa));
Vrem->P()=NewP;
PosLType pos(p.T(),p.F(),p.E(),p.V());
pos.Reset();
To_Del.reserve(40);
To_Del.clear();
while (!pos.LoopEnd())
{
//get the two faces that doesn't share the edge
FacePair fp=_FindNoEdgeFace(pos.T(),pos.E());
int fa0=fp.first;
int fa1=fp.second;
//now set the T-T topology on that faces
TetraType *tleft=pos.T()->TTp(fa0);
TetraType *tright=pos.T()->TTp(fa1);
int ileft=pos.T()->TTi(fa0);
int iright=pos.T()->TTi(fa1);
//in this case I cannot do the collapse
assert (!((pos.T()==tleft)&&(pos.T()==tright)));
//case no one is extern face
if ((!pos.T()->IsBorderF(fa0))&&(!pos.T()->IsBorderF(fa1)))
//connect the 2 tetrahedrons
Topology::_AttachTTTopology(tleft,ileft,tright,iright);
else
//case f2 is an extern face
if (pos.T()->IsBorderF(fa0))
{
tright->TTp(iright)=tright;
tright->TTi(iright)=iright;
}
else //case fa1 is an extern face
//if ((pos.T()->IsBorderF(fa3))
{
tleft->TTp(ileft)=tleft;
tleft->TTi(ileft)=ileft;
}
//end setting T-T topology
//setting the V-T topology
//i remove the tetrahedrons that have the edge
// to collapse
Topology::DetachVTTopology(pos.T());
//end setting the V-T topology
To_Del.push_back(pos.T());
pos.NextT();
n_deleted++;
// tm.tn--;
}
//delting old tetrahedrons
vector<TetraType*>::iterator ti;
for (ti=To_Del.begin();ti<To_Del.end();ti++)
(*ti)->SetD();
//now I cycle on the tetrahedron that had the old vertex
//reassegning the new one.
VTIterator< TetraType> VTi(Vdel->VTb(),Vdel->VTi());
while (!VTi.End())
{
TetraType *T_Change=VTi.Vt();
int index=VTi.Vi();
//VTi++;
//assegning the vertex that remain
T_Change->V(index)=Vrem;
Topology::DetachVTTopology(Vdel,T_Change);
Topology::InsertVTTopology(Vrem,index,T_Change);
//that's cause i restart everytime in the chain
//from the vertex
VTi.Vt()=Vdel->VTb();
VTi.Vi()=Vdel->VTi();
#ifdef _DEBUG
_AssertingVolume(T_Change);
#endif
}
if (Vdel->IsB())
Vrem->SetB();
//set as deleted the vertex
Vdel->SetD();
// tm.vn--;
return n_deleted;
}
static void orMarkE(Edge E,char M)
{
map<Edge,char>::iterator EI;
EI=_EdgeMark().find(E);
if (EI==_EdgeMark().end())
_EdgeMark().insert (pair<Edge,char>(E,M));
else
(*EI).second|=M;
}
static bool isMarkedE(Edge E,char M)
{
map<Edge,char>::iterator EI;
EI=_EdgeMark().find(E);
if (EI==_EdgeMark().end())
return false;
else return ((*EI).second & M);
}
static void orMarkF(Face F,char M)
{
map<Face,char>::iterator FI;
FI=_FaceMark().find(F);
if (FI==_FaceMark().end())
_FaceMark().insert (pair<Face,char>(F,M));
else
(*FI).second|=M;
}
static bool isMarkedF(Face F,char M)
{
map<Face,char>::iterator FI;
FI=_FaceMark().find(F);
if (FI==_FaceMark().end())
return false;
else return ((*FI).second & M);
}
///this structure is used to find the sets that are used in link conditions and more
///verify the link conditions on faces ///verify the link conditions on faces
bool _LinkConditionsF(PosType pos) static bool _LinkConditionsF(PosType pos)
{ {
const int LINK_V0 = 0x00000001; const int LINK_V0 = 0x00000001;
const int LINK_EE = 0x00000002; const int LINK_EE = 0x00000002;
EdgeMark.clear(); _EdgeMark().clear();
// Mark edges of ve0 // Mark edges of ve0
vector< TetraType *>::iterator ti=_Sets.v0.begin(); vector< TetraType *>::iterator ti=_Sets().v0.begin();
vector< char >::iterator en=_Sets.indexv0.begin(); vector< char >::iterator en=_Sets().indexv0.begin();
while (ti!=_Sets.v0.end()) while (ti!=_Sets().v0.end())
{ {
//put dummy face //put dummy face
for (int f=0;f<3;f++) for (int f=0;f<3;f++)
@ -340,19 +357,19 @@ bool _LinkConditionsF(PosType pos)
int f_test=Tetra::FofV((*en),f); int f_test=Tetra::FofV((*en),f);
if ((*ti)->IsBorderF(f_test)) if ((*ti)->IsBorderF(f_test))
{ {
orMarkF(Face((*ti)->V(Tetra::VofF(f_test,0)),(*ti)->V(Tetra::VofF(f_test,1)),&_dummyV),LINK_V0); orMarkF(Face((*ti)->V(Tetra::VofF(f_test,0)),(*ti)->V(Tetra::VofF(f_test,1)),&_DummyV()),LINK_V0);
orMarkF(Face((*ti)->V(Tetra::VofF(f_test,1)),(*ti)->V(Tetra::VofF(f_test,2)),&_dummyV),LINK_V0); orMarkF(Face((*ti)->V(Tetra::VofF(f_test,1)),(*ti)->V(Tetra::VofF(f_test,2)),&_DummyV()),LINK_V0);
orMarkF(Face((*ti)->V(Tetra::VofF(f_test,2)),(*ti)->V(Tetra::VofF(f_test,0)),&_dummyV),LINK_V0); orMarkF(Face((*ti)->V(Tetra::VofF(f_test,2)),(*ti)->V(Tetra::VofF(f_test,0)),&_DummyV()),LINK_V0);
} }
} }
ti++; ti++;
en++; en++;
} }
ti=_Sets.E.begin(); ti=_Sets().E.begin();
en=_Sets.indexE.begin(); en=_Sets().indexE.begin();
//mark them as intersection //mark them as intersection
while (ti!=_Sets.E.end()) while (ti!=_Sets().E.end())
{ {
//faces on the edge //faces on the edge
int f0=Tetra::FofE((*en),0); int f0=Tetra::FofE((*en),0);
@ -360,16 +377,16 @@ bool _LinkConditionsF(PosType pos)
if ((*ti)->IsBorderF(f0)) if ((*ti)->IsBorderF(f0))
{ {
orMarkF(Face((*ti)->V(Tetra::VofF(f0,0)),(*ti)->V(Tetra::VofF(f0,1)),&_dummyV),LINK_EE); orMarkF(Face((*ti)->V(Tetra::VofF(f0,0)),(*ti)->V(Tetra::VofF(f0,1)),&_DummyV()),LINK_EE);
orMarkF(Face((*ti)->V(Tetra::VofF(f0,1)),(*ti)->V(Tetra::VofF(f0,2)),&_dummyV),LINK_EE); orMarkF(Face((*ti)->V(Tetra::VofF(f0,1)),(*ti)->V(Tetra::VofF(f0,2)),&_DummyV()),LINK_EE);
orMarkF(Face((*ti)->V(Tetra::VofF(f0,2)),(*ti)->V(Tetra::VofF(f0,0)),&_dummyV),LINK_EE); orMarkF(Face((*ti)->V(Tetra::VofF(f0,2)),(*ti)->V(Tetra::VofF(f0,0)),&_DummyV()),LINK_EE);
} }
if ((*ti)->IsBorderF(f1)) if ((*ti)->IsBorderF(f1))
{ {
orMarkF(Face((*ti)->V(Tetra::VofF(f1,0)),(*ti)->V(Tetra::VofF(f1,1)),&_dummyV),LINK_EE); orMarkF(Face((*ti)->V(Tetra::VofF(f1,0)),(*ti)->V(Tetra::VofF(f1,1)),&_DummyV()),LINK_EE);
orMarkF(Face((*ti)->V(Tetra::VofF(f1,1)),(*ti)->V(Tetra::VofF(f1,2)),&_dummyV),LINK_EE); orMarkF(Face((*ti)->V(Tetra::VofF(f1,1)),(*ti)->V(Tetra::VofF(f1,2)),&_DummyV()),LINK_EE);
orMarkF(Face((*ti)->V(Tetra::VofF(f1,2)),(*ti)->V(Tetra::VofF(f1,0)),&_dummyV),LINK_EE); orMarkF(Face((*ti)->V(Tetra::VofF(f1,2)),(*ti)->V(Tetra::VofF(f1,0)),&_DummyV()),LINK_EE);
} }
ti++; ti++;
@ -377,9 +394,9 @@ bool _LinkConditionsF(PosType pos)
} }
//and at the end I verify if the intersection is equal to the star of the edge //and at the end I verify if the intersection is equal to the star of the edge
ti=_Sets.v1.begin(); ti=_Sets().v1.begin();
en=_Sets.indexv1.begin(); en=_Sets().indexv1.begin();
while (ti!=_Sets.v1.end()) while (ti!=_Sets().v1.end())
{ {
//dummy edges control //dummy edges control
@ -389,9 +406,9 @@ bool _LinkConditionsF(PosType pos)
if ((*ti)->IsBorderF(f_test)) if ((*ti)->IsBorderF(f_test))
{ {
//control all the 3 edges //control all the 3 edges
Face f_test0=Face((*ti)->V(Tetra::VofF(f_test,0)),(*ti)->V(Tetra::VofF(f_test,1)),&_dummyV); Face f_test0=Face((*ti)->V(Tetra::VofF(f_test,0)),(*ti)->V(Tetra::VofF(f_test,1)),&_DummyV());
Face f_test1=Face((*ti)->V(Tetra::VofF(f_test,1)),(*ti)->V(Tetra::VofF(f_test,2)),&_dummyV); Face f_test1=Face((*ti)->V(Tetra::VofF(f_test,1)),(*ti)->V(Tetra::VofF(f_test,2)),&_DummyV());
Face f_test2=Face((*ti)->V(Tetra::VofF(f_test,2)),(*ti)->V(Tetra::VofF(f_test,0)),&_dummyV); Face f_test2=Face((*ti)->V(Tetra::VofF(f_test,2)),(*ti)->V(Tetra::VofF(f_test,0)),&_DummyV());
if (((isMarkedF(f_test0,LINK_V0))&&(!isMarkedF(f_test0,LINK_EE)))|| if (((isMarkedF(f_test0,LINK_V0))&&(!isMarkedF(f_test0,LINK_EE)))||
((isMarkedF(f_test1,LINK_V0))&&(!isMarkedF(f_test1,LINK_EE)))|| ((isMarkedF(f_test1,LINK_V0))&&(!isMarkedF(f_test1,LINK_EE)))||
((isMarkedF(f_test2,LINK_V0))&&(!isMarkedF(f_test2,LINK_EE)))) ((isMarkedF(f_test2,LINK_V0))&&(!isMarkedF(f_test2,LINK_EE))))
@ -405,17 +422,17 @@ bool _LinkConditionsF(PosType pos)
} }
///verify the link conditions on edges ///verify the link conditions on edges
bool _LinkConditionsE(PosType pos) static bool _LinkConditionsE(PosType pos)
{ {
const int LINK_V0 = 0x00000001; const int LINK_V0 = 0x00000001;
const int LINK_EE = 0x00000002; const int LINK_EE = 0x00000002;
FaceMark.clear(); _FaceMark().clear();
// Mark edges of ve0 // Mark edges of ve0
vector< TetraType *>::iterator ti=_Sets.v0.begin(); vector< TetraType *>::iterator ti=_Sets().v0.begin();
vector< char >::iterator en=_Sets.indexv0.begin(); vector< char >::iterator en=_Sets().indexv0.begin();
while (ti!=_Sets.v0.end()) while (ti!=_Sets().v0.end())
{ {
//put dummy edge //put dummy edge
for (int f=0;f<3;f++) for (int f=0;f<3;f++)
@ -423,19 +440,19 @@ bool _LinkConditionsE(PosType pos)
int f_test=Tetra::FofV((*en),f); int f_test=Tetra::FofV((*en),f);
if ((*ti)->IsBorderF(f_test)) if ((*ti)->IsBorderF(f_test))
{ {
orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,0)),&_dummyV),LINK_V0); orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,0)),&_DummyV()),LINK_V0);
orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,1)),&_dummyV),LINK_V0); orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,1)),&_DummyV()),LINK_V0);
orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,2)),&_dummyV),LINK_V0); orMarkE(Edge((*ti)->V(Tetra::VofF(f_test,2)),&_DummyV()),LINK_V0);
} }
} }
ti++; ti++;
en++; en++;
} }
ti=_Sets.E.begin(); ti=_Sets().E.begin();
en=_Sets.indexE.begin(); en=_Sets().indexE.begin();
//mark them as intersection //mark them as intersection
while (ti!=_Sets.E.end()) while (ti!=_Sets().E.end())
{ {
//faces on the edge //faces on the edge
int f0=Tetra::FofE((*en),0); int f0=Tetra::FofE((*en),0);
@ -443,16 +460,16 @@ bool _LinkConditionsE(PosType pos)
if ((*ti)->IsBorderF(f0)) if ((*ti)->IsBorderF(f0))
{ {
orMarkE(Edge((*ti)->V(Tetra::VofF(f0,0)),&_dummyV),LINK_EE); orMarkE(Edge((*ti)->V(Tetra::VofF(f0,0)),&_DummyV()),LINK_EE);
orMarkE(Edge((*ti)->V(Tetra::VofF(f0,1)),&_dummyV),LINK_EE); orMarkE(Edge((*ti)->V(Tetra::VofF(f0,1)),&_DummyV()),LINK_EE);
orMarkE(Edge((*ti)->V(Tetra::VofF(f0,2)),&_dummyV),LINK_EE); orMarkE(Edge((*ti)->V(Tetra::VofF(f0,2)),&_DummyV()),LINK_EE);
} }
if ((*ti)->IsBorderF(f1)) if ((*ti)->IsBorderF(f1))
{ {
orMarkE(Edge((*ti)->V(Tetra::VofF(f1,0)),&_dummyV),LINK_EE); orMarkE(Edge((*ti)->V(Tetra::VofF(f1,0)),&_DummyV()),LINK_EE);
orMarkE(Edge((*ti)->V(Tetra::VofF(f1,1)),&_dummyV),LINK_EE); orMarkE(Edge((*ti)->V(Tetra::VofF(f1,1)),&_DummyV()),LINK_EE);
orMarkE(Edge((*ti)->V(Tetra::VofF(f1,2)),&_dummyV),LINK_EE); orMarkE(Edge((*ti)->V(Tetra::VofF(f1,2)),&_DummyV()),LINK_EE);
} }
ti++; ti++;
@ -460,9 +477,9 @@ bool _LinkConditionsE(PosType pos)
} }
//and at the end I verify if the intersection is equal to the star of the edge //and at the end I verify if the intersection is equal to the star of the edge
ti=_Sets.v1.begin(); ti=_Sets().v1.begin();
en=_Sets.indexv1.begin(); en=_Sets().indexv1.begin();
while (ti!=_Sets.v1.end()) while (ti!=_Sets().v1.end())
{ {
//dummy edges control //dummy edges control
@ -472,9 +489,9 @@ bool _LinkConditionsE(PosType pos)
if ((*ti)->IsBorderF(f_test)) if ((*ti)->IsBorderF(f_test))
{ {
//control all the 3 edges //control all the 3 edges
Edge e_test0=Edge((*ti)->V(Tetra::VofF(f_test,0)),&_dummyV); Edge e_test0=Edge((*ti)->V(Tetra::VofF(f_test,0)),&_DummyV());
Edge e_test1=Edge((*ti)->V(Tetra::VofF(f_test,1)),&_dummyV); Edge e_test1=Edge((*ti)->V(Tetra::VofF(f_test,1)),&_DummyV());
Edge e_test2=Edge((*ti)->V(Tetra::VofF(f_test,2)),&_dummyV); Edge e_test2=Edge((*ti)->V(Tetra::VofF(f_test,2)),&_DummyV());
if (((isMarkedE(e_test0,LINK_V0))&&(!isMarkedE(e_test0,LINK_EE)))|| if (((isMarkedE(e_test0,LINK_V0))&&(!isMarkedE(e_test0,LINK_EE)))||
((isMarkedE(e_test1,LINK_V0))&&(!isMarkedE(e_test1,LINK_EE)))|| ((isMarkedE(e_test1,LINK_V0))&&(!isMarkedE(e_test1,LINK_EE)))||
((isMarkedE(e_test2,LINK_V0))&&(!isMarkedE(e_test2,LINK_EE)))) ((isMarkedE(e_test2,LINK_V0))&&(!isMarkedE(e_test2,LINK_EE))))
@ -489,14 +506,14 @@ bool _LinkConditionsE(PosType pos)
///verify the link conditions on vertices ///verify the link conditions on vertices
bool _LinkConditionsV() static bool _LinkConditionsV()
{ {
const int LINK_V0 = VertexType::NewUserBit(); const int LINK_V0 = VertexType::NewUserBit();
const int LINK_V1 = VertexType::NewUserBit(); const int LINK_V1 = VertexType::NewUserBit();
const int LINK_EE = VertexType::NewUserBit(); const int LINK_EE = VertexType::NewUserBit();
const int NOT_LINKED = ~(LINK_V0 | LINK_V1 | LINK_EE); const int NOT_LINKED = ~(LINK_V0 | LINK_V1 | LINK_EE);
_dummyV.Flags() &= NOT_LINKED; _DummyV().Flags() &= NOT_LINKED;
VertexType *vt0; VertexType *vt0;
VertexType *vt1; VertexType *vt1;
@ -504,10 +521,10 @@ bool _LinkConditionsV()
VertexType *vt3; VertexType *vt3;
vector< TetraType *>::iterator ti=_Sets.v0_U_v1.begin(); vector< TetraType *>::iterator ti=_Sets().v0_U_v1.begin();
//reset all link flags //reset all link flags
while (ti!=_Sets.v0_U_v1.end()) while (ti!=_Sets().v0_U_v1.end())
{ {
for(int i=0;i<4;i++) for(int i=0;i<4;i++)
(*ti)->V(i)->Flags() &= NOT_LINKED; (*ti)->V(i)->Flags() &= NOT_LINKED;
@ -517,11 +534,11 @@ bool _LinkConditionsV()
//also in the ones that appartain to the edge //also in the ones that appartain to the edge
vector< char >::iterator en; vector< char >::iterator en;
ti=_Sets.E.begin(); ti=_Sets().E.begin();
en=_Sets.indexE.begin(); en=_Sets().indexE.begin();
//reset all link flags for intersection and in the same //reset all link flags for intersection and in the same
//time mark them as intersection //time mark them as intersection
while (ti!=_Sets.E.end()) while (ti!=_Sets().E.end())
{ {
for(int i=0;i<4;i++) for(int i=0;i<4;i++)
{ {
@ -536,7 +553,7 @@ bool _LinkConditionsV()
int f1=Tetra::FofE((*en),1); int f1=Tetra::FofE((*en),1);
if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1))) if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1)))
_dummyV.Flags() |= LINK_EE; _DummyV().Flags() |= LINK_EE;
ti++; ti++;
en++; en++;
@ -544,10 +561,10 @@ bool _LinkConditionsV()
// Mark vertices of ve0 // Mark vertices of ve0
ti=_Sets.v0.begin(); ti=_Sets().v0.begin();
en=_Sets.indexv0.begin(); en=_Sets().indexv0.begin();
while (ti!=_Sets.v0.end()) while (ti!=_Sets().v0.end())
{ {
for(int i=0;i<4;i++) for(int i=0;i<4;i++)
(*ti)->V(i)->Flags() |= LINK_V0; (*ti)->V(i)->Flags() |= LINK_V0;
@ -558,7 +575,7 @@ bool _LinkConditionsV()
int f2=Tetra::FofV((*en),2); int f2=Tetra::FofV((*en),2);
if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1))||((*ti)->IsBorderF(f2))) if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1))||((*ti)->IsBorderF(f2)))
_dummyV.Flags() |= LINK_V0; _DummyV().Flags() |= LINK_V0;
ti++; ti++;
en++; en++;
@ -566,10 +583,10 @@ bool _LinkConditionsV()
//and at the end I verify if the intersection is equal to the star of the edge //and at the end I verify if the intersection is equal to the star of the edge
bool correct=true; bool correct=true;
ti=_Sets.v1.begin(); ti=_Sets().v1.begin();
en=_Sets.indexv1.begin(); en=_Sets().indexv1.begin();
while (ti!=_Sets.v1.end()) while (ti!=_Sets().v1.end())
{ {
vt0=(*ti)->V(0); vt0=(*ti)->V(0);
vt1=(*ti)->V(1); vt1=(*ti)->V(1);
@ -594,7 +611,7 @@ bool _LinkConditionsV()
int f2=Tetra::FofV((*en),2); int f2=Tetra::FofV((*en),2);
if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1))||((*ti)->IsBorderF(f2))) if (((*ti)->IsBorderF(f0))||((*ti)->IsBorderF(f1))||((*ti)->IsBorderF(f2)))
if ((_dummyV.Flags()& LINK_V0)&&(!(_dummyV.Flags()& LINK_EE))) if ((_DummyV().Flags()& LINK_V0)&&(!(_DummyV().Flags()& LINK_EE)))
correct=false; correct=false;
if (!correct) if (!correct)
@ -614,7 +631,7 @@ bool _LinkConditionsV()
} }
///verify the flip condition ///verify the flip condition
bool _FlipCondition(PosType pos,CoordType NewP) static bool _FlipCondition(PosType pos,CoordType NewP)
{ {
int edge=pos.E(); int edge=pos.E();
VertexType *ve0=pos.T()->V(Tetra::VofE(edge,0)); VertexType *ve0=pos.T()->V(Tetra::VofE(edge,0));
@ -623,7 +640,7 @@ bool _FlipCondition(PosType pos,CoordType NewP)
CoordType oldpos1; CoordType oldpos1;
//CoordType newpos=((ve0->P()*alfa)+(ve1->P()*(1.f-alfa))); //CoordType newpos=((ve0->P()*alfa)+(ve1->P()*(1.f-alfa)));
vector< TetraType *>::iterator ti=_Sets.no_E.begin(); vector< TetraType *>::iterator ti=_Sets().no_E.begin();
//verification //verification
oldpos0 = ve0->P(); oldpos0 = ve0->P();
@ -633,19 +650,20 @@ bool _FlipCondition(PosType pos,CoordType NewP)
ve0->P() =NewP; ve0->P() =NewP;
ve1->P() =NewP; ve1->P() =NewP;
while (ti!=_Sets.no_E.end()) while (ti!=_Sets().no_E.end())
{ {
assert(!(*ti)->IsD()); assert(!(*ti)->IsD());
assert((((*ti)->V(0)==ve0)||((*ti)->V(1)==ve0)||((*ti)->V(2)==ve0)||((*ti)->V(3)==ve0))^ assert((((*ti)->V(0)==ve0)||((*ti)->V(1)==ve0)||((*ti)->V(2)==ve0)||((*ti)->V(3)==ve0))^
(((*ti)->V(0)==ve1)||((*ti)->V(1)==ve1)||((*ti)->V(2)==ve1)||((*ti)->V(3)==ve1))); (((*ti)->V(0)==ve1)||((*ti)->V(1)==ve1)||((*ti)->V(2)==ve1)||((*ti)->V(3)==ve1)));
Tetra3<ScalarType> T=Tetra3<ScalarType>(); /* Tetra3<ScalarType> T=Tetra3<ScalarType>();
T.P0(0)=(*ti)->V(0)->cP(); T.P0(0)=(*ti)->V(0)->cP();
T.P1(0)=(*ti)->V(1)->cP(); T.P1(0)=(*ti)->V(1)->cP();
T.P2(0)=(*ti)->V(2)->cP(); T.P2(0)=(*ti)->V(2)->cP();
T.P3(0)=(*ti)->V(3)->cP(); T.P3(0)=(*ti)->V(3)->cP();*/
//flip comes if volume is less or equal to zero //flip comes if volume is less or equal to zero
if (T.ComputeVolume()<=0) ScalarType tv = vcg::ComputeVolume(**ti);
if (vcg::ComputeVolume<TetraType>(**ti)<=0)
{ {
ve0->P()=oldpos0; ve0->P()=oldpos0;
ve1->P()=oldpos1; ve1->P()=oldpos1;
@ -662,7 +680,7 @@ bool _FlipCondition(PosType pos,CoordType NewP)
} }
///update the normal of the modified tetrahedrons ond the normal of the vertex that remain after collapse ///update the normal of the modified tetrahedrons ond the normal of the vertex that remain after collapse
void _InitTetrahedronValues(VertexType* v) static void _InitTetrahedronValues(VertexType* v)
{ {
VTIterator<TetraType> VTi=VTIterator<TetraType>(v->VTb(),v->VTi()); VTIterator<TetraType> VTi=VTIterator<TetraType>(v->VTb(),v->VTi());
@ -690,7 +708,7 @@ void _InitTetrahedronValues(VertexType* v)
if (VTi.Vt()->V(i)->IsB()) if (VTi.Vt()->V(i)->IsB())
{ {
if (VertexType::HasNormal) if (VertexType::HasNormal)
_UN.PerVertex(VTi.Vt()->V(i)); UpdateNormals::PerVertex(VTi.Vt()->V(i));
} }
} }
@ -704,7 +722,7 @@ public:
///Return the aspect Ratio media of the tetrahedrons ///Return the aspect Ratio media of the tetrahedrons
///that share the adge to collapse ///that share the adge to collapse
ScalarType AspectRatioCollapsed(PosType p) static ScalarType AspectRatioCollapsed(PosType p)
{ {
PosL pos=PosL(p.T(),p.F(),p.E(),p.V()); PosL pos=PosL(p.T(),p.F(),p.E(),p.V());
pos.Reset(); pos.Reset();
@ -722,7 +740,7 @@ ScalarType AspectRatioCollapsed(PosType p)
///check the topologycal preserving conditions for the collapse indicated by pos ///check the topologycal preserving conditions for the collapse indicated by pos
bool CheckPreconditions(PosType pos,CoordType NewP) static bool CheckPreconditions(PosType pos,CoordType NewP)
{ {
VertexType *v0=pos.T()->V(Tetra::VofE(pos.E(),0)); VertexType *v0=pos.T()->V(Tetra::VofE(pos.E(),0));
VertexType *v1=pos.T()->V(Tetra::VofE(pos.E(),1)); VertexType *v1=pos.T()->V(Tetra::VofE(pos.E(),1));
@ -730,7 +748,7 @@ bool CheckPreconditions(PosType pos,CoordType NewP)
//we can do it. //we can do it.
bool border0=v0->IsB(); bool border0=v0->IsB();
bool border1=v1->IsB(); bool border1=v1->IsB();
bool bordere=_Topo.IsExternEdge(pos.T(),pos.E()); bool bordere=Topology::IsExternEdge(pos.T(),pos.E());
//first case vertex external and edge internal //first case vertex external and edge internal
if ((border0 && border1)&&(!bordere)) if ((border0 && border1)&&(!bordere))
@ -750,11 +768,11 @@ bool CheckPreconditions(PosType pos,CoordType NewP)
} }
///return the sum of volumes of the union of stars on vertices (the original volume of tetrahedrons) ///return the sum of volumes of the union of stars on vertices (the original volume of tetrahedrons)
ScalarType VolumeOriginal() static ScalarType VolumeOriginal()
{ {
vector< TetraType *>::iterator ti=_Sets.v0_U_v1.begin(); vector< TetraType *>::iterator ti=_Sets().v0_U_v1.begin();
ScalarType vol=0; ScalarType vol=0;
while (ti!=_Sets.v0_U_v1.end()) while (ti!=_Sets().v0_U_v1.end())
{ {
vol+=(*ti)->Volume(); vol+=(*ti)->Volume();
ti++; ti++;
@ -763,7 +781,7 @@ ScalarType VolumeOriginal()
} }
///Calculate the volume on the vertex resulting after collapse... ///Calculate the volume on the vertex resulting after collapse...
ScalarType VolumeSimulateCollapse(PosType Pos,CoordType newP) static ScalarType VolumeSimulateCollapse(PosType Pos,CoordType newP)
{ {
VertexType *Vrem=(Pos.T()->V(Tetra::VofE(Pos.E(),0))); VertexType *Vrem=(Pos.T()->V(Tetra::VofE(Pos.E(),0)));
VertexType *Vdel=(Pos.T()->V(Tetra::VofE(Pos.E(),1))); VertexType *Vdel=(Pos.T()->V(Tetra::VofE(Pos.E(),1)));
@ -777,16 +795,20 @@ ScalarType VolumeSimulateCollapse(PosType Pos,CoordType newP)
//move vertex that remain in the new position //move vertex that remain in the new position
Vrem->P() = newP; Vrem->P() = newP;
vector< TetraType *>::iterator ti=_Sets.no_E.begin(); vector< TetraType *>::iterator ti=_Sets().no_E.begin();
while (ti!=_Sets.no_E.end()) while (ti!=_Sets().no_E.end())
{ {
Tetra3<ScalarType> T=Tetra3<ScalarType>(); /* Tetra3<ScalarType> T=Tetra3<ScalarType>();
T.P0(0)=(*ti)->V(0)->cP(); T.P0(0)=(*ti)->V(0)->cP();
T.P1(0)=(*ti)->V(1)->cP(); T.P1(0)=(*ti)->V(1)->cP();
T.P2(0)=(*ti)->V(2)->cP(); T.P2(0)=(*ti)->V(2)->cP();
T.P3(0)=(*ti)->V(3)->cP(); T.P3(0)=(*ti)->V(3)->cP();
vol+=T.ComputeVolume();
vol+=T.ComputeVolume(); */
// vol+= vcg::ComputeVolume<TetraType>(*((Tetra3<ScalarType>*)&*ti));
vol+= vcg::ComputeVolume(**ti);
ti++; ti++;
} }
Vrem->P()=oldpos; Vrem->P()=oldpos;
@ -794,19 +816,19 @@ ScalarType VolumeSimulateCollapse(PosType Pos,CoordType newP)
} }
///finds sets used for all test in edge collapse ///finds sets used for all test in edge collapse
void FindSets(vcg::tetra::Pos<TetraType> pos) static void FindSets(vcg::tetra::Pos<TetraType> pos)
{ {
_Sets.clear(); _Sets().clear();
int size=40; int size=40;
_Sets.v0.reserve(size); _Sets().v0.reserve(size);
_Sets.indexv0.reserve(size); _Sets().indexv0.reserve(size);
_Sets.v1.reserve(size); _Sets().v1.reserve(size);
_Sets.indexv1.reserve(size); _Sets().indexv1.reserve(size);
_Sets.v0_U_v1.reserve(size*2); _Sets().v0_U_v1.reserve(size*2);
_Sets.no_E.reserve(size*2); _Sets().no_E.reserve(size*2);
_Sets.E.reserve(size); _Sets().E.reserve(size);
_Sets.indexE.reserve(size); _Sets().indexE.reserve(size);
int edge =pos.E(); int edge =pos.E();
@ -818,13 +840,13 @@ void FindSets(vcg::tetra::Pos<TetraType> pos)
while (!vf0.End()) while (!vf0.End())
{ {
//set of ve0 //set of ve0
_Sets.v0.push_back(vf0.Vt()); _Sets().v0.push_back(vf0.Vt());
_Sets.indexv0.push_back(vf0.Vi()); _Sets().indexv0.push_back(vf0.Vi());
//set of union //set of union
_Sets.v0_U_v1.push_back(vf0.Vt()); _Sets().v0_U_v1.push_back(vf0.Vt());
//set of union minus intersection //set of union minus intersection
if ((vf0.Vt()->V(0)!=ve1)&&(vf0.Vt()->V(1)!=ve1)&&(vf0.Vt()->V(2)!=ve1)&&(vf0.Vt()->V(3)!=ve1)) if ((vf0.Vt()->V(0)!=ve1)&&(vf0.Vt()->V(1)!=ve1)&&(vf0.Vt()->V(2)!=ve1)&&(vf0.Vt()->V(3)!=ve1))
_Sets.no_E.push_back(vf0.Vt()); _Sets().no_E.push_back(vf0.Vt());
vf0++; vf0++;
} }
@ -835,19 +857,19 @@ void FindSets(vcg::tetra::Pos<TetraType> pos)
while (!vf0.End()) while (!vf0.End())
{ {
//set of ve1 //set of ve1
_Sets.v1.push_back(vf0.Vt()); _Sets().v1.push_back(vf0.Vt());
_Sets.indexv1.push_back(vf0.Vi()); _Sets().indexv1.push_back(vf0.Vi());
//set of union //set of union
_Sets.v0_U_v1.push_back(vf0.Vt()); _Sets().v0_U_v1.push_back(vf0.Vt());
//set of union minus intersection //set of union minus intersection
if ((vf0.Vt()->V(0)!=ve0)&&(vf0.Vt()->V(1)!=ve0)&&(vf0.Vt()->V(2)!=ve0)&&(vf0.Vt()->V(3)!=ve0)) if ((vf0.Vt()->V(0)!=ve0)&&(vf0.Vt()->V(1)!=ve0)&&(vf0.Vt()->V(2)!=ve0)&&(vf0.Vt()->V(3)!=ve0))
_Sets.no_E.push_back(vf0.Vt()); _Sets().no_E.push_back(vf0.Vt());
vf0++; vf0++;
} }
//erase duplicated tetrahedrons from the union set //erase duplicated tetrahedrons from the union set
sort(_Sets.v0_U_v1.begin(),_Sets.v0_U_v1.end()); sort(_Sets().v0_U_v1.begin(),_Sets().v0_U_v1.end());
unique(_Sets.v0_U_v1.begin(),_Sets.v0_U_v1.end()); unique(_Sets().v0_U_v1.begin(),_Sets().v0_U_v1.end());
//now compute the intersection //now compute the intersection
PosLType PL(pos.T(),pos.F(),pos.E(),pos.V()); PosLType PL(pos.T(),pos.F(),pos.E(),pos.V());
@ -855,21 +877,21 @@ void FindSets(vcg::tetra::Pos<TetraType> pos)
//mark the vertex on the edge //mark the vertex on the edge
while (!PL.LoopEnd()) while (!PL.LoopEnd())
{ {
_Sets.E.push_back(PL.T()); _Sets().E.push_back(PL.T());
_Sets.indexE.push_back(PL.E()); _Sets().indexE.push_back(PL.E());
PL.NextT(); PL.NextT();
} }
} }
///do the collapse on the edge in postype p ///do the collapse on the edge in postype p
void DoCollapse(PosType p,CoordType newP) static int DoCollapse(PosType p,CoordType newP)
{ {
VertexType *v=p.T()->V(p.V()); VertexType *v=p.T()->V(p.V());
assert(p.T()->HasVTAdjacency()); assert(p.T()->HasVTAdjacency());
_Collapse(p,newP); int n_deleted = _Collapse(p,newP);
_InitTetrahedronValues(v); _InitTetrahedronValues(v);
return n_deleted;
} }