Reimplement isComplexManifold

Reimplement isRegular
This commit is contained in:
Massimiliano Corsini 2005-12-15 13:53:13 +00:00
parent becbfab7da
commit ba6382f984
1 changed files with 109 additions and 157 deletions

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.18 2005/12/14 14:04:35 corsini
Fix genus computation
Revision 1.17 2005/12/12 12:11:40 cignoni Revision 1.17 2005/12/12 12:11:40 cignoni
Removed unuseful detectunreferenced Removed unuseful detectunreferenced
@ -86,17 +89,18 @@ Initial Release
#ifndef __VCGLIB_CLEAN #ifndef __VCGLIB_CLEAN
#define __VCGLIB_CLEAN #define __VCGLIB_CLEAN
// Standard headers
#include <map> #include <map>
#include <algorithm> #include <algorithm>
#include <stack> #include <stack>
// VCG headers
#include <vcg/simplex/face/face.h> #include <vcg/simplex/face/face.h>
#include<vcg/simplex/face/topology.h> #include <vcg/simplex/face/pos.h>
#include <vcg/simplex/face/topology.h>
#include <vcg/complex/trimesh/base.h> #include <vcg/complex/trimesh/base.h>
#include <vcg/complex/trimesh/closest.h> #include <vcg/complex/trimesh/closest.h>
#include <vcg/space/index/grid_static_ptr.h> #include <vcg/space/index/grid_static_ptr.h>
#include<vcg/complex/trimesh/allocate.h> #include<vcg/complex/trimesh/allocate.h>
@ -232,14 +236,11 @@ namespace vcg {
return deleted; return deleted;
} }
static int RemoveZeroAreaFace(MeshType& m, ScalarType epsilon=0) static int RemoveZeroAreaFace(MeshType& m, ScalarType epsilon=0)
{ {
FaceIterator fi; FaceIterator fi;
int count_fd = 0; int count_fd = 0;
for(fi=m.face.begin(); fi!=m.face.end();++fi) for(fi=m.face.begin(); fi!=m.face.end();++fi)
if(Area<FaceType>(*fi) <= epsilon) if(Area<FaceType>(*fi) <= epsilon)
{ {
@ -249,30 +250,66 @@ namespace vcg {
} }
return count_fd; return count_fd;
} }
/**
* Check if the mesh is a manifold.
*
* First of all, for each face the FF condition is checked.
* Then, a second test is performed: for each vertex the
* number of face found have to be the same of the number of
* face found with the VF walk trough.
*/
static bool IsComplexManifold( MeshType & m ) static bool IsComplexManifold( MeshType & m )
{ {
bool flagManifold = true;
VertexIterator vi;
FaceIterator fi; FaceIterator fi;
bool Manifold = true;
for( fi=m.face.begin();fi!=m.face.end();++fi) // First Test
assert(m.HasFFTopology());
for (fi = m.face.begin(); fi != m.face.end(); ++fi)
{ {
for (int j=0;j<3;j++) if ((!IsManifold(*fi,0))||
(!IsManifold(*fi,1))||
(!IsManifold(*fi,2)))
{ {
if(!IsManifold(*fi,j)) flagManifold = false;
{ break;
Manifold = false;
fi= m.face.end();
--fi;
j=3;
}
}
if((BorderCount(*fi)>0))
{
Manifold = false;
fi= m.face.end();
--fi;
} }
} }
return Manifold;
// Second Test
if (flagManifold)
{
assert(m.HasVFTopology());
face::VFIterator<FaceType> vfi;
int starSizeFF;
int starSizeVF;
for (vi = m.vert.begin(); vi != m.vert.end(); ++vi)
{
face::VFIterator<FaceType> vfi(&*vi);
face::Pos<FaceType> pos((*vi).VFp(), &*vi);
starSizeFF = pos.StarSize();
starSizeVF = 0;
while(!vfi.End())
{
++vfi;
starSizeVF++;
}
if (starSizeFF != starSizeVF)
{
flagManifold = false;
break;
}
}
}
return flagManifold;
} }
static void CountEdges( MeshType & m, int &count_e, int &boundary_e ) static void CountEdges( MeshType & m, int &count_e, int &boundary_e )
@ -341,8 +378,6 @@ namespace vcg {
(*fi).ClearS(); (*fi).ClearS();
gi=m.face.begin(); fi=gi; gi=m.face.begin(); fi=gi;
for(fi=m.face.begin();fi!=m.face.end();fi++)//for all faces do for(fi=m.face.begin();fi!=m.face.end();fi++)//for all faces do
{ {
for(int j=0;j<3;j++)//for all edges for(int j=0;j<3;j++)//for all edges
@ -383,7 +418,7 @@ namespace vcg {
} }
} }
} }
return holes.size(); return static_cast<int>(holes.size());
} }
static int BorderEdges( MeshType & m, int numholes) static int BorderEdges( MeshType & m, int numholes)
@ -491,148 +526,65 @@ namespace vcg {
return -((V + F - E + numholes - 2 * numcomponents) / 2); return -((V + F - E + numholes - 2 * numcomponents) / 2);
} }
static void IsRegularMesh(MeshType &m, bool Regular, bool Semiregular) /**
* Check if the given mesh is regular, semi-regular or irregular.
*
* Each vertex of a \em regular mesh has valence 6 except for border vertices
* which have valence 4.
*
* A \em semi-regular mesh is derived from an irregular one applying
* 1-to-4 subdivision recursively. (not checked for now)
*
* All other meshes are \em irregular.
*/
static void IsRegularMesh(MeshType &m, bool &Regular, bool &Semiregular)
{ {
int inc=0; // This algorithm requires Vertex-Face topology
VertexIterator v; assert(m.HasVFTopology());
FaceIterator fi;
vcg::face::Pos<FaceType> he; Regular = true;
vcg::face::Pos<FaceType> hei;
for(v=m.vert.begin();v!=m.vert.end();++v) VertexIterator vi;
(*v).ClearS();
for(fi=m.face.begin();fi!=m.face.end();++fi) // for each vertex the number of edges are count
for (vi = m.vert.begin(); vi != m.vert.end(); ++vi)
{ {
for (int j=0; j<3; j++) face::Pos<FaceType> he((*vi).VFp(), &*vi);
face::Pos<FaceType> ht = he;
int n=0;
bool border=false;
do
{ {
he.Set(&(*fi),j,fi->V(j)); ++n;
if (!face::IsBorder(*fi,j) && !face::IsBorder(*fi,(j+2)%3) && !fi->V(j)->IsS()) ht.NextE();
{ if (ht.IsBorder())
hei=he; border=true;
inc=1; }
he.FlipE(); while (ht != he);
he.NextF();
while (he.f!=hei.f)
{
he.FlipE();
if (he.IsBorder())
{
inc=6;
break;
}
he.NextF();
inc++;
}
if (inc!=6)
Regular=false;
if (inc!=6 && inc!=5)
Semiregular=false;
fi->V(j)->SetS();
} if (border)
else n = n/2;
fi->V(j)->SetS();
} if ((n != 6)&&(!border && n != 4))
if (Semiregular==false) {
Regular = false;
break; break;
}
} }
if (!Regular)
Semiregular = false;
else
{
// For now we do not account for semi-regularity
Semiregular = false;
}
} }
static void IsOrientedMesh(MeshType &m, bool Oriented, bool Orientable) static void IsOrientedMesh(MeshType &m, bool Oriented, bool Orientable)
{ {
FaceIterator fi; //...TODO...
FacePointer gi=&*m.face.begin();
vcg::face::Pos<FaceType> he;
vcg::face::Pos<FaceType> hei;
std::stack<FacePointer> sf;
FacePointer l;
for(fi=m.face.begin();fi!=m.face.end();++fi)
{
(*fi).ClearS();
(*fi).ClearUserBit(0);
}
//gi=m.face.begin(); fi=gi;
for(fi=m.face.begin();fi!=m.face.end();++fi)
{
if (!(*fi).IsS())
{
(*fi).SetS();
sf.push(&*fi);
while (!sf.empty())
{
gi=sf.top();
sf.pop();
for(int j=0;j<3;++j)
{
if( !face::IsBorder(*gi,j) )
{
he.Set(&(*gi),0,gi->V(0));
l=he.f->FFp(j);
he.Set(&(*gi),j,gi->V(j));
hei.Set(he.f->FFp(j),he.f->FFi(j), (he.f->FFp(j))->V(he.f->FFi(j)));
if( !(*gi).IsUserBit(0) )
{
if (he.v!=hei.v)// bene
{
if ((*l).IsS() && (*l).IsUserBit(0))
{
Orientable=false;
break;
}
else if (!(*l).IsS())
{
(*l).SetS();
sf.push(l);
}
}
else if (!(*l).IsS())
{
Oriented=false;
(*l).SetS();
(*l).SetUserBit(0);
sf.push(l);
}
else if ((*l).IsS() && !(*l).IsUserBit(0))
{
Orientable=false;
break;
}
}
else if (he.v==hei.v)// bene
{
if ((*l).IsS() && (*l).IsUserBit(0))
{
Orientable=false;
break;
}
else if (!(*l).IsS())
{
(*l).SetS();
sf.push(l);
}
}
else if (!(*l).IsS())
{
Oriented=false;
(*l).SetS();
(*l).SetUserBit(0);
sf.push(l);
}
else if ((*l).IsS() && !(*l).IsUserBit(0))
{
Orientable=false;
break;
}
}
}
}
}
if (!Orientable)
break;
}
} }
static bool SelfIntersections(MeshType &m) static bool SelfIntersections(MeshType &m)