Complete re-wrote of the link condition test for topology preserving edge collapse. Now it is much slower but really correct. Hopefully.

This commit is contained in:
Paolo Cignoni 2010-06-18 11:47:04 +00:00
parent 212c15b77b
commit 830fb74a0f
1 changed files with 103 additions and 1 deletions

View File

@ -66,6 +66,7 @@ class EdgeCollapse
typedef typename TriMeshType::FaceType FaceType;
/// The vertex type
typedef typename FaceType::VertexType VertexType;
typedef typename FaceType::VertexPointer VertexPointer;
/// The vertex iterator type
typedef typename TriMeshType::VertexIterator VertexIterator;
/// The tetra iterator type
@ -139,8 +140,109 @@ class EdgeCollapse
if(zv0==-1) AV1().push_back( x ); // la faccia x.f non ha il vertice v1 => e' incidente solo in v0
}
}
/*
Link Conditions test, as described in
bool LinkConditions(EdgeType pos){
Topology Preserving Edge Contraction
T. Dey, H. Edelsbrunner,
Pub. Inst. Math. 1999
Lk (sigma) is the set of all the faces of the cofaces of sigma that are disjoint from sigma
Lk(v0) inters Lk(v1) == Lk(v0-v1)
To perform these tests using only the VF adjacency we resort to some virtual counters over
the vertices and the edges, we implement them as std::maps, and we increase these counters
by running over all the faces around each vertex of the collapsing edge.
At the end (after adding dummy stuff) we should have
2 for vertices not shared
4 for vertices shared
2 for edges shared
1 for edges not shared.
*/
bool LinkConditions(EdgeType pos)
{
typedef typename vcg::face::VFIterator<FaceType> VFIterator;
// at the end of the loop each vertex must be counted twice
// except for boundary vertex.
std::map<VertexPointer,int> VertCnt;
std::map<std::pair<VertexPointer,VertexPointer>,int> EdgeCnt;
// the list of the boundary vertexes for the two endpoints
std::vector<VertexPointer> BoundaryVertexVec[2];
// Collect vertexes and edges of V0 and V1
VFIterator vfi;
for(int i=0;i<2;++i)
{
vfi = VFIterator(pos.V(i));
for( ;!vfi.End();++vfi)
{
++ VertCnt[vfi.V1()];
++ VertCnt[vfi.V2()];
if(vfi.V1()<vfi.V2()) ++EdgeCnt[make_pair(vfi.V1(),vfi.V2())];
else ++EdgeCnt[make_pair(vfi.V2(),vfi.V1())];
}
// Now a loop to add dummy stuff: add the dummy vertex and two dummy edges
// (and remember to increase the counters for the two boundary vertexes involved)
typename std::map<VertexPointer,int>::iterator vcmit;
for(vcmit=VertCnt.begin();vcmit!=VertCnt.end();++vcmit)
{
if((*vcmit).second==1) // boundary vertexes are counted only once
BoundaryVertexVec[i].push_back((*vcmit).first);
}
if(BoundaryVertexVec[i].size()==2)
{ // aha! one of the two vertex of the collapse is on the boundary
// so add dummy vertex and two dummy edges
VertCnt[0]+=2;
++ EdgeCnt[std::make_pair(VertexPointer(0),BoundaryVertexVec[i][0]) ] ;
++ EdgeCnt[std::make_pair(VertexPointer(0),BoundaryVertexVec[i][1]) ] ;
// remember to hide the boundaryness of the two boundary vertexes
++VertCnt[BoundaryVertexVec[i][0]];
++VertCnt[BoundaryVertexVec[i][1]];
}
}
// Final loop to find cardinality of lk( V0-V1 )
// Note that Lk(edge) is only a set of vertices.
std::vector<VertexPointer> LkEdge;
for( vfi = VFIterator(pos.V(0)); !vfi.End(); ++vfi)
{
if(vfi.V1() == pos.V(1) ) LkEdge.push_back(pos.V(2));
if(vfi.V2() == pos.V(1) ) LkEdge.push_back(pos.V(1));
}
// if the collapsing edge was a boundary edge, we must add the dummy vertex.
// Note that this implies that Lk(edge) >=2;
if(LkEdge.size()==1)
{
LkEdge.push_back(0);
}
// NOW COUNT!!!
size_t SharedEdgeCnt=0;
typename std::map<std::pair<VertexPointer,VertexPointer>, int>::iterator eci;
for(eci=EdgeCnt.begin();eci!=EdgeCnt.end();++eci)
if((*eci).second == 2) SharedEdgeCnt ++;
if(SharedEdgeCnt>0) return false;
size_t SharedVertCnt=0;
typename std::map<VertexPointer,int>::iterator vci;
for(vci=VertCnt.begin();vci!=VertCnt.end();++vci)
if((*vci).second == 4) SharedVertCnt++;
if(SharedVertCnt != LkEdge.size() ) return false;
return true;
}
bool LinkConditionsOld(EdgeType pos){
const int ADJ_1 = TriMeshType::VertexType::NewBitFlag();
const int ADJ_E = TriMeshType::VertexType::NewBitFlag();