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