From 858b87d98b66e7e7bc2bc0095310b547fa57553a Mon Sep 17 00:00:00 2001 From: ganovelli Date: Thu, 15 Jul 2004 11:36:13 +0000 Subject: [PATCH] first working draft (trivial collapse) --- vcg/complex/trimesh/edge_collapse.h | 351 +++++++++++++++++++--------- 1 file changed, 246 insertions(+), 105 deletions(-) diff --git a/vcg/complex/trimesh/edge_collapse.h b/vcg/complex/trimesh/edge_collapse.h index 2d1b541e..50f92aea 100644 --- a/vcg/complex/trimesh/edge_collapse.h +++ b/vcg/complex/trimesh/edge_collapse.h @@ -29,6 +29,7 @@ #include +#include #include /** \addtogroup trimesh */ @@ -51,7 +52,7 @@ class EdgeCollapse /// The vertex iterator type typedef typename TriMeshType::VertexIterator VertexIterator; /// The tetra iterator type - typedef typename TriMeshType::FaceIterator TetraIterator; + typedef typename TriMeshType::FaceIterator FaceIterator; /// The coordinate type typedef typename FaceType::VertexType::CoordType CoordType; /// The scalar type @@ -60,8 +61,18 @@ class EdgeCollapse typedef typename TriMeshType::FaceContainer FaceContainer; ///the container of vertex type typedef typename TriMeshType::VertContainer VertContainer; - - /// Default Constructor + ///half edge type + typedef typename vcg::face::Pos PosType; + /// vector of pos + typedef typename std::vector PosVec; + ///of VFIterator + typedef typename vcg::face::VFIterator VFI; + /// vector of VFIterator + typedef typename std::vector > VFIVec; + + + + /// Default Constructor EdgeCollapse() { }; @@ -91,7 +102,7 @@ class EdgeCollapse }; -map EdgeMark; +std::map EdgeMark; void orMark(Edge E,char M) { @@ -113,119 +124,249 @@ bool isMarked(Edge E,char M) } ///control link conditions for the collapse -bool LinkCondition(vcg::face::Pos pos) -{ - const int LINK_V0 = VertexType::NewBitFlag(); - const int LINK_V1 = VertexType::NewBitFlag(); - const int LINK_EE = VertexType::NewBitFlag(); - - const int NOT_LINKED = ~(LINK_V0 | LINK_V1 | LINK_EE); - - VertexType *ve0=pos.f->V(pos.z); - VertexType *ve1=pos.f->V((pos.z+1)%3); - int edge =pos.z; +//bool LinkCondition(vcg::face::Pos pos) +//{ +// const int LINK_V0 = VertexType::NewBitFlag(); +// const int LINK_V1 = VertexType::NewBitFlag(); +// const int LINK_EE = VertexType::NewBitFlag(); +// +// const int NOT_LINKED = ~(LINK_V0 | LINK_V1 | LINK_EE); +// +// VertexType *ve0=pos.f->V(pos.z); +// VertexType *ve1=pos.f->V((pos.z+1)%3); +// int edge =pos.z; +// +// VFIterator vf0(ve0->VFb(),ve0->VFi()); +// // Clear visited and adj flag for all vertices adj to v0; +// while (!vf0.End()) +// { +// vf0.f->V(0)->Flags() &= NOT_LINKED; +// vf0.f->V(1)->Flags() &= NOT_LINKED; +// vf0.f->V(2)->Flags() &= NOT_LINKED; +// vf0++; +// } +// +// VFIterator vf1(ve1->VFb(),ve1->VFi()); +// // Clear visited and adj flag for all vertices adj to v0; +// while (!vf1.End()) +// { +// vf1.f->V(0)->Flags() &= NOT_LINKED; +// vf1.f->V(1)->Flags() &= NOT_LINKED; +// vf1.f->V(2)->Flags() &= NOT_LINKED; +// vf1++; +// } +// +// vf0.f=ve0->VFb(); +// vf0.f=ve0->VFi(); +// // Mark vertices of v0 +// while (!vf0.End()) +// { +// vf0.f->V(0)->Flags() |= (LINK_V0); +// vf0.f->V(1)->Flags() |= (LINK_V0); +// vf0.f->V(2)->Flags() |= (LINK_V0); +// orMark(Edge(vf0.f->V(0),vf0.f->V(1)),LINK_V0); +// orMark(Edge(vf0.f->V(1),vf0.f->V(2)),LINK_V0); +// orMark(Edge(vf0.f->V(2),vf0.f->V(0)),LINK_V0); +// vf0++; +// } +// +// //mark the entities on the edge +// VertexType* vt0=pos.f->V(edge); +// VertexType* vt1=pos.f->V((edge+1)%3); +// VertexType* vt2=pos.f->V((edge+2)%3); +// +// vt0->Flags() |= (LINK_EE); +// vt1->Flags() |= (LINK_EE); +// vt2->Flags() |= (LINK_EE); +// +// +// FaceType *opp=pos.f()->FFp(edge); +// int eopp=pos.f()->FFi(edge); +// +// VertexType* vt3=opp.f->V((eopp+2)%3); +// vt3->Flags() |= LINK_EE; +// +// //mark the edges +// orMark(Edge(vt0,vt1),LINK_EE); +// orMark(Edge(vt0,vt2),LINK_EE); +// orMark(Edge(vt1,vt2),LINK_EE); +// orMark(Edge(vt0,vt3),LINK_EE); +// orMark(Edge(vt1,vt3),LINK_EE); +// +// //and at the end I verify if the intersection is equal to the star of the edge +// vf1.f=ve1->VFb(); +// vf1.f=ve1->VFi(); +// bool correct=true; +// while (!vf1.End()) +// { +// vt0=vf1.f->V(0); +// vt1=vf1.f->V(1); +// vt2=vf1.f->V(2); +// +// if ((vt0->Flags()& LINK_V0)&&(!(vt0->Flags()& LINK_EE))) +// correct=false; +// else +// if ((vt1->Flags()& LINK_V0)&&(!(vt1->Flags()& LINK_EE))) +// correct=false; +// else +// if ((vt2->Flags()& LINK_V0)&&(!(vt2->Flags()& LINK_EE))) +// correct=false; +// else +// if ((isMarked(Edge(v0,v1),LINK_V0))&&(!isMarked(Edge(v0,v1),LINK_EE))) +// correct=false; +// else +// if ((isMarked(Edge(v1,v2),LINK_V0))&&(!isMarked(Edge(v1,v2),LINK_EE))) +// correct=false; +// else +// if ((isMarked(Edge(v2,v0),LINK_V0))&&(!isMarked(Edge(v2,v0),LINK_EE))) +// correct=false; +// +// if (!correct) +// { +// VertexType::DeleteBitFlag(LINK_V0); +// VertexType::DeleteBitFlag(LINK_V1); +// VertexType::DeleteBitFlag(LINK_EE); +// return (false) +// } +// vf1++; +// } +// return true; +// VertexType::DeleteBitFlag(LINK_V0); +// VertexType::DeleteBitFlag(LINK_V1); +// VertexType::DeleteBitFlag(LINK_EE); +// } - VFIterator vf0(ve0->VFb(),ve0->VFi()); - // Clear visited and adj flag for all vertices adj to v0; - while (!vf0.End()) - { - vf0.f->V(0)->Flags() &= NOT_LINKED; - vf0.f->V(1)->Flags() &= NOT_LINKED; - vf0.f->V(2)->Flags() &= NOT_LINKED; - vf0++; - } + static VFIVec & AV0(){static VFIVec av0; return av0;} + static VFIVec & AV1(){static VFIVec av1; return av1;} + static VFIVec & AV01(){static VFIVec av01; return av01;} - VFIterator vf1(ve1->VFb(),ve1->VFi()); - // Clear visited and adj flag for all vertices adj to v0; - while (!vf1.End()) - { - vf1.f->V(0)->Flags() &= NOT_LINKED; - vf1.f->V(1)->Flags() &= NOT_LINKED; - vf1.f->V(2)->Flags() &= NOT_LINKED; - vf1++; - } - vf0.f=ve0->VFb(); - vf0.f=ve0->VFi(); - // Mark vertices of v0 - while (!vf0.End()) - { - vf0.f->V(0)->Flags() |= (LINK_V0); - vf0.f->V(1)->Flags() |= (LINK_V0); - vf0.f->V(2)->Flags() |= (LINK_V0); - orMark(Edge(vf0.f->V(0),vf0.f->V(1)),LINK_V0); - orMark(Edge(vf0.f->V(1),vf0.f->V(2)),LINK_V0); - orMark(Edge(vf0.f->V(2),vf0.f->V(0)),LINK_V0); - vf0++; - } + void FindSets(PosType p) + { + VertexType * v0 = p.V(0); + VertexType * v1 = p.V(1); + + AV0().clear(); // Facce incidenti in v0 + AV1().clear(); // Facce incidenti in v1 + AV01().clear(); // Facce incidenti in v0 e v1 - //mark the entities on the edge - VertexType* vt0=pos.f->V(edge); - VertexType* vt1=pos.f->V((edge+1)%3); - VertexType* vt2=pos.f->V((edge+2)%3); + VFI x; - vt0->Flags() |= (LINK_EE); - vt1->Flags() |= (LINK_EE); - vt2->Flags() |= (LINK_EE); - - - FaceType *opp=pos.f()->FFp(edge); - int eopp=pos.f()->FFi(edge); - - VertexType* vt3=opp.f->V((eopp+2)%3); - vt3->Flags() |= LINK_EE; + for( x.f = v0->VFp(), x.z = v0->VFi(); x.f!=0; x++) + { + + int zv1 = -1; - //mark the edges - orMark(Edge(vt0,vt1),LINK_EE); - orMark(Edge(vt0,vt2),LINK_EE); - orMark(Edge(vt1,vt2),LINK_EE); - orMark(Edge(vt0,vt3),LINK_EE); - orMark(Edge(vt1,vt3),LINK_EE); + for(int j=0;j<3;++j) + if( x.f->V(j)==&*v1 ) { + zv1 = j; + break; + } + if(zv1==-1) AV0().push_back( x ); // la faccia x.f non ha il vertice v1 => e' incidente solo in v0 + else AV01().push_back( x ); + } - //and at the end I verify if the intersection is equal to the star of the edge - vf1.f=ve1->VFb(); - vf1.f=ve1->VFi(); - bool correct=true; - while (!vf1.End()) - { - vt0=vf1.f->V(0); - vt1=vf1.f->V(1); - vt2=vf1.f->V(2); + for( x.f = v1->VFp(), x.z = v1->VFi(); x.f!=0; x++ ) + { + int zv0 = -1; - if ((vt0->Flags()& LINK_V0)&&(!(vt0->Flags()& LINK_EE))) - correct=false; - else - if ((vt1->Flags()& LINK_V0)&&(!(vt1->Flags()& LINK_EE))) - correct=false; - else - if ((vt2->Flags()& LINK_V0)&&(!(vt2->Flags()& LINK_EE))) - correct=false; - else - if ((isMarked(Edge(v0,v1),LINK_V0))&&(!isMarked(Edge(v0,v1),LINK_EE))) - correct=false; - else - if ((isMarked(Edge(v1,v2),LINK_V0))&&(!isMarked(Edge(v1,v2),LINK_EE))) - correct=false; - else - if ((isMarked(Edge(v2,v0),LINK_V0))&&(!isMarked(Edge(v2,v0),LINK_EE))) - correct=false; + for(int j=0;j<3;++j) + if( x.f->V(j)==&*v0 ) { + zv0 = j; + break; + } + if(zv0==-1) AV1().push_back( x ); // la faccia x.f non ha il vertice v1 => e' incidente solo in v0 + } +} - if (!correct) - { - VertexType::DeleteBitFlag(LINK_V0); - VertexType::DeleteBitFlag(LINK_V1); - VertexType::DeleteBitFlag(LINK_EE); - return (false) - } - vf1++; - } - return true; - VertexType::DeleteBitFlag(LINK_V0); - VertexType::DeleteBitFlag(LINK_V1); - VertexType::DeleteBitFlag(LINK_EE); + bool LinkConditions(PosType pos){ + + const int ADJ_1 = TriMeshType::VertexType::NewBitFlag(); + const int ADJ_E = TriMeshType::VertexType::NewBitFlag(); + //enum {ADJ_1= MeshType::VertexType::USER0, + // ADJ_E= MeshType::VertexType::USER0<<1} ; + const int ALLADJ = ADJ_1|ADJ_E; + const int NOTALLADJ = ~(ADJ_1 | ADJ_E | TriMeshType::VertexType::VISITED); + const int NOTALLADJ1 = ~(ADJ_E | TriMeshType::VertexType::VISITED); + + //EdgePosB x; + vcg::face::VFIterator x; + // Clear visited and adj flag for all vertices adj to v0; + for(x.f = pos.V(0)->VFp(), x.z = pos.V(0)->VFi(); x.f!=0; x++ ) { + x.f->V1(x.z)->Flags() &= NOTALLADJ; + x.f->V2(x.z)->Flags() &= NOTALLADJ; + } + // Clear visited flag for all vertices adj to v1 and set them adj1 to v1; + for(x.f = pos.V(1)->VFp(), x.z = pos.V(1)->VFi(); x.f!=0; x++ ) { + x.f->V1(x.z)->Flags() &= NOTALLADJ1; + x.f->V2(x.z)->Flags() &= NOTALLADJ1; + } + // Mark vertices adj to v1 as ADJ_1 and adj1 to v1; + for(x.f = pos.V(1)->VFp(), x.z = pos.V(1)->VFi(); x.f!=0; x++ ) { + if(x.f->V1(x.z)==pos.V(0)) x.f->V2(x.z)->Flags() |= ADJ_E | ADJ_1; + else x.f->V2(x.z)->Flags() |= ADJ_1; + if(x.f->V2(x.z)==pos.V(0)) x.f->V1(x.z)->Flags() |= ADJ_E | ADJ_1; + else x.f->V1(x.z)->Flags() |= ADJ_1; + } + + // compute the number of: + int adj01=0; // vertices adjacents to both v0 and v1 + int adje=0; // vertices adjacents to an egde (usually 2) + for(x.f = pos.V(0)->VFp(), x.z = pos.V(0)->VFi(); x.f!=0; x++ ) { + if(!x.f->V1(x.z)->IsV()) { + x.f->V1(x.z)->SetV(); + if(x.f->V1(x.z)->Flags()&ADJ_1) ++adj01; + if(x.f->V1(x.z)->Flags()&ADJ_E) ++adje; + } + if(!x.f->V2(x.z)->IsV()) { + x.f->V2(x.z)->SetV(); + if(x.f->V2(x.z)->Flags()&ADJ_1) ++adj01; + if(x.f->V2(x.z)->Flags()&ADJ_E) ++adje; + } + } + + //bool val=TopoCheck2(); + //if(val != (adj01==adje)) printf("Wrong topo %i %i\n",adj01,adje); + TriMeshType::VertexType::DeleteBitFlag(ADJ_E); + TriMeshType::VertexType::DeleteBitFlag(ADJ_1); + + return (adj01==adje); } + + int DoCollapse(PosType & c, Point3 p) + { + VFIVec::iterator i; + int n_face_del =0 ; + + for(i=AV01().begin();i!=AV01().end();++i) + { + FaceType * f = ((*i).f); + assert(f->V((*i).z) == c.V(0)); + + vcg::face::VFDetach(*f,((*i).z+1)%3); + vcg::face::VFDetach(*((*i).f),((*i).z+2)%3); + ((*i).f)->SetD(); + n_face_del++; + } + + for(i=AV0().begin();i!=AV0().end();++i) + { + (*i).f->V((*i).z) = c.V(1); // In tutte le facce incidenti in v0, si sostituisce v0 con v1 + (*i).f->VFp((*i).z) = (*i).f->V((*i).z)->VFp(); // e appendo la lista di facce incidenti in v1 a questa faccia + (*i).f->VFi((*i).z) = (*i).f->V((*i).z)->VFi(); + (*i).f->V((*i).z)->VFp() = (*i).f; + (*i).f->V((*i).z)->VFi() = (*i).z; + } + + + TriMeshType::VertexType nv; +//* c.v[1]->Merge(*c.v[0]); + c.V(0)->SetD(); + return n_face_del; + } + }; }