00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include<vcg/space/triangle3.h>
00025 #include<vcg/complex/complex.h>
00026 #include<vcg/complex/algorithms/hole.h>
00027 #include<vcg/complex/algorithms/local_optimization.h>
00028 #include<vcg/complex/algorithms/local_optimization/tri_edge_flip.h>
00029 #include<vcg/complex/algorithms/smooth.h>
00030 #include<vcg/complex/algorithms/refine.h>
00031
00032 #include<vcg/complex/algorithms/update/selection.h>
00033
00034
00035 #include<vcg/complex/algorithms/update/topology.h>
00036 #include <vcg/complex/algorithms/update/flag.h>
00037 #include <vcg/complex/algorithms/update/normal.h>
00038
00039
00040 #include<vcg/simplex/face/pos.h>
00041
00042
00043 #include <wrap/io_trimesh/import_ply.h>
00044 #include <wrap/io_trimesh/export_ply.h>
00045
00046 using namespace vcg;
00047 using namespace std;
00048
00049 class MyFace;
00050 class MyVertex;
00051 struct MyUsedTypes : public UsedTypes< Use<MyVertex> ::AsVertexType,
00052 Use<MyFace> ::AsFaceType>{};
00053
00054 class MyVertex : public Vertex< MyUsedTypes, vertex::Coord3f, vertex::BitFlags, vertex::Normal3f, vertex::Mark, vertex::Color4b >{};
00055 class MyFace : public Face < MyUsedTypes, face::VertexRef,face::FFAdj, face::Mark, face::BitFlags, face::Normal3f> {};
00056
00057 class MyMesh : public tri::TriMesh< vector<MyVertex>, vector<MyFace > >{};
00058
00059
00060 class MyDelaunayFlip: public vcg::tri::TriEdgeFlip< MyMesh, MyDelaunayFlip > {
00061 public:
00062 typedef vcg::tri::TriEdgeFlip< MyMesh, MyDelaunayFlip > TEF;
00063 inline MyDelaunayFlip( const TEF::PosType &p, int i,BaseParameterClass *pp) :TEF(p,i,pp){}
00064 };
00065
00066 bool callback(int percent, const char *str) {
00067 cout << "str: " << str << " " << percent << "%\r";
00068 return true;
00069 }
00070
00071 template <class MESH>
00072 bool NormalTest(typename face::Pos<typename MESH::FaceType> pos)
00073 {
00074
00075 typename MESH::ScalarType thr = 0.0f;
00076 typename MESH::CoordType NdP = vcg::TriangleNormal<typename MESH::FaceType>(*pos.f);
00077 typename MESH::CoordType tmp, oop, soglia = typename MESH::CoordType(thr,thr,thr);
00078 face::Pos<typename MESH::FaceType> aux=pos;
00079 do{
00080 aux.FlipF();
00081 aux.FlipE();
00082 oop = Abs(tmp - ::vcg::TriangleNormal<typename MESH::FaceType>(*pos.f));
00083 if(oop < soglia )return false;
00084 }while(aux != pos && !aux.IsBorder());
00085
00086 return true;
00087 }
00088
00089 int main(int argc,char ** argv){
00090
00091 if(argc<5)
00092 {
00093 printf(
00094 "\n HoleFilling (" __DATE__ ")\n"
00095 "Visual Computing Group I.S.T.I. C.N.R.\n"
00096 "Usage: trimesh_hole #algorithm #size filein.ply fileout.ply \n"
00097 "#algorithm: \n"
00098 " 1) Trivial Ear \n"
00099 " 2) Minimum weight Ear \n"
00100 " 3) Selfintersection Ear \n"
00101 " 4) Minimum weight \n"
00102 );
00103 exit(0);
00104 }
00105
00106 int algorithm = atoi(argv[1]);
00107 int holeSize = atoi(argv[2]);
00108 if(algorithm < 0 && algorithm > 4)
00109 {
00110 printf("Error in algorithm's selection %i\n",algorithm);
00111 exit(0);
00112 }
00113
00114 MyMesh m;
00115
00116 if(tri::io::ImporterPLY<MyMesh>::Open(m,argv[3])!=0)
00117 {
00118 printf("Error reading file %s\n",argv[2]);
00119 exit(0);
00120 }
00121
00122
00123 tri::UpdateTopology<MyMesh>::FaceFace(m);
00124 tri::UpdateNormal<MyMesh>::PerVertexPerFace(m);
00125 tri::UpdateFlags<MyMesh>::FaceBorderFromFF(m);
00126 assert(tri::Clean<MyMesh>::IsFFAdjacencyConsistent(m));
00127
00128
00129 float AVG,sumA=0.0f;
00130 int numA=0,indice;
00131 indice = m.face.size();
00132 MyMesh::FaceIterator fi;
00133 for(fi=m.face.begin();fi!=m.face.end();++fi)
00134 {
00135 sumA += DoubleArea(*fi)/2;
00136 numA++;
00137 for(int ind =0;ind<3;++ind)
00138 fi->V(ind)->InitIMark();
00139 }
00140 AVG=sumA/numA;
00141
00142
00143 switch(algorithm)
00144 {
00145 case 1: tri::Hole<MyMesh>::EarCuttingFill<tri::TrivialEar<MyMesh> >(m,holeSize,false); break;
00146 case 2: tri::Hole<MyMesh>::EarCuttingFill<tri::MinimumWeightEar< MyMesh> >(m,holeSize,false,callback); break;
00147 case 3: tri::Hole<MyMesh>::EarCuttingIntersectionFill<tri::SelfIntersectionEar< MyMesh> >(m,holeSize,false); break;
00148 case 4: tri::Hole<MyMesh>::MinimumWeightFill(m,holeSize, false); tri::UpdateTopology<MyMesh>::FaceFace(m); break;
00149 }
00150
00151 tri::UpdateFlags<MyMesh>::FaceBorderFromFF(m);
00152
00153 assert(tri::Clean<MyMesh>::IsFFAdjacencyConsistent(m));
00154
00155 printf("\nStart refinig...\n");
00156
00157
00158 MyMesh::VertexIterator vi;
00159 MyMesh::FaceIterator f;
00160 std::vector<MyMesh::FacePointer> vf;
00161 f = m.face.begin();
00162 f += indice;
00163 for(; f != m.face.end();++f)
00164 {
00165 if(!f->IsD())
00166 {
00167 f->SetS();
00168 }
00169 }
00170
00171 std::vector<MyMesh::FacePointer *> FPP;
00172 std::vector<MyMesh::FacePointer> added;
00173 std::vector<MyMesh::FacePointer>::iterator vfit;
00174 int i=1;
00175 printf("\n");
00176
00177 for(f = m.face.begin();f!=m.face.end();++f) if(!(*f).IsD())
00178 {
00179 if( f->IsS() )
00180 {
00181 f->V(0)->IsW();
00182 f->V(1)->IsW();
00183 f->V(2)->IsW();
00184 }
00185 else
00186 {
00187 f->V(0)->ClearW();
00188 f->V(1)->ClearW();
00189 f->V(2)->ClearW();
00190 }
00191 }
00192 BaseParameterClass pp;
00193 vcg::LocalOptimization<MyMesh> Fs(m,&pp);
00194 Fs.SetTargetMetric(0.0f);
00195 Fs.Init<MyDelaunayFlip >();
00196 Fs.DoOptimization();
00197
00198
00199 do
00200 {
00201 vf.clear();
00202 f = m.face.begin();
00203 f += indice;
00204 for(; f != m.face.end();++f)
00205 {
00206 if(f->IsS())
00207 {
00208 bool test= true;
00209 for(int ind =0;ind<3;++ind)
00210 f->V(ind)->InitIMark();
00211 test = (DoubleArea<MyMesh::FaceType>(*f)/2) > AVG;
00212 if(test)
00213 {
00214 vf.push_back(&(*f));
00215 }
00216 }
00217 }
00218
00219
00220 printf("\r Refining [%d] - > %d",i,int(vf.size()));
00221 i++;
00222
00223 FPP.clear();
00224 added.clear();
00225
00226 for(vfit = vf.begin(); vfit!=vf.end();++vfit)
00227 {
00228 FPP.push_back(&(*vfit));
00229 }
00230 int toadd= vf.size();
00231 MyMesh::FaceIterator f1,f2;
00232 f2 = tri::Allocator<MyMesh>::AddFaces(m,(toadd*2),FPP);
00233 MyMesh::VertexIterator vertp = tri::Allocator<MyMesh>::AddVertices(m,toadd);
00234 std::vector<MyMesh::FacePointer> added;
00235 added.reserve(toadd);
00236 vfit=vf.begin();
00237
00238 for(int i = 0; i<toadd;++i,f2++,vertp++)
00239 {
00240 f1=f2;
00241 f2++;
00242 TriSplit<MyMesh,CenterPointBarycenter<MyMesh> >::Apply(vf[i],&(*f1),&(*f2),&(*vertp),CenterPointBarycenter<MyMesh>() );
00243 f1->SetS();
00244 f2->SetS();
00245 for(int itr=0;itr<3;itr++)
00246 {
00247 f1->V(itr)->SetW();
00248 f2->V(itr)->SetW();
00249 }
00250 added.push_back( &(*f1) );
00251 added.push_back( &(*f2) );
00252 }
00253
00254 BaseParameterClass pp;
00255 vcg::LocalOptimization<MyMesh> FlippingSession(m,&pp);
00256 FlippingSession.SetTargetMetric(0.0f);
00257 FlippingSession.Init<MyDelaunayFlip >();
00258 FlippingSession.DoOptimization();
00259
00260 }while(!vf.empty());
00261
00262 vcg::LocalOptimization<MyMesh> Fiss(m,&pp);
00263 Fiss.SetTargetMetric(0.0f);
00264 Fiss.Init<MyDelaunayFlip >();
00265 Fiss.DoOptimization();
00266
00267
00268
00269 tri::io::ExporterPLY<MyMesh>::Save(m,"PreSmooth.ply",false);
00270
00271 int UBIT = MyMesh::VertexType::NewBitFlag();
00272 f = m.face.begin();
00273 f += indice;
00274 for(; f != m.face.end();++f)
00275 {
00276 if(f->IsS())
00277 {
00278 for(int ind =0;ind<3;++ind){
00279 if(NormalTest<MyMesh>(face::Pos<MyMesh::FaceType>(&(*f),ind )))
00280 {
00281 f->V(ind)->SetUserBit(UBIT);
00282 }
00283 }
00284 f->ClearS();
00285 }
00286 }
00287
00288 for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00289 {
00290 if( vi->IsUserBit(UBIT) )
00291 {
00292 (*vi).SetS();
00293 vi->ClearUserBit(UBIT);
00294 }
00295 }
00296
00297 tri::Smooth<MyMesh>::VertexCoordLaplacian(m,1,true);
00298
00299 printf("\nCompleted. Saving....\n");
00300
00301 tri::io::ExporterPLY<MyMesh>::Save(m,argv[4],false);
00302 return 0;
00303 }
00304