1 /****************************************************************************
2 * VCGLib                                                            o o     *
3 * Visual and Computer Graphics Library                            o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2004-2016                                           \/)\/    *
6 * Visual Computing Lab                                            /\/|      *
7 * ISTI - Italian National Research Council                           |      *
8 *                                                                    \      *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 
24 #include<vcg/space/triangle3.h>
25 #include<vcg/complex/complex.h>
26 #include<vcg/complex/algorithms/hole.h>
27 #include<vcg/complex/algorithms/local_optimization.h>
28 #include<vcg/complex/algorithms/local_optimization/tri_edge_flip.h>
29 #include<vcg/complex/algorithms/smooth.h>
30 #include<vcg/complex/algorithms/refine.h>
31 
32 // input output
33 #include <wrap/io_trimesh/import_ply.h>
34 #include <wrap/io_trimesh/export_ply.h>
35 
36 using namespace vcg;
37 using namespace std;
38 
39 class MyFace;
40 class MyVertex;
41 struct MyUsedTypes : public UsedTypes<	Use<MyVertex>		::AsVertexType,
42     Use<MyFace>			::AsFaceType>{};
43 
44 class MyVertex  : public Vertex< MyUsedTypes, vertex::Coord3f, vertex::BitFlags, vertex::Normal3f, vertex::Mark, vertex::Color4b >{};
45 class MyFace    : public Face  < MyUsedTypes, face::VertexRef,face::FFAdj, face::Mark, face::BitFlags, face::Normal3f> {};
46 
47 class MyMesh : public tri::TriMesh< vector<MyVertex>, vector<MyFace > >{};
48 
49 //Delaunay
50 class MyDelaunayFlip: public vcg::tri::TriEdgeFlip< MyMesh, MyDelaunayFlip > {
51 public:
52     typedef  vcg::tri::TriEdgeFlip< MyMesh,  MyDelaunayFlip > TEF;
MyDelaunayFlip(const TEF::PosType & p,int i,BaseParameterClass * pp)53     inline MyDelaunayFlip(  const TEF::PosType &p, int i,BaseParameterClass *pp) :TEF(p,i,pp){}
54 };
55 
callback(int percent,const char * str)56 bool callback(int percent, const char *str) {
57   cout << "str: " << str << " " << percent << "%\r";
58   return true;
59 }
60 
61 template <class MESH>
NormalTest(typename face::Pos<typename MESH::FaceType> pos)62 bool NormalTest(typename face::Pos<typename MESH::FaceType> pos)
63 {
64     //giro intorno al vertice e controllo le normali
65     typename MESH::ScalarType thr = 0.0f;
66         typename MESH::CoordType NdP = vcg::TriangleNormal<typename MESH::FaceType>(*pos.f);
67     typename MESH::CoordType tmp, oop, soglia = typename MESH::CoordType(thr,thr,thr);
68     face::Pos<typename MESH::FaceType> aux=pos;
69     do{
70         aux.FlipF();
71         aux.FlipE();
72                 oop = Abs(tmp - ::vcg::TriangleNormal<typename MESH::FaceType>(*pos.f));
73         if(oop < soglia )return false;
74     }while(aux != pos && !aux.IsBorder());
75 
76     return true;
77 }
78 
main(int argc,char ** argv)79 int main(int argc,char ** argv){
80 
81     if(argc<5)
82     {
83         printf(
84             "\n     HoleFilling (" __DATE__ ")\n"
85             "Visual Computing Group I.S.T.I. C.N.R.\n"
86       "Usage: trimesh_hole #algorithm #size filein.ply fileout.ply \n"
87             "#algorithm: \n"
88             " 1) Trivial Ear \n"
89             " 2) Minimum weight Ear \n"
90             " 3) Selfintersection Ear \n"
91             " 4) Minimum weight \n"
92             );
93         exit(0);
94     }
95 
96     int algorithm = atoi(argv[1]);
97     int holeSize  = atoi(argv[2]);
98     if(algorithm < 0 && algorithm > 4)
99     {
100     printf("Error in algorithm's selection %i\n",algorithm);
101         exit(0);
102     }
103 
104     MyMesh m;
105 
106     if(tri::io::ImporterPLY<MyMesh>::Open(m,argv[3])!=0)
107     {
108         printf("Error reading file  %s\n",argv[2]);
109         exit(0);
110     }
111 
112     //update the face-face topology
113     tri::UpdateTopology<MyMesh>::FaceFace(m);
114     tri::UpdateNormal<MyMesh>::PerVertexPerFace(m);
115     tri::UpdateFlags<MyMesh>::FaceBorderFromFF(m);
116   assert(tri::Clean<MyMesh>::IsFFAdjacencyConsistent(m));
117 
118     //compute the average of face area
119     float AVG,sumA=0.0f;
120     int numA=0,indice;
121     indice = m.face.size();
122     MyMesh::FaceIterator fi;
123     for(fi=m.face.begin();fi!=m.face.end();++fi)
124     {
125             sumA += DoubleArea(*fi)/2;
126             numA++;
127             for(int ind =0;ind<3;++ind)
128                 fi->V(ind)->InitIMark();
129     }
130     AVG=sumA/numA;
131 
132   //tri::Hole<MyMesh> holeFiller;
133     switch(algorithm)
134     {
135   case 1:			tri::Hole<MyMesh>::EarCuttingFill<tri::TrivialEar<MyMesh> >(m,holeSize,false);                	        break;
136   case 2:   	tri::Hole<MyMesh>::EarCuttingFill<tri::MinimumWeightEar< MyMesh> >(m,holeSize,false,callback);          break;
137   case 3: 		tri::Hole<MyMesh>::EarCuttingIntersectionFill<tri::SelfIntersectionEar< MyMesh> >(m,holeSize,false);		break;
138   case 4: 		tri::Hole<MyMesh>::MinimumWeightFill(m,holeSize, false); tri::UpdateTopology<MyMesh>::FaceFace(m);      break;
139     }
140 
141     tri::UpdateFlags<MyMesh>::FaceBorderFromFF(m);
142 
143   assert(tri::Clean<MyMesh>::IsFFAdjacencyConsistent(m));
144 
145   printf("\nStart refinig...\n");
146 
147 /*start refining */
148     MyMesh::VertexIterator vi;
149     MyMesh::FaceIterator f;
150     std::vector<MyMesh::FacePointer> vf;
151     f =  m.face.begin();
152     f += indice;
153     for(; f != m.face.end();++f)
154     {
155         if(!f->IsD())
156         {
157             f->SetS();
158         }
159     }
160 
161     std::vector<MyMesh::FacePointer *> FPP;
162     std::vector<MyMesh::FacePointer> added;
163     std::vector<MyMesh::FacePointer>::iterator vfit;
164     int i=1;
165     printf("\n");
166 
167     for(f =  m.face.begin();f!=m.face.end();++f) if(!(*f).IsD())
168     {
169         if( f->IsS() )
170         {
171             f->V(0)->IsW();
172             f->V(1)->IsW();
173             f->V(2)->IsW();
174         }
175         else
176         {
177             f->V(0)->ClearW();
178             f->V(1)->ClearW();
179             f->V(2)->ClearW();
180         }
181     }
182     BaseParameterClass pp;
183                 vcg::LocalOptimization<MyMesh> Fs(m,&pp);
184                 Fs.SetTargetMetric(0.0f);
185                 Fs.Init<MyDelaunayFlip >();
186                 Fs.DoOptimization();
187 
188 
189     do
190     {
191         vf.clear();
192         f =  m.face.begin();
193         f += indice;
194         for(; f != m.face.end();++f)
195         {
196             if(f->IsS())
197             {
198                 bool test= true;
199                 for(int ind =0;ind<3;++ind)
200                     f->V(ind)->InitIMark();
201                 test = (DoubleArea<MyMesh::FaceType>(*f)/2) > AVG;
202                 if(test)
203                 {
204                     vf.push_back(&(*f));
205                 }
206             }
207         }
208 
209         //info print
210     printf("\r Refining [%d] - > %d",i,int(vf.size()));
211         i++;
212 
213         FPP.clear();
214         added.clear();
215 
216         for(vfit = vf.begin(); vfit!=vf.end();++vfit)
217         {
218             FPP.push_back(&(*vfit));
219         }
220         int toadd= vf.size();
221         MyMesh::FaceIterator f1,f2;
222         f2 = tri::Allocator<MyMesh>::AddFaces(m,(toadd*2),FPP);
223         MyMesh::VertexIterator vertp = tri::Allocator<MyMesh>::AddVertices(m,toadd);
224         std::vector<MyMesh::FacePointer> added;
225         added.reserve(toadd);
226         vfit=vf.begin();
227 
228         for(int i = 0; i<toadd;++i,f2++,vertp++)
229         {
230             f1=f2;
231             f2++;
232             TriSplit<MyMesh,CenterPointBarycenter<MyMesh> >::Apply(vf[i],&(*f1),&(*f2),&(*vertp),CenterPointBarycenter<MyMesh>() );
233             f1->SetS();
234             f2->SetS();
235             for(int itr=0;itr<3;itr++)
236             {
237                 f1->V(itr)->SetW();
238                 f2->V(itr)->SetW();
239             }
240             added.push_back( &(*f1) );
241             added.push_back( &(*f2) );
242         }
243 
244         BaseParameterClass pp;
245         vcg::LocalOptimization<MyMesh> FlippingSession(m,&pp);
246         FlippingSession.SetTargetMetric(0.0f);
247         FlippingSession.Init<MyDelaunayFlip >();
248         FlippingSession.DoOptimization();
249 
250     }while(!vf.empty());
251 
252     vcg::LocalOptimization<MyMesh> Fiss(m,&pp);
253     Fiss.SetTargetMetric(0.0f);
254     Fiss.Init<MyDelaunayFlip >();
255     Fiss.DoOptimization();
256 
257 /*end refining */
258 
259     tri::io::ExporterPLY<MyMesh>::Save(m,"PreSmooth.ply",false);
260 
261     int UBIT = MyMesh::VertexType::NewBitFlag();
262     f =  m.face.begin();
263     f += indice;
264     for(; f != m.face.end();++f)
265     {
266         if(f->IsS())
267         {
268             for(int ind =0;ind<3;++ind){
269                 if(NormalTest<MyMesh>(face::Pos<MyMesh::FaceType>(&(*f),ind )))
270                 {
271                     f->V(ind)->SetUserBit(UBIT);
272                 }
273             }
274             f->ClearS();
275         }
276     }
277 
278     for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
279     {
280         if( vi->IsUserBit(UBIT) )
281         {
282             (*vi).SetS();
283             vi->ClearUserBit(UBIT);
284         }
285     }
286 
287     tri::Smooth<MyMesh>::VertexCoordLaplacian(m,1,true);
288 
289     printf("\nCompleted. Saving....\n");
290 
291   tri::io::ExporterPLY<MyMesh>::Save(m,argv[4],false);
292     return 0;
293 }
294 
295