diff --git a/vcg/simplex/face/topology.h b/vcg/simplex/face/topology.h index 01ffa8ee..0b345968 100644 --- a/vcg/simplex/face/topology.h +++ b/vcg/simplex/face/topology.h @@ -24,6 +24,8 @@ #ifndef _VCG_FACE_TOPOLOGY #define _VCG_FACE_TOPOLOGY +#include + namespace vcg { namespace face { /** \addtogroup face */ @@ -244,47 +246,46 @@ void FFDetachManifold(FaceType & f, const int e) template void FFDetach(FaceType & f, const int e) { - assert(FFCorrectness(f,e)); - assert(!IsBorder(f,e)); // Never try to detach a border edge! - int complexity=ComplexSize(f,e); - (void) complexity; - assert(complexity>0); + assert(FFCorrectness(f,e)); + assert(!IsBorder(f,e)); // Never try to detach a border edge! + int complexity=ComplexSize(f,e); + (void) complexity; + assert(complexity>0); + vcg::face::Pos FirstFace(&f,e); // Build the half edge + vcg::face::Pos LastFace(&f,e); // Build the half edge + FirstFace.NextF(); + LastFace.NextF(); + int cnt=0; - Pos< FaceType > FirstFace(&f,e); // Build the half edge - Pos< FaceType > LastFace(&f,e); // Build the half edge - FirstFace.NextF(); - LastFace.NextF(); - int cnt=0; +// then in case of non manifold face continue to advance LastFace +// until I find it become the one that +// preceed the face I want to erase - // then in case of non manifold face continue to advance LastFace - // until I find it become the one that - // preceed the face I want to erase + while ( LastFace.f->FFp(LastFace.z) != &f) + { + assert(ComplexSize(*LastFace.f,LastFace.z)==complexity); + assert(!LastFace.IsManifold()); // We enter in this loop only if we are on a non manifold edge + assert(!LastFace.IsBorder()); + LastFace.NextF(); + cnt++; + assert(cnt<100); + } - while ( LastFace.f->FFp(LastFace.z) != &f) - { - assert(ComplexSize(*LastFace.f,LastFace.z)==complexity); - assert(!LastFace.IsManifold()); // We enter in this loop only if we are on a non manifold edge - assert(!LastFace.IsBorder()); - LastFace.NextF(); - cnt++; - assert(cnt<100); - } + assert(LastFace.f->FFp(LastFace.z)==&f); + assert(f.FFp(e)== FirstFace.f); - assert(LastFace.f->FFp(LastFace.z)==&f); - assert(f.FFp(e)== FirstFace.f); + // Now we link the last one to the first one, skipping the face to be detached; + LastFace.f->FFp(LastFace.z) = FirstFace.f; + LastFace.f->FFi(LastFace.z) = FirstFace.z; + assert(ComplexSize(*LastFace.f,LastFace.z)==complexity-1); - // Now we link the last one to the first one, skipping the face to be detached; - LastFace.f->FFp(LastFace.z) = FirstFace.f; - LastFace.f->FFi(LastFace.z) = FirstFace.z; - assert(ComplexSize(*LastFace.f,LastFace.z)==complexity-1); + // At the end selfconnect the chosen edge to make a border. + f.FFp(e) = &f; + f.FFi(e) = e; + assert(ComplexSize(f,e)==1); - // At the end selfconnect the chosen edge to make a border. - f.FFp(e) = &f; - f.FFi(e) = e; - assert(ComplexSize(f,e)==1); - - assert(FFCorrectness(*LastFace.f,LastFace.z)); - assert(FFCorrectness(f,e)); + assert(FFCorrectness(*LastFace.f,LastFace.z)); + assert(FFCorrectness(f,e)); } @@ -297,25 +298,34 @@ void FFDetach(FaceType & f, const int e) template void FFAttach(FaceType * &f, int z1, FaceType *&f2, int z2) { - //typedef FEdgePosB< FACE_TYPE > ETYPE; - Pos< FaceType > EPB(f2,z2); - Pos< FaceType > TEPB; - TEPB = EPB; - EPB.NextF(); - while( EPB.f != f2) //Alla fine del ciclo TEPB contiene la faccia che precede f2 - { - TEPB = EPB; - EPB.NextF(); - } - //Salvo i dati di f1 prima di sovrascrivere + //typedef FEdgePosB< FACE_TYPE > ETYPE; + vcg::face::Pos< FaceType > EPB(f2,z2); + vcg::face::Pos< FaceType > TEPB; + TEPB = EPB; + EPB.NextF(); + while( EPB.f != f2) //Alla fine del ciclo TEPB contiene la faccia che precede f2 + { + TEPB = EPB; + EPB.NextF(); + } + //Salvo i dati di f1 prima di sovrascrivere FaceType *f1prec = f->FFp(z1); - int z1prec = f->FFi(z1); + int z1prec = f->FFi(z1); + //Aggiorno f1 + assert(f1prec == f); + assert(TEPB.f->FFp(TEPB.z) == f2); + f->FFp(z1) = TEPB.f->FFp(TEPB.z); - f->FFi(z1) = TEPB.f->FFi(TEPB.z); - //Aggiorno la faccia che precede f2 - TEPB.f->FFp(TEPB.z) = f1prec; - TEPB.f->FFi(TEPB.z) = z1prec; + f->FFi(z1) = TEPB.f->FFi(TEPB.z); + + //Aggiorno la faccia che precede f2 + TEPB.f->FFp(TEPB.z) = f1prec; + TEPB.f->FFi(TEPB.z) = z1prec; + + assert(FFCorrectness(*f,z1)); + assert(FFCorrectness(*TEPB.f, TEPB.z)); + } /** This function attach the face (via the edge z1) to another face (via the edge z2). @@ -625,15 +635,54 @@ bool CheckFlipEdge(FaceType &f, int z) PosType startPos=pos; do { - pos.NextE(); - if (g_v2 == pos.VFlip()) - return false; + pos.NextE(); + if (g_v2 == pos.VFlip()) + return false; } while (pos != startPos); return true; } +template +bool checkFlipEdgeNotManifold (FaceType &f, const int z) +{ + typedef typename FaceType::VertexType VertexType; + typedef typename vcg::face::Pos< FaceType > PosType; + if (z<0 || z>2) return false; + + // boundary edges cannot be flipped + if (vcg::face::IsBorder(f, z)) return false; + + FaceType *g = f.FFp(z); + int w = f.FFi(z); + + // check if the vertices of the edge are the same + // e.g. the mesh has to be well oriented + if (g->V(w)!=f.V1(z) || g->V1(w)!=f.V(z) ) + return false; + + // check if the flipped edge is already present in the mesh + // f_v2 and g_v2 are the vertices of the new edge + VertexType *f_v2 = f.V2(z); + VertexType *g_v2 = g->V2(w); + + PosType pos(&f, (z+2)%3, f_v2); + PosType startPos=pos; + do + { + pos.FlipE(); + pos.NextF(); +// if (g_v2 == pos.F()->V((pos.E()+1) % 3)) + if (g_v2 == pos.VFlip()) + return false; + } + while (pos != startPos); + + return true; + +} + /*! * Flip the z-th edge of the face f. * Check for topological correctness first using CheckFlipEdge(). @@ -675,41 +724,121 @@ void FlipEdge(FaceType &f, const int z) assert( g->V2(w) != f.V1(z) ); assert( g->V2(w) != f.V2(z) ); + int fi1 = f.FFi(f.Next(z)); + FaceType* fp1 = f.FFp(f.Next(z)); + + int gi1 = g->FFi(g->Next(w)); + FaceType* gp1 = g->FFp(g->Next(w)); + +// FaceType* fp2 = f.FFp(f.Next(z)); + + f.V1(z) = g->V2(w); g->V1(w) = f.V2(z); - f.FFp(z) = g->FFp((w+1)%3); - f.FFi(z) = g->FFi((w+1)%3); - g->FFp(w) = f.FFp((z+1)%3); - g->FFi(w) = f.FFi((z+1)%3); - f.FFp((z+1)%3) = g; - f.FFi((z+1)%3) = (w+1)%3; - g->FFp((w+1)%3) = &f; - g->FFi((w+1)%3) = (z+1)%3; + //topology update - if(f.FFp(z)==g) - { - f.FFp(z) = &f; - f.FFi(z) = z; - } - else - { - f.FFp(z)->FFp( f.FFi(z) ) = &f; - f.FFp(z)->FFi( f.FFi(z) ) = z; - } - if(g->FFp(w)==&f) - { - g->FFp(w)=g; - g->FFi(w)=w; - } - else - { - g->FFp(w)->FFp( g->FFi(w) ) = g; - g->FFp(w)->FFi( g->FFi(w) ) = w; - } + + f.FFp(z) = g->FFp((w+1)%3); + f.FFi(z) = g->FFi((w+1)%3); + g->FFp(w) = f.FFp((z+1)%3); + g->FFi(w) = f.FFi((z+1)%3); + + f.FFp((z+1)%3) = g; + f.FFi((z+1)%3) = (w+1)%3; + g->FFp((w+1)%3) = &f; + g->FFi((w+1)%3) = (z+1)%3; + + if(f.FFp(z)==g) + { + f.FFp(z) = &f; + f.FFi(z) = z; + } + else + { + f.FFp(z)->FFp( f.FFi(z) ) = &f; + f.FFp(z)->FFi( f.FFi(z) ) = z; + } + if(g->FFp(w)==&f) + { + g->FFp(w)=g; + g->FFi(w)=w; + } + else + { + g->FFp(w)->FFp( g->FFi(w) ) = g; + g->FFp(w)->FFi( g->FFi(w) ) = w; + } } +/*! +* Flip the z-th edge of the face f. +* Check for topological correctness first using CheckFlipEdge(). +* \param f pointer to the face +* \param z the edge index +* +* Note: For edge flip we intend the swap of the diagonal of the quadrilater +* formed by the face \a f and the face adjacent to the specified edge. +* +* 0__________ 2 0__________2 +* -> 1|\ | | /|1 +* | \ g | | g / | +* | \ | |w / | +* | f z\w | | / f z| +* | \ | | / | +* |__________\|1 <- 1|/__________| +* 2 0 2 0 +* +* Note that, after an operation FlipEdge(f,z) +* to topologically revert it should be sufficient to do FlipEdge(f,z+1) +* (even if the mesh is actually different: f and g will be swapped) +* +*/ +template +void FlipEdgeNotManifold(FaceType &f, const int z) +{ + assert(z>=0); + assert(z<3); + assert( !IsBorder(f,z) ); + assert( face::IsManifold(f, z)); + + FaceType *g = f.FFp(z); // The other face + int w = f.FFi(z); // and other side + + assert( g->V0(w) == f.V1(z) ); + assert( g->V1(w) == f.V0(z) ); + assert( g->V2(w) != f.V0(z) ); + assert( g->V2(w) != f.V1(z) ); + assert( g->V2(w) != f.V2(z) ); + + int fi1 = f.FFi(f.Next(z)); + FaceType* fp1 = f.FFp(f.Next(z)); + + int gi1 = g->FFi(g->Next(w)); + FaceType* gp1 = g->FFp(g->Next(w)); + + + FFDetach(f, z); + if (!IsBorder(f, (z+1)%3)) + FFDetach(f, (z+1)%3); + if (!IsBorder(*g, (w+1)%3)) + FFDetach(*g, (w+1)%3); + + f.V1(z) = g->V2(w); + g->V1(w) = f.V2(z); + + //topology update + FaceType* ftmp = &f; + + if (gp1 != g) + FFAttach(ftmp, z, gp1, gi1); + if (fp1 != &f) + FFAttach(g, w, fp1, fi1); + + FFAttachManifold(ftmp, (z+1)%3, g, (w+1)%3); +} + template void TriSplit(FaceType *fToSplit, FaceType *newf0, FaceType *newf1, typename FaceType::VertexType *newVert) {