/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: not supported by cvs2svn $ Revision 1.15 2005/10/12 10:36:26 cignoni Removed unused local type Edge. Now it use the standard simplex edge. Revision 1.14 2004/12/10 01:04:42 cignoni better comments Revision 1.13 2004/11/23 10:34:45 cignoni passed parameters by reference in many funcs and gcc cleaning ****************************************************************************/ #ifndef __VCG_TETRA_TRI_COLLAPSE #define __VCG_TETRA_TRI_COLLAPSE #include #include namespace vcg{ namespace tri{ /** \addtogroup trimesh */ /*@{*/ /** This a static utility class for the edge collapse. It provides a common set of useful function for actually making an edge collapse over a trimesh. See also the corresponding class in the local optimization framework called TriEdgeCollapse **/ template class EdgeCollapse { public: /// The tetrahedral mesh type typedef TRI_MESH_TYPE TriMeshType; /// The tetrahedron type typedef typename TriMeshType::FaceType FaceType; /// The vertex type typedef typename FaceType::VertexType VertexType; /// The vertex iterator type typedef typename TriMeshType::VertexIterator VertexIterator; /// The tetra iterator type typedef typename TriMeshType::FaceIterator FaceIterator; /// The coordinate type typedef typename FaceType::VertexType::CoordType CoordType; /// The scalar type typedef typename TriMeshType::VertexType::ScalarType ScalarType; ///the container of tetrahedron type typedef typename TriMeshType::FaceContainer FaceContainer; ///the container of vertex type typedef typename TriMeshType::VertContainer VertContainer; ///half edge type typedef typename TriMeshType::FaceType::EdgeType EdgeType; /// vector of pos typedef typename std::vector EdgeVec; ///of VFIterator typedef typename vcg::face::VFIterator VFI; /// vector of VFIterator typedef typename std::vector > VFIVec; /// Default Constructor EdgeCollapse() { }; ~EdgeCollapse() { }; static VFIVec & AV0(){static VFIVec av0; return av0;} static VFIVec & AV1(){static VFIVec av1; return av1;} static VFIVec & AV01(){static VFIVec av01; return av01;} void FindSets(EdgeType &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 VFI x; for( x.f = v0->VFp(), x.z = v0->VFi(); x.f!=0; ++x) { int zv1 = -1; 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 ); } for( x.f = v1->VFp(), x.z = v1->VFi(); x.f!=0; ++x ) { int zv0 = -1; 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 } } bool LinkConditions(EdgeType 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; typename 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(EdgeType & c, const Point3 &p) { FindSets(c); typename VFIVec::iterator i; int n_face_del =0 ; //set Face Face topology if (TriMeshType::HasFFTopology()) { //int e0=c.z; //int e1=c.f->FFi(c.z); //opposite edge //FaceType *f0=c.f; //FaceType *f1=f0->FFp(c.z); // ////take right indexes //FaceType *f00=f0->FFp((e0+1)%3); //FaceType *f01=f0->FFp((e0+2)%3); //int If00=f0->FFi((e0+1)%3); //int If01=f0->FFi((e0+2)%3); // ////then attach faces //f00->FFp(If00)=f01; //f00->FFi(If00)=If01; //f01->FFp(If01)=f00; //f01->FFi(If01)=If00; ////and the ones of face f1 //f00=f1->FFp((e1+1)%3); //f01=f1->FFp((e1+2)%3); //If00=f1->FFi((e1+1)%3); //If01=f1->FFi((e1+2)%3); // ////and attach faces //f00->FFp(If00)=f01; //f00->FFi(If00)=If01; //f01->FFp(If01)=f00; //f01->FFi(If01)=If00; } 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(f,((*i).z+2)%3); f.SetD(); n_face_del++; } //set Vertex Face topology 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; } c.V(0)->SetD(); c.V(1)->P()=p; return n_face_del; } }; } } #endif