Added IsCoherentlyOrientedMesh and cleaned up a bit the self intersection

This commit is contained in:
Paolo Cignoni 2013-06-24 10:50:14 +00:00
parent 9acdf598a1
commit 98e49178ba
1 changed files with 238 additions and 228 deletions

View File

@ -946,14 +946,12 @@ private:
static void CountEdges( MeshType & m, int &count_e, int &boundary_e ) static void CountEdges( MeshType & m, int &count_e, int &boundary_e )
{ {
tri::RequireFFAdjacency(m);
count_e=0; count_e=0;
boundary_e=0; boundary_e=0;
UpdateFlags<MeshType>::FaceClearV(m); UpdateFlags<MeshType>::FaceClearV(m);
FaceIterator fi;
vcg::face::Pos<FaceType> he;
vcg::face::Pos<FaceType> hei;
bool counted =false; bool counted =false;
for(fi=m.face.begin();fi!=m.face.end();fi++) for(FaceIterator fi=m.face.begin();fi!=m.face.end();fi++)
{ {
if(!((*fi).IsD())) if(!((*fi).IsD()))
{ {
@ -970,8 +968,8 @@ private:
} }
else//We have a non-manifold edge else//We have a non-manifold edge
{ {
hei.Set(&(*fi), j , fi->V(j)); vcg::face::Pos<FaceType> hei(&(*fi), j , fi->V(j));
he=hei; vcg::face::Pos<FaceType> he=hei;
he.NextF(); he.NextF();
while (he.f!=hei.f)// so we have to iterate all faces that are connected to this edge while (he.f!=hei.f)// so we have to iterate all faces that are connected to this edge
{ {
@ -1212,31 +1210,31 @@ private:
Semiregular = false; Semiregular = false;
} }
} }
// static void IsOrientedMesh(MeshType &m, bool &Oriented, bool &Orientable)
static bool IsCoherentlyOrientedMesh(MeshType &m)
{
for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
if (!fi->IsD())
for(int i=0;i<3;++i)
if(!face::CheckOrientation(*fi,i))
return false;
return true;
}
static void OrientCoherentlyMesh(MeshType &m, bool &Oriented, bool &Orientable) static void OrientCoherentlyMesh(MeshType &m, bool &Oriented, bool &Orientable)
{ {
RequireFFAdjacency(m); RequireFFAdjacency(m);
assert(&Oriented != &Orientable); assert(&Oriented != &Orientable);
assert(m.face.back().FFp(0)); // This algorithms require FF topology initialized
// This algorithms require FF topology initialized
assert(m.face.back().FFp(0));
Orientable = true; Orientable = true;
Oriented = true; Oriented = true;
// Ensure that each face is deselected tri::UpdateSelection<MeshType>::FaceClear(m);
FaceIterator fi;
for (fi = m.face.begin(); fi != m.face.end(); ++fi)
fi->ClearS();
// initialize stack
std::stack<FacePointer> faces; std::stack<FacePointer> faces;
for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
// for each face of the mesh
FacePointer fp,fpaux;
int iaux;
for (fi = m.face.begin(); fi != m.face.end(); ++fi)
{ {
if (!fi->IsD() && !fi->IsS()) if (!fi->IsD() && !fi->IsS())
{ {
@ -1247,15 +1245,15 @@ private:
// empty the stack // empty the stack
while (!faces.empty()) while (!faces.empty())
{ {
fp = faces.top(); FacePointer fp = faces.top();
faces.pop(); faces.pop();
// make consistently oriented the adjacent faces // make consistently oriented the adjacent faces
for (int j = 0; j < 3; j++) for (int j = 0; j < 3; j++)
{ {
// get one of the adjacent face // get one of the adjacent face
fpaux = fp->FFp(j); FacePointer fpaux = fp->FFp(j);
iaux = fp->FFi(j); int iaux = fp->FFi(j);
if (!fpaux->IsD() && fpaux != fp && face::IsManifold<FaceType>(*fp, j)) if (!fpaux->IsD() && fpaux != fp && face::IsManifold<FaceType>(*fp, j))
{ {
@ -1290,6 +1288,8 @@ private:
if (!Orientable) break; if (!Orientable) break;
} }
} }
/// Flip the orientation of the whole mesh flipping all the faces (by swapping the first two vertices) /// Flip the orientation of the whole mesh flipping all the faces (by swapping the first two vertices)
static void FlipMesh(MeshType &m, bool selected=false) static void FlipMesh(MeshType &m, bool selected=false)
{ {
@ -1497,27 +1497,26 @@ private:
static bool SelfIntersections(MeshType &m, std::vector<FaceType*> &ret) static bool SelfIntersections(MeshType &m, std::vector<FaceType*> &ret)
{ {
RequirePerFaceMark(m); RequirePerFaceMark(m);
Box3< ScalarType> bbox;
TriMeshGrid gM;
ret.clear(); ret.clear();
FaceIterator fi;
int referredBit = FaceType::NewBitFlag(); int referredBit = FaceType::NewBitFlag();
tri::UpdateFlags<MeshType>::FaceClear(m,referredBit); tri::UpdateFlags<MeshType>::FaceClear(m,referredBit);
std::vector<FaceType*> inBox; TriMeshGrid gM;
gM.Set(m.face.begin(),m.face.end()); gM.Set(m.face.begin(),m.face.end());
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
{ {
(*fi).SetUserBit(referredBit); (*fi).SetUserBit(referredBit);
Box3< ScalarType> bbox;
(*fi).GetBBox(bbox); (*fi).GetBBox(bbox);
std::vector<FaceType*> inBox;
vcg::tri::GetInBoxFace(m, gM, bbox,inBox); vcg::tri::GetInBoxFace(m, gM, bbox,inBox);
bool Intersected=false; bool Intersected=false;
typename std::vector<FaceType*>::iterator fib; typename std::vector<FaceType*>::iterator fib;
for(fib=inBox.begin();fib!=inBox.end();++fib) for(fib=inBox.begin();fib!=inBox.end();++fib)
{ {
if(!(*fib)->IsUserBit(referredBit) && (*fib != &*fi) ) if(!(*fib)->IsUserBit(referredBit) && (*fib != &*fi) )
if(TestFaceFaceIntersection(&*fi,*fib)){ if(Clean<MeshType>::TestFaceFaceIntersection(&*fi,*fib)){
ret.push_back(*fib); ret.push_back(*fib);
if(!Intersected) { if(!Intersected) {
ret.push_back(&*fi); ret.push_back(&*fi);
@ -1623,8 +1622,19 @@ private:
int i0,i1; ScalarType a,b; int i0,i1; ScalarType a,b;
face::FindSharedVertex(f0,f1,i0,i1); face::FindSharedVertex(f0,f1,i0,i1);
Point3f shP = f0->V(i0)->P()*0.5; Point3f shP = f0->V(i0)->P()*0.5;
if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f0).V1(i0)->P()*0.5+shP,(*f0).V2(i0)->P()*0.5+shP), *f1, a, b) ) return true; if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f0).V1(i0)->P()*0.5+shP,(*f0).V2(i0)->P()*0.5+shP), *f1, a, b) )
if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f1).V1(i1)->P()*0.5+shP,(*f1).V2(i1)->P()*0.5+shP), *f0, a, b) ) return true; {
// a,b are the param coords of the intersection point of the segment.
if(a+b>=1 || a<=EPSIL || b<=EPSIL ) return false;
return true;
}
if(vcg::IntersectionSegmentTriangle(Segment3<ScalarType>((*f1).V1(i1)->P()*0.5+shP,(*f1).V2(i1)->P()*0.5+shP), *f0, a, b) )
{
// a,b are the param coords of the intersection point of the segment.
if(a+b>=1 || a<=EPSIL || b<=EPSIL ) return false;
return true;
}
} }
return false; return false;
} }