#ifndef MIQ_SEAMS_INTIALIZER #define MIQ_SEAMS_INTIALIZER #include #include #include #include template class SeamsInitializer { private: typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::FaceIterator FaceIterator; MeshType *mesh; ///per face per edge of mmatch in the solver typename MeshType::template PerFaceAttributeHandle Handle_MMatch; ///per vertex singular or not typename MeshType::template PerVertexAttributeHandle Handle_Singular; ///per vertex degree of a singularity typename MeshType::template PerVertexAttributeHandle Handle_SingularDegree; ///seam per face typename MeshType::template PerFaceAttributeHandle > Handle_Seams; ///seam index per face typename MeshType::template PerFaceAttributeHandle Handle_SeamsIndex; bool IsRotSeam(const FaceType *f0,const int edge) { unsigned char MM=Handle_MMatch[f0][edge];//MissMatch(f0,edge); return (MM!=0); } ///return true if a vertex is singluar by looking at initialized missmatches bool IsSingularByMMatch(const VertexType &v,int &missmatch) { ///check that is on border.. if (v.IsB()) return false; vcg::face::Pos pos(v.cVFp(), v.cVFi()); std::vector > posVec; vcg::face::VFOrderedStarFF(pos, posVec); missmatch=0; for (unsigned int i=0;i::template GetPerFaceAttribute(*mesh,std::string("MissMatch")); Handle_Singular=vcg::tri::Allocator::template GetPerVertexAttribute(*mesh,std::string("Singular")); Handle_SingularDegree=vcg::tri::Allocator::template GetPerVertexAttribute(*mesh,std::string("SingularityDegree")); Handle_Seams=vcg::tri::Allocator::template GetPerFaceAttribute >(*mesh,std::string("Seams")); Handle_SeamsIndex=vcg::tri::Allocator::template GetPerFaceAttribute(*mesh,std::string("SeamsIndex")); } void FloodFill(FaceType* start) { std::deque d; ///clean the visited flag start->SetV(); d.push_back(start); while (!d.empty()){ FaceType *f = d.at(0); d.pop_front(); for (int s = 0; s<3; s++) { FaceType *g = f->FFp(s); int j = f->FFi(s); if ((!(IsRotSeam(f,s))) && (!(IsRotSeam(g,j))) && (!g->IsV()) ) { Handle_Seams[f][s]=false; Handle_Seams[g][j]=false; g->SetV(); d.push_back(g); } } } } void Retract(){ std::vector e(mesh->vert.size(),0); // number of edges per vert VertexType *vb = &(mesh->vert[0]); for (FaceIterator f = mesh->face.begin(); f!=mesh->face.end(); f++) if (!f->IsD()){ for (int s = 0; s<3; s++){ //if (f->seam[s]) if (Handle_Seams[f][s]) if (f->FFp(s)<=&*f) { e[ f->V(s) - vb ] ++; e[ f->V1(s) - vb ] ++; } } } bool over=true; int guard = 0; do { over = true; for (FaceIterator f = mesh->face.begin(); f!=mesh->face.end(); f++) if (!f->IsD()){ for (int s = 0; s<3; s++){ //if (f->seam[s]) if (Handle_Seams[f][s]) if (!(IsRotSeam(&(*f),s))) // never retract rot seams //if (f->FFp(s)<=&*f) { if (e[ f->V(s) - vb ] == 1) { // dissolve seam //f->seam[s] = false; Handle_Seams[f][s]=false; //f->FFp(s)->seam[(int)f->FFi(s)] = false; Handle_Seams[f->FFp(s)][(int)f->FFi(s)]=false; e[ f->V(s) - vb ] --; e[ f->V1(s) - vb ] --; over = false; } } } } if (guard++>10000) over = true; } while (!over); } void AddSeamsByMM() { for (unsigned int i=0;iface.size();i++) { FaceType *f=&mesh->face[i]; if (f->IsD())continue; for (int j=0;j<3;j++) { if (IsRotSeam(f,j)) Handle_Seams[f][j]=true; //f->SetSeam(j); } } } void SelectSingularityByMM() { for (unsigned int i=0;ivert.size();i++) { if (mesh->vert[i].IsD())continue; int missmatch; bool isSing=IsSingularByMMatch(mesh->vert[i],missmatch); if (isSing) { mesh->vert[i].SetS(); Handle_Singular[i]=true; if (missmatch==3)missmatch=1; else if (missmatch==1)missmatch=3; Handle_SingularDegree[i]=missmatch; } else { mesh->vert[i].ClearS(); Handle_Singular[i]=false; Handle_SingularDegree[i]=0; } } } int InitTopologycalCuts(){ vcg::tri::UpdateFlags::FaceClearV(*mesh); for (FaceIterator f = mesh->face.begin(); f!=mesh->face.end(); f++) if (!f->IsD()) { Handle_Seams[f][0]=true; Handle_Seams[f][1]=true; Handle_Seams[f][2]=true; } int index=0; for (FaceIterator f = mesh->face.begin(); f!=mesh->face.end(); f++) if (!f->IsD()) { if (!f->IsV()) { index++; FloodFill(&*f); } } Retract(); return index; } void InitMMatch() { for (unsigned int i=0;iface.size();i++) { FaceType *curr_f=&mesh->face[i]; for (int j=0;j<3;j++) { FaceType *opp_f=curr_f->FFp(j); if (curr_f==opp_f) Handle_MMatch[curr_f][j]=0; else Handle_MMatch[curr_f][j]=vcg::tri::CrossField::MissMatchByCross(*curr_f,*opp_f); } } } void InitSeamIndexes() { ///initialize seams indexes for (unsigned int i=0;iface.size();i++) { FaceType *f=&mesh->face[i]; for (int j=0;j<3;j++) Handle_SeamsIndex[f][j]=-1; } std::vector > > seamsVert; seamsVert.resize(mesh->vert.size()); for (unsigned int i=0;iface.size();i++) { FaceType *f=&mesh->face[i]; for (int j=0;j<3;j++) { if (f->IsB(j))continue; if (Handle_Seams[f][j]) { VertexType *v0=f->V0(j); VertexType *v1=f->V1(j); if (v0>v1)continue; int index0=v0-&mesh->vert[0]; int index1=v1-&mesh->vert[0]; std::pair entry=std::pair(f,j); seamsVert[index0].push_back(entry); seamsVert[index1].push_back(entry); } } } int curr_index=0; for (unsigned int i=0;ivert.size();i++) { VertexType *v_seam=&mesh->vert[i]; bool IsVertex=(Handle_Singular[i])||(seamsVert[i].size()>2)|| (v_seam->IsB()); if(!IsVertex)continue; ///then follows the seam for (unsigned int j=0;jFFp(edge); int edge1=f->FFi(edge); Handle_SeamsIndex[f1][edge1]=curr_index;///set current value assert((v0==f->V0(edge))|| (v0==f->V1(edge))); if (f->V0(edge)==v0) v1=f->V1(edge); else v1=f->V0(edge); assert(v0!=v1); //int index0=v0-&mesh->vert[0]; int index1=v1-&mesh->vert[0]; bool IsVertex=(Handle_Singular[v1])|| (seamsVert[index1].size()>2)|| (v1->IsB()); if(IsVertex) finished=true; else { assert(seamsVert[index1].size()==2); FaceType *f_new[2]; int edge_new[2]; f_new[0]=seamsVert[index1][0].first; edge_new[0]=seamsVert[index1][0].second; f_new[1]=seamsVert[index1][1].first; edge_new[1]=seamsVert[index1][1].second; assert((f_new[0]==f)||(f_new[1]==f)); assert((edge_new[0]==edge)||(edge_new[1]==edge)); if ((f_new[0]==f)&&(edge_new[0]==edge)) { f=f_new[1]; edge=edge_new[1]; } else { f=f_new[0]; edge=edge_new[0]; } v0=v1; } } while (!finished); //return; curr_index++; } } } public: void Init(MeshType *_mesh, bool orient_globally, bool initMM, bool initCuts) { mesh=_mesh; vcg::tri::UpdateTopology::FaceFace(*_mesh); vcg::tri::UpdateFlags::FaceBorderFromFF(*_mesh); vcg::tri::UpdateFlags::VertexBorderFromFace(*_mesh); AddAttributesIfNeeded(); if (orient_globally) vcg::tri::CrossField::MakeDirectionFaceCoherent(*mesh); if (initMM) InitMMatch(); SelectSingularityByMM(); if (initCuts) { InitTopologycalCuts(); AddSeamsByMM(); } //InitSeamIndexes(); } SeamsInitializer(){mesh=NULL;} }; #endif