~ubuntu-branches/ubuntu/vivid/meshlab/vivid

« back to all changes in this revision

Viewing changes to meshlab/src/meshlabplugins/filter_isoparametrization/dual_coord_optimization.h

  • Committer: Bazaar Package Importer
  • Author(s): Teemu Ikonen
  • Date: 2009-10-08 16:40:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20091008164041-0c2ealqv8b8uc20c
Tags: 1.2.2-1
* New upstream version
* Do not build filter_isoparametrization because liblevmar dependency
  is not (yet) in Debian
* Fix compilation with gcc-4.4, thanks to Jonathan Liu for the patch
  (closes: #539544)
* rules: Add compiler variables to the qmake call (for testing with new
  GCC versions)
* io_3ds.pro: Make LIBS and INCLUDEPATH point to Debian version of lib3ds
* io_epoch.pro: Make LIBS point to Debian version of libbz2
* control:
  - Move Homepage URL to the source package section
  - Update to standards-version 3.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef DUAL_OPTIMIZER
 
2
#define DUAL_OPTIMIZER
 
3
#include <wrap/callback.h>
 
4
 
 
5
template <class MeshType>
 
6
class BaryOptimizatorDual
 
7
{
 
8
        typedef typename MeshType::VertexType VertexType;
 
9
        typedef typename MeshType::FaceType   FaceType;
 
10
        typedef typename MeshType::CoordType  CoordType;
 
11
        typedef typename MeshType::ScalarType ScalarType;
 
12
        typedef typename vcg::tri::AreaPreservingTexCoordOptimization<MeshType> OptType;
 
13
        //typedef typename vcg::tri::MIPSTexCoordOptimization<MeshType> OptType1;
 
14
 
 
15
 
 
16
public:
 
17
        struct param_domain{
 
18
                MeshType *domain;
 
19
                std::vector<FaceType*> ordered_faces;
 
20
        };
 
21
 
 
22
        //OptType *optimizer;
 
23
        
 
24
        ///set of star meshes to optimize barycentryc coords locally
 
25
        std::vector<param_domain> star_meshes;
 
26
        std::vector<param_domain> diamond_meshes;
 
27
        std::vector<param_domain> face_meshes;
 
28
        ///structures for the optimization
 
29
        std::vector<MeshType*> HRES_meshes;
 
30
        std::vector<std::vector<VertexType*> > Ord_HVert;
 
31
        /*std::vector<std::vector<VertexType*> > HVert;*/
 
32
 
 
33
        /*///subdomain in witch a vertex falls into
 
34
        std::vector<param_domain*> subdomain;*/
 
35
 
 
36
        ///map fo correspondences between domain & entities
 
37
        //std::map<VertexType*,param_domain*> starMap;
 
38
        //std::map<std::pair<FaceType*,FaceType*>,param_domain*> diamondMap;
 
39
        //std::map<FaceType*,param_domain*> faceMap;
 
40
 
 
41
        ///hight resolution mesh and domain mesh
 
42
        MeshType *domain;
 
43
        MeshType *h_res_mesh;
 
44
        
 
45
        ///initialize star parametrization
 
46
        void InitStarEquilateral()//const ScalarType &average_area=1)
 
47
        {
 
48
                ///for each vertex
 
49
                int index=0;
 
50
                for (unsigned int i=0;i<domain->vert.size();i++)
 
51
                {
 
52
                        if (!(domain->vert[i].IsD()))
 
53
                        {
 
54
                                std::vector<VertexType*> starCenter;
 
55
                                starCenter.push_back(&domain->vert[i]);
 
56
 
 
57
                                star_meshes[index].domain=new MeshType();
 
58
 
 
59
                                ///create star
 
60
                                CreateMeshVertexStar(starCenter,star_meshes[index].ordered_faces,*star_meshes[index].domain);
 
61
                                
 
62
                                ///and parametrize it
 
63
                                ParametrizeStarEquilateral<MeshType>(*star_meshes[index].domain,1.0);
 
64
 
 
65
                                /*///insert in search structure
 
66
                                starMap.insert(std::pair<VertexType*,param_domain*>(&domain->vert[i],&star_meshes[index]));*/
 
67
 
 
68
                                index++;
 
69
                        }
 
70
                }               
 
71
        }
 
72
        
 
73
        void InitDiamondEquilateral(const ScalarType &edge_len=1.0)
 
74
        {
 
75
                
 
76
                ///for each vertex
 
77
                int index=0;
 
78
                for (unsigned int i=0;i<domain->face.size();i++)
 
79
                {
 
80
                        if (!(domain->face[i].IsD()))
 
81
                        {
 
82
                                FaceType *f0=&domain->face[i];
 
83
                                //for each edge
 
84
                                for (int j=0;j<3;j++)
 
85
                                {
 
86
                                        FaceType * f1=f0->FFp(j);
 
87
                                        if (f1<f0)
 
88
                                        {
 
89
                                                ///add to domain map
 
90
                                                std::pair<FaceType*,FaceType*> entry=std::pair<FaceType*,FaceType*>(f0,f1);
 
91
                                                /*diamondMap.insert(std::pair<std::pair<FaceType*,FaceType*> ,param_domain*>(entry,&diamond_meshes[index]));*/
 
92
                                                ///end domain mapping
 
93
 
 
94
                                                int num0=j;
 
95
                                                int num1=f0->FFi(j);
 
96
 
 
97
                                                ///copy the mesh
 
98
                                                std::vector<FaceType*> faces;
 
99
                                                faces.push_back(f0);
 
100
                                                faces.push_back(f1);
 
101
 
 
102
                                                diamond_meshes[index].domain=new MeshType();
 
103
 
 
104
                                                ///create a copy of the mesh
 
105
                                                std::vector<VertexType*> orderedVertex;
 
106
                                                CopyMeshFromFaces<MeshType>(faces,orderedVertex,*diamond_meshes[index].domain);
 
107
                                                UpdateTopologies<MeshType>(diamond_meshes[index].domain);
 
108
 
 
109
                                                ///set other components
 
110
                                                diamond_meshes[index].ordered_faces.resize(2);
 
111
                                                diamond_meshes[index].ordered_faces[0]=f0;
 
112
                                                diamond_meshes[index].ordered_faces[1]=f1;
 
113
                                                ///parametrize locally
 
114
                                                ParametrizeDiamondEquilateral<MeshType>(*diamond_meshes[index].domain,num0,num1,edge_len);
 
115
                                        
 
116
                                                index++;
 
117
                                        }
 
118
                                }
 
119
                        }
 
120
                }
 
121
        }
 
122
        
 
123
 
 
124
        void InitFaceEquilateral(const ScalarType &edge_len=1)
 
125
        {
 
126
                ///for each vertex
 
127
                int index=0;
 
128
                for (unsigned int i=0;i<domain->face.size();i++)
 
129
                {
 
130
                        if (!(domain->face[i].IsD()))
 
131
                        {
 
132
                                FaceType *f0=&domain->face[i];
 
133
 
 
134
                                std::vector<FaceType*> faces;
 
135
                                faces.push_back(f0);
 
136
 
 
137
                                ///create the mesh
 
138
                                face_meshes[index].domain=new MeshType();
 
139
                                std::vector<VertexType*> orderedVertex;
 
140
                                CopyMeshFromFaces<MeshType>(faces,orderedVertex,*face_meshes[index].domain);
 
141
 
 
142
                                assert(face_meshes[index].domain->vn==3);
 
143
                                assert(face_meshes[index].domain->fn==1);
 
144
 
 
145
                                ///initialize auxiliary structures
 
146
                                face_meshes[index].ordered_faces.resize(1);
 
147
                                face_meshes[index].ordered_faces[0]=f0;
 
148
                                
 
149
                                ///parametrize it
 
150
                                ParametrizeFaceEquilateral<MeshType>(*face_meshes[index].domain,edge_len);
 
151
                                ///add to search structures
 
152
                                /*faceMap.insert(std::pair<FaceType*,param_domain*>(f0,&face_meshes[index]));*/
 
153
                                index++;
 
154
                        }
 
155
                }
 
156
        }
 
157
 
 
158
///given a point and a face return the half-star in witch it falls
 
159
int getVertexStar(const CoordType &point,FaceType *f)
 
160
{
 
161
        CoordType edge0=(f->P(0)+f->P(1))/2.0;
 
162
        CoordType edge1=(f->P(1)+f->P(2))/2.0;
 
163
        CoordType edge2=(f->P(2)+f->P(0))/2.0;
 
164
        CoordType Center=(f->P(0)+f->P(1)+f->P(2))/3.0;
 
165
        CoordType vect0=edge0-point;
 
166
        CoordType vect1=Center-point;
 
167
        CoordType vect2=edge2-point;
 
168
        CoordType Norm=f->N();
 
169
        ScalarType in0=(vect0^vect1)*Norm;
 
170
        ScalarType in1=(vect1^vect2)*Norm;
 
171
        if ((in0>=0)&&(in1>=0))
 
172
                return 0;
 
173
 
 
174
        vect0=edge0-point;
 
175
        vect1=Center-point;
 
176
        vect2=edge1-point;
 
177
        in0=(vect1^vect0)*Norm;
 
178
        in1=(vect2^vect1)*Norm;
 
179
        if ((in0>=0)&&(in1>=0))
 
180
                return 1;
 
181
 
 
182
        vect0=edge1-point;
 
183
        vect1=Center-point;
 
184
        vect2=edge2-point;
 
185
        in0=(vect1^vect0)*Norm;
 
186
        in1=(vect2^vect1)*Norm;
 
187
        assert((in0>=0)&&(in1>=0));
 
188
        return 2;
 
189
}
 
190
 
 
191
///given a point and a face return the half-diamond edge index in witch it falls
 
192
int getEdgeDiamond(const CoordType &point,FaceType *f)
 
193
{
 
194
        CoordType Center=(f->P(0)+f->P(1)+f->P(2))/3.0;
 
195
        CoordType vect0=f->P(1)-point;
 
196
        CoordType vect1=Center-point;
 
197
        CoordType vect2=f->P(0)-point;
 
198
        CoordType Norm=f->N();
 
199
        ScalarType in0=(vect0^vect1)*Norm;
 
200
        ScalarType in1=(vect1^vect2)*Norm;
 
201
        if ((in0>=0)&&(in1>=0))
 
202
                return 0;
 
203
 
 
204
        vect0=f->P(2)-point;
 
205
        vect1=Center-point;
 
206
        vect2=f->P(1)-point;
 
207
        in0=(vect0^vect1)*Norm;
 
208
        in1=(vect1^vect2)*Norm;
 
209
        if ((in0>=0)&&(in1>=0))
 
210
                return 1;
 
211
 
 
212
        vect0=f->P(0)-point;
 
213
        vect1=Center-point;
 
214
        vect2=f->P(2)-point;
 
215
        in0=(vect0^vect1)*Norm;
 
216
        in1=(vect1^vect2)*Norm;
 
217
        assert((in0>=0)&&(in1>=0));
 
218
        return 2;
 
219
}
 
220
 
 
221
 
 
222
///initialize Star Submeshes
 
223
void InitStarSubdivision()
 
224
{
 
225
 
 
226
        int index=0;
 
227
        HRES_meshes.clear();
 
228
        Ord_HVert.clear();
 
229
        ///initialilze vector of meshes
 
230
        HRES_meshes.resize(star_meshes.size());
 
231
        Ord_HVert.resize(star_meshes.size());
 
232
        /*HVert.resize(star_meshes.size());*/
 
233
        for (unsigned int i=0;i<HRES_meshes.size();i++)
 
234
                HRES_meshes[i]=new MeshType();
 
235
 
 
236
        ///for each vertex of base domain
 
237
        for (unsigned int i=0;i<domain->vert.size();i++)
 
238
        {
 
239
                VertexType *center=&domain->vert[i];
 
240
                if (!center->IsD())
 
241
                {
 
242
                        ///copy current parametrization of star 
 
243
                        for (unsigned int k=0;k<star_meshes[index].ordered_faces.size();k++)
 
244
                        {
 
245
                                FaceType *param=&star_meshes[index].domain->face[k];
 
246
                                FaceType *original=star_meshes[index].ordered_faces[k];
 
247
                                for (int v=0;v<3;v++)
 
248
                                        original->V(v)->T().P()=param->V(v)->T().P();
 
249
                        }
 
250
 
 
251
                        ///get h res vertex on faces composing the star
 
252
                        std::vector<VertexType*> Hres,inDomain;
 
253
                        getHresVertex<FaceType>(star_meshes[index].ordered_faces,Hres);
 
254
 
 
255
                        ///find out the vertices falling in the substar
 
256
                        /*HVert[index].reserve(Hres.size()/2);*/
 
257
                        for (unsigned int k=0;k<Hres.size();k++)
 
258
                        {
 
259
                                VertexType* chosen;
 
260
                                VertexType* test=Hres[k];
 
261
                                CoordType proj=Warp(test);
 
262
                                FaceType * father=test->father;
 
263
                                CoordType bary=test->Bary;
 
264
                                ///get index of half-star
 
265
                                int index=getVertexStar(proj,father);
 
266
                                chosen=father->V(index);
 
267
                                ///if is part of current half star
 
268
                                if (chosen==center)
 
269
                                {
 
270
                                        inDomain.push_back(test);
 
271
                                        ///parametrize it
 
272
                                        GetUV<MeshType>(father,bary,test->T().U(),test->T().V());
 
273
                                }
 
274
                        }
 
275
                        ///create Hres mesh already parametrized
 
276
                        std::vector<FaceType*> OrderedFaces;
 
277
                        CopyMeshFromVertices<MeshType>(inDomain,Ord_HVert[index],OrderedFaces,*HRES_meshes[index]);
 
278
                        index++;
 
279
                }
 
280
        }
 
281
}
 
282
 
 
283
/////subdivide the mesh into Star subdomain
 
284
//void InitStarSubdivision()
 
285
//{
 
286
//      
 
287
//      vcg::SimpleTempData<typename MeshType::VertContainer, param_domain* > domainVert(h_res_mesh->vert);
 
288
//
 
289
//      for (int i=0;i<h_res_mesh->vert.size();i++)
 
290
//      {
 
291
//              assert(!h_res_mesh->vert[i].IsD());
 
292
//              ///get father and bary coordinate
 
293
//              FaceType *father=h_res_mesh->vert[i].father;
 
294
//              CoordType bary=h_res_mesh->vert[i].Bary;
 
295
//
 
296
//              ///then get the substar falling into
 
297
//
 
298
//              ///get nearest vertex
 
299
//              VertexType* chosen;
 
300
//              CoordType proj=Warp(&h_res_mesh->vert[i]);              
 
301
//              int index=getVertexStar(proj,father);
 
302
//              ///chosen is the half-star center
 
303
//              chosen=father->V(index);
 
304
//
 
305
//              ///then get corresponding half-star reference parametrized mesh
 
306
//              std::map<VertexType*,param_domain*>::iterator iteStar=starMap.find(chosen);
 
307
//              assert(iteStar!=starMap.end());
 
308
//              ///end parametrize it using that star
 
309
//
 
310
//              ///get corresponding parametrizad face
 
311
//              param_domain* pdomain=(*iteStar).second;
 
312
//              FaceType *param_face=NULL;
 
313
//              int f=0;
 
314
//              while ((f<pdomain->ordered_faces.size())&&(param_face==NULL))
 
315
//              {
 
316
//                      if (pdomain->ordered_faces[f]==father)
 
317
//                              param_face=&pdomain->domain.face[f];
 
318
//                      f++;
 
319
//              }
 
320
//              assert(param_face!=NULL);
 
321
//              ///then translate barycentric into UV over the star
 
322
//              ScalarType u,v;
 
323
//              GetUV<MeshType>(param_face,bary,u,v);
 
324
//
 
325
//              ///set UV values
 
326
//              h_res_mesh->vert[i].T().U()=u;
 
327
//              h_res_mesh->vert[i].T().V()=v;
 
328
//              h_res_mesh->vert[i].ClearS();
 
329
//
 
330
//              ///set corresponding domain
 
331
//              domainVert[i]=pdomain;
 
332
//              subdomain[i]=pdomain;
 
333
//      }
 
334
//
 
335
//      ///then set as selected border vertices
 
336
//      for (int i=0;i<h_res_mesh->face.size();i++)
 
337
//      {
 
338
//              VertexType *v0=h_res_mesh->face[i].V(0);
 
339
//              VertexType *v1=h_res_mesh->face[i].V(1);
 
340
//              VertexType *v2=h_res_mesh->face[i].V(2);
 
341
//              if (!((domainVert[v0]==domainVert[v1])&&(domainVert[v1]==domainVert[v2])))
 
342
//              {
 
343
//                      v0->SetS();
 
344
//                      v1->SetS();
 
345
//                      v2->SetS();
 
346
//              }
 
347
//      }
 
348
//}
 
349
 
 
350
 
 
351
///initialize Star Submeshes
 
352
void InitDiamondSubdivision()
 
353
{
 
354
        
 
355
        int index=0;
 
356
        HRES_meshes.clear();
 
357
        Ord_HVert.clear();
 
358
        ///initialilze vector of meshes
 
359
        HRES_meshes.resize(diamond_meshes.size());
 
360
        Ord_HVert.resize(diamond_meshes.size());
 
361
        /*HVert.resize(star_meshes.size());*/
 
362
        for (unsigned int i=0;i<HRES_meshes.size();i++)
 
363
                HRES_meshes[i]=new MeshType();
 
364
 
 
365
        ///for each edge of base domain
 
366
        for (unsigned int i=0;i<domain->face.size();i++)
 
367
        {
 
368
                FaceType *f0=&domain->face[i];
 
369
                if (f0->IsD())
 
370
                        break;
 
371
                //for each edge
 
372
                for (int eNum=0;eNum<3;eNum++)
 
373
                {
 
374
                        FaceType * f1=f0->FFp(eNum);
 
375
                        if (f1<f0)
 
376
                        {
 
377
                                ///copy current parametrization of diamond 
 
378
                                for (unsigned int k=0;k<diamond_meshes[index].ordered_faces.size();k++)
 
379
                                {
 
380
                                        FaceType *param=&diamond_meshes[index].domain->face[k];
 
381
                                        FaceType *original=diamond_meshes[index].ordered_faces[k];
 
382
                                        for (int v=0;v<3;v++)
 
383
                                                original->V(v)->T().P()=param->V(v)->T().P();
 
384
                                }
 
385
 
 
386
                                ///get h res vertex on faces composing the diamond
 
387
                                std::vector<VertexType*> Hres,inDomain;
 
388
                                getHresVertex<FaceType>(diamond_meshes[index].ordered_faces,Hres);
 
389
 
 
390
                                ///find out the vertices falling in the half-diamond
 
391
                                /*HVert[index].reserve(Hres.size()/2);*/
 
392
                                for (unsigned int k=0;k<Hres.size();k++)
 
393
                                {
 
394
                                        //VertexType* chosen;
 
395
                                        VertexType* test=Hres[k];
 
396
                                        CoordType proj=Warp(test);
 
397
                                        FaceType * father=test->father;
 
398
                                        CoordType bary=test->Bary;
 
399
                                        ///get index of half-star
 
400
                                        int index=getEdgeDiamond(proj,father);
 
401
                                        ///if is part of current half star
 
402
                                        if (index==eNum)
 
403
                                        {
 
404
                                                inDomain.push_back(test);
 
405
                                                ///parametrize it
 
406
                                                GetUV<MeshType>(father,bary,test->T().U(),test->T().V());
 
407
                                        }
 
408
                                }
 
409
                                ///create Hres mesh already parametrized
 
410
                                std::vector<FaceType*> OrderedFaces;
 
411
                                CopyMeshFromVertices<MeshType>(inDomain,Ord_HVert[index],OrderedFaces,*HRES_meshes[index]);
 
412
                                index++;
 
413
                        }
 
414
                }
 
415
        }
 
416
}
 
417
 
 
418
/////subdivide the mesh into subdomains
 
419
//void InitDiamondSubdivision()
 
420
//{
 
421
//      
 
422
//      vcg::SimpleTempData<typename MeshType::VertContainer, param_domain* > domainVert(h_res_mesh->vert);
 
423
//
 
424
//      for (int i=0;i<h_res_mesh->vert.size();i++)
 
425
//      {
 
426
//              /*h_res_mesh->vert[i].C()=vcg::Color4b(255,255,255,255);*/
 
427
//
 
428
//              assert(!h_res_mesh->vert[i].IsD());
 
429
//              ///get father and bary coordinate
 
430
//              FaceType *father=h_res_mesh->vert[i].father;
 
431
//              CoordType bary=h_res_mesh->vert[i].Bary;
 
432
//
 
433
//              ///get nearest edge
 
434
//              int chosen;
 
435
//              CoordType proj=Warp(&h_res_mesh->vert[i]);
 
436
//              
 
437
//              chosen=getEdgeDiamond(proj,father);
 
438
//              ///then get corresponding star
 
439
//              FaceType *fadj=father->FFp(chosen);
 
440
//              FaceType *f0=(father>fadj)? father:fadj;
 
441
//              FaceType *f1=(father<fadj)? father:fadj;
 
442
//
 
443
//              std::pair<FaceType*,FaceType*> keyF=std::pair<FaceType*,FaceType*>(f0,f1);
 
444
//              std::map<std::pair<FaceType*,FaceType*> ,param_domain*>::iterator iteDiam=diamondMap.find(keyF);
 
445
//              assert(iteDiam!=diamondMap.end());
 
446
//
 
447
//              ///end parametrize it using that star
 
448
//              param_domain* pdomain=(*iteDiam).second;
 
449
//              FaceType *param_face=NULL;
 
450
//              int f=0;
 
451
//              while ((f<pdomain->ordered_faces.size())&&(param_face==NULL))
 
452
//              {
 
453
//                      if (pdomain->ordered_faces[f]==father)
 
454
//                              param_face=&pdomain->domain.face[f];
 
455
//                      f++;
 
456
//              }
 
457
//              assert(param_face!=NULL);
 
458
//              ///then translate barycentric into UV over the star
 
459
//              ScalarType u,v;
 
460
//              GetUV<MeshType>(param_face,bary,u,v);
 
461
//
 
462
//              ///set UV values
 
463
//              h_res_mesh->vert[i].T().U()=u;
 
464
//              h_res_mesh->vert[i].T().V()=v;
 
465
//              h_res_mesh->vert[i].ClearS();
 
466
//
 
467
//              ///set corresponding domain
 
468
//              domainVert[i]=pdomain;
 
469
//              subdomain[i]=pdomain;
 
470
//      }
 
471
//
 
472
//      ///then set as selected border vertices
 
473
//      for (int i=0;i<h_res_mesh->face.size();i++)
 
474
//      {
 
475
//              VertexType *v0=h_res_mesh->face[i].V(0);
 
476
//              VertexType *v1=h_res_mesh->face[i].V(1);
 
477
//              VertexType *v2=h_res_mesh->face[i].V(2);
 
478
//              if (!((domainVert[v0]==domainVert[v1])&&(domainVert[v1]==domainVert[v2])))
 
479
//              {
 
480
//                      v0->SetS();
 
481
//                      v1->SetS();
 
482
//                      v2->SetS();
 
483
//              }
 
484
//      }
 
485
//}
 
486
 
 
487
///initialize Star Submeshes
 
488
void InitFaceSubdivision()
 
489
{
 
490
 
 
491
        int index=0;
 
492
        HRES_meshes.clear();
 
493
        Ord_HVert.clear();
 
494
        ///initialilze vector of meshes
 
495
        HRES_meshes.resize(face_meshes.size());
 
496
        Ord_HVert.resize(face_meshes.size());
 
497
 
 
498
        for (unsigned int i=0;i<HRES_meshes.size();i++)
 
499
                HRES_meshes[i]=new MeshType();
 
500
 
 
501
        ///for each face of base domain
 
502
        for (unsigned int i=0;i<domain->face.size();i++)
 
503
        {
 
504
                FaceType *f0=&domain->face[i];
 
505
                if (f0->IsD())
 
506
                        break;
 
507
                ///copy current parametrization of face 
 
508
                FaceType *param=&face_meshes[index].domain->face[0];
 
509
                FaceType *original=face_meshes[index].ordered_faces[0];
 
510
 
 
511
                assert(face_meshes[index].domain->vn==3);
 
512
                assert(face_meshes[index].domain->fn==1);
 
513
                assert(face_meshes[index].ordered_faces.size()==1);
 
514
                assert(original==f0);
 
515
 
 
516
                for (int v=0;v<3;v++)
 
517
                        original->V(v)->T().P()=param->V(v)->T().P();
 
518
 
 
519
                ///get h res vertex on faces composing the diamond
 
520
                std::vector<VertexType*> inDomain;
 
521
                getHresVertex<FaceType>(face_meshes[index].ordered_faces,inDomain);
 
522
 
 
523
                ///transform in UV
 
524
                for (unsigned int k=0;k<inDomain.size();k++)
 
525
                {
 
526
                        VertexType* test=inDomain[k];
 
527
                        FaceType * father=test->father;
 
528
                        assert(father==f0);
 
529
                        CoordType bary=test->Bary;
 
530
                        GetUV<MeshType>(father,bary,test->T().U(),test->T().V());
 
531
                }
 
532
                ///create Hres mesh already parametrized
 
533
                std::vector<FaceType*> OrderedFaces;
 
534
                CopyMeshFromVertices<MeshType>(inDomain,Ord_HVert[index],OrderedFaces,*HRES_meshes[index]);
 
535
                index++;
 
536
        }
 
537
 }
 
538
 
 
539
/////subdivide the mesh into subdomains
 
540
//void InitFaceSubdivision()
 
541
//{
 
542
//      
 
543
//      vcg::SimpleTempData<typename MeshType::VertContainer, param_domain* > domainVert(h_res_mesh->vert);
 
544
//
 
545
//      for (int i=0;i<h_res_mesh->vert.size();i++)
 
546
//      {
 
547
//      
 
548
//              assert(!h_res_mesh->vert[i].IsD());
 
549
//              ///get father and bary coordinate
 
550
//              FaceType *father=h_res_mesh->vert[i].father;
 
551
//              CoordType bary=h_res_mesh->vert[i].Bary;
 
552
//
 
553
//              std::map<FaceType*,param_domain*>::iterator iteFace=faceMap.find(father);
 
554
//              assert(iteFace!=faceMap.end());
 
555
//
 
556
//              ///end parametrize it using that star
 
557
//              param_domain* pdomain=(*iteFace).second;
 
558
//              FaceType *param_face=&pdomain->domain.face[0];
 
559
//              assert(father==pdomain->ordered_faces[0]);
 
560
//
 
561
//              ///then translate barycentric into UV over the star
 
562
//              ScalarType u,v;
 
563
//              GetUV<MeshType>(param_face,bary,u,v);
 
564
//
 
565
//              ///set UV values
 
566
//              h_res_mesh->vert[i].T().U()=u;
 
567
//              h_res_mesh->vert[i].T().V()=v;
 
568
//              h_res_mesh->vert[i].ClearS();
 
569
//
 
570
//              ///set corresponding domain
 
571
//              domainVert[i]=pdomain;
 
572
//              subdomain[i]=pdomain;
 
573
//      }
 
574
//
 
575
//      ///then set as selected border vertices
 
576
//      for (int i=0;i<h_res_mesh->face.size();i++)
 
577
//      {
 
578
//              VertexType *v0=h_res_mesh->face[i].V(0);
 
579
//              VertexType *v1=h_res_mesh->face[i].V(1);
 
580
//              VertexType *v2=h_res_mesh->face[i].V(2);
 
581
//              if (!((domainVert[v0]==domainVert[v1])&&(domainVert[v1]==domainVert[v2])))
 
582
//              {
 
583
//                      v0->SetS();
 
584
//                      v1->SetS();
 
585
//                      v2->SetS();
 
586
//              }
 
587
//      }
 
588
//}
 
589
 
 
590
//void GetDomainHVert(param_domain*  domain,std::vector<VertexType*> &HresVert)
 
591
//{
 
592
//      HresVert.clear();
 
593
//      for (int i=0;i<h_res_mesh->vert.size();i++)
 
594
//              if (subdomain[i]==domain)
 
595
//                      HresVert.push_back(&h_res_mesh->vert[i]);
 
596
//}
 
597
 
 
598
////test current domains and unfold when is necessary and needed
 
599
//bool UnfoldDomain()
 
600
//{
 
601
//      std::set<param_domain*> folded_domains;
 
602
//
 
603
//      ///set all vertices as non-visited
 
604
//      for (int i=0;i<h_res_mesh->vert.size();i++)
 
605
//              h_res_mesh->vert[i].ClearV();
 
606
//
 
607
//      ///collect folded vertices
 
608
//      bool folded=false;
 
609
//      for (int i=0;i<h_res_mesh->face.size();i++)
 
610
//      {
 
611
//              if (!(h_res_mesh->face[i].V(0)->IsS()&&
 
612
//                      h_res_mesh->face[i].V(1)->IsS()&&
 
613
//                      h_res_mesh->face[i].V(2)->IsS()))
 
614
//              {
 
615
//                      FaceType *f=&h_res_mesh->face[i];
 
616
//                      vcg::Point2<ScalarType> tex0=vcg::Point2<ScalarType>(f->V(0)->T().U(),f->V(0)->T().V());
 
617
//                      vcg::Point2<ScalarType> tex1=vcg::Point2<ScalarType>(f->V(1)->T().U(),f->V(1)->T().V());
 
618
//                      vcg::Point2<ScalarType> tex2=vcg::Point2<ScalarType>(f->V(2)->T().U(),f->V(2)->T().V());
 
619
//                      vcg::Triangle2<MeshType::ScalarType> t2d=vcg::Triangle2<MeshType::ScalarType>(tex0,tex1,tex2);
 
620
//                      ScalarType area=(tex1-tex0)^(tex2-tex0);
 
621
//                      if (area<0)
 
622
//                      {
 
623
//                              h_res_mesh->face[i].V(0)->SetV();
 
624
//                              h_res_mesh->face[i].V(1)->SetV();
 
625
//                              h_res_mesh->face[i].V(2)->SetV();
 
626
//                              folded=true;
 
627
//                      }
 
628
//              }
 
629
//      }
 
630
//
 
631
//      if (!folded)
 
632
//      {
 
633
//              //printf("nothing to unfold\n");
 
634
//              return true;
 
635
//      }
 
636
//
 
637
//      ///collect all domains in wich needed optimization
 
638
//      for (int i=0;i<h_res_mesh->vert.size();i++)
 
639
//              if (h_res_mesh->vert[i].IsV())
 
640
//                      folded_domains.insert(subdomain[i]);
 
641
//
 
642
//      ///clear flags
 
643
//      for (int i=0;i<h_res_mesh->vert.size();i++)
 
644
//              h_res_mesh->vert[i].ClearV();
 
645
//
 
646
//      ///for each one try to unfold
 
647
//      std::set<param_domain*>::iterator iteParam;
 
648
//      for (iteParam=folded_domains.begin();iteParam!=folded_domains.end();iteParam++)
 
649
//      {
 
650
//              std::vector<VertexType*> HresVert;
 
651
//              std::vector<VertexType*> ordVert;
 
652
//              //HresVert.clear();
 
653
//              ///get h resolution vertex
 
654
//              MeshType folded;
 
655
//              //getHresVertex<FaceType>((*iteParam)->ordered_faces,HresVert);*/
 
656
//              /*for (int i=0;i<h_res_mesh->vert.size();i++)
 
657
//                      if (subdomain[i]==(*iteParam))
 
658
//                              HresVert.push_back(&h_res_mesh->vert[i]);*/
 
659
//
 
660
//              GetDomainHVert((*iteParam),HresVert);
 
661
//
 
662
//              CopyMeshFromVertices<MeshType>(HresVert,ordVert,folded);
 
663
//              //bool done=true;
 
664
//              bool done=UnFold<MeshType>(folded,(*iteParam)->ordered_faces.size());
 
665
//              ///copy back values
 
666
//              
 
667
//              if (done)
 
668
//              {
 
669
//                      for (int i=0;i<folded.vert.size();i++)
 
670
//                              ordVert[i]->T().P()=folded.vert[i].T().P();
 
671
//              }
 
672
//      }
 
673
//      return true;
 
674
//}
 
675
 
 
676
//void MinimizeStep(char *phasename,
 
677
//                                const ScalarType &conv_interval=0.00001,
 
678
//                                const int &max_step=500)
 
679
//{
 
680
//      //////statistics
 
681
//      UnfoldDomain();
 
682
//      int opt_type=0;
 
683
//      std::vector<CoordType> oldPos;
 
684
//      std::vector<FaceType*> oldFather;
 
685
//      oldPos.resize(h_res_mesh->vert.size());
 
686
//      oldFather.resize(h_res_mesh->vert.size());
 
687
//
 
688
//      for (int i=0;i<h_res_mesh->vert.size();i++)
 
689
//      {
 
690
//              oldPos[i]=h_res_mesh->vert[i].Bary;
 
691
//              oldFather[i]=h_res_mesh->vert[i].father;
 
692
//      }
 
693
//      
 
694
//
 
695
//      ///fix selected vertices 
 
696
//      optimizer[0]->SetNothingAsFixed();
 
697
//      for (int i=0;i<h_res_mesh->vert.size();i++)
 
698
//              if (h_res_mesh->vert[i].IsS())
 
699
//                      optimizer[opt_type]->FixVertex(&h_res_mesh->vert[i]);
 
700
//
 
701
//      
 
702
//
 
703
//      //ScalarType speed=2.0/(sqrt((ScalarType)h_res_mesh->vn/(ScalarType)domain->vn))*optimize_speed_fact;
 
704
//      //optimizer[opt_type]->SetSpeed(speed);
 
705
//
 
706
//      /////then iterate until convergence
 
707
//      //for (int i=0;i<max_step;i++)
 
708
//      //      optimizer[opt_type]->IterateBlind();
 
709
//      ScalarType speed0=sqrt((ScalarType)domain->fn/(ScalarType)h_res_mesh->vn) * optimize_speed_fact;
 
710
//      //ScalarType speed0=optimize_speed_fact;
 
711
//      optimizer[opt_type]->SetSpeed(speed0);
 
712
//      ///END SETTINS SPEED
 
713
//      //if ((!bi)&&(b))
 
714
//      //      opt.IterateUntilConvergence(0.001);//,itenum);    
 
715
//      //else
 
716
//      int ite=optimizer[opt_type]->IterateUntilConvergence(speed0/10.0);//,itenum);
 
717
//
 
718
//      /*optimizer[opt_type]->IterateUntilConvergence(conv_interval,max_step);*/
 
719
//      bool inside=true;
 
720
//      
 
721
//      //reassing fathers and bary coordinates
 
722
//      for (int i=0;i<h_res_mesh->vert.size();i++)
 
723
//      {
 
724
//              VertexType *vert=&h_res_mesh->vert[i];
 
725
//              param_domain* pdomain=subdomain[i];
 
726
//              ScalarType u=vert->T().U();
 
727
//              ScalarType v=vert->T().V();
 
728
//              ///then get face falling into and estimate (alpha,beta,gamma)
 
729
//              CoordType bary;
 
730
//              BaseFace* chosen;
 
731
//              inside &=GetBaryFaceFromUV(pdomain->domain,u,v,pdomain->ordered_faces,bary,chosen);
 
732
//              vert->father=chosen;
 
733
//              vert->Bary=bary;
 
734
//      }
 
735
//      //assert(inside);
 
736
//      ////statistics
 
737
//      int changed=0;
 
738
//      ScalarType max_diff=0;
 
739
//      for (int i=0;i<h_res_mesh->vert.size();i++)
 
740
//      {
 
741
//              //ScalarType displ=(oldPos[i]-ProjectPos(h_res_mesh->vert[i])).Norm();
 
742
//              if (oldFather[i]!=h_res_mesh->vert[i].father)
 
743
//                      changed++;
 
744
//
 
745
//              else {
 
746
//                      ScalarType displ = (oldPos[i]-h_res_mesh->vert[i].Bary).SquaredNorm();
 
747
//                      if (displ>max_diff) max_diff=displ;
 
748
//              }
 
749
//      }
 
750
//      printf("%s : \n",phasename);
 
751
//      printf(" diff:%6.5f \n",sqrt(max_diff) );
 
752
//      printf("migr:%i \n",changed);
 
753
//      printf("AREA distorsion:%lf \n",ApproxAreaDistortion<MeshType>(*h_res_mesh,domain->fn));
 
754
//      printf("ANGLE distorsion:%lf \n",ApproxAngleDistortion<MeshType>(*h_res_mesh));
 
755
//      /*if (!inside)
 
756
//              printf("Point out of parametrization during optimization \n");*/
 
757
//
 
758
//}
 
759
 
 
760
void MinimizeStep(const int &phaseNum)
 
761
{
 
762
        
 
763
 
 
764
        //Ord_HVert[index]
 
765
        for (unsigned int i=0;i<HRES_meshes.size();i++)
 
766
        {
 
767
 
 
768
                MeshType *currMesh=HRES_meshes[i];
 
769
                if (currMesh->fn>0)
 
770
                {
 
771
                UpdateTopologies<MeshType>(currMesh);
 
772
                
 
773
                ///on star
 
774
                int numDom=1;
 
775
                switch (phaseNum)
 
776
                {
 
777
                case 0:numDom=6;break;//star
 
778
                case 1:numDom=2;break;//diam
 
779
                case 2:numDom=1;break;//face
 
780
                }
 
781
                ///save previous values
 
782
                InitDampRestUV(*currMesh);
 
783
                bool b=UnFold<MeshType>(*currMesh,numDom);
 
784
                bool isOK=testParamCoords<MeshType>(*currMesh);
 
785
                if ((!b)||(!isOK))
 
786
                        RestoreRestUV<MeshType>(*currMesh);
 
787
 
 
788
                OptType opt(*currMesh);
 
789
                opt.TargetCurrentGeometry();
 
790
                opt.SetBorderAsFixed();
 
791
 
 
792
                ///save previous values
 
793
                InitDampRestUV(*currMesh);
 
794
                
 
795
                
 
796
 
 
797
                ///NEW SETTING SPEED
 
798
                /*ScalarType edge_esteem=GetSmallestUVEdgeSize<MeshType>(*currMesh);
 
799
                ScalarType speed0=edge_esteem*0.01;
 
800
                ScalarType conv=edge_esteem*0.0005;*/
 
801
                ScalarType edge_esteem=GetSmallestUVHeight(*currMesh);
 
802
                
 
803
 
 
804
                ScalarType speed0=edge_esteem*0.1;
 
805
                ScalarType conv=edge_esteem*0.002;
 
806
 
 
807
                if (accuracy>1)
 
808
                        conv*=1.0/(ScalarType)((accuracy-1)*10.0);
 
809
 
 
810
                opt.SetSpeed(speed0);
 
811
                /*int ite=*/opt.IterateUntilConvergence(conv);
 
812
 
 
813
                ///test for uv errors
 
814
                bool IsOK=true;
 
815
                for (unsigned int j=0;j<currMesh->vert.size();j++)
 
816
                {
 
817
                        VertexType *ParamVert=&currMesh->vert[j];
 
818
                        ScalarType u=ParamVert->T().U();
 
819
                        ScalarType v=ParamVert->T().V();
 
820
                        if ((!((u<=1.001)&&(u>=-1.001)))||
 
821
                           (!(v<=1.001)&&(v>=-1.001)))
 
822
                        {
 
823
                                IsOK=false;
 
824
//#ifndef _MESHLAB
 
825
//                              printf("error in minimization... recovering...\n");
 
826
//#endif
 
827
                                for (unsigned int k=0;k<currMesh->vert.size();k++)
 
828
                                        currMesh->vert[k].T().P()=currMesh->vert[k].RestUV;
 
829
                                break;
 
830
                        }
 
831
                }
 
832
                //reassing fathers and bary coordinates
 
833
                for (unsigned int j=0;j<currMesh->vert.size();j++)
 
834
                {
 
835
                        VertexType *ParamVert=&currMesh->vert[j];
 
836
                        VertexType *OrigVert=Ord_HVert[i][j];
 
837
                        ScalarType u=ParamVert->T().U();
 
838
                        ScalarType v=ParamVert->T().V();
 
839
                        ///then get face falling into and estimate (alpha,beta,gamma)
 
840
                        CoordType bary;
 
841
                        BaseFace* chosen;
 
842
                        param_domain *currDom;
 
843
                        switch (phaseNum)
 
844
                        {
 
845
                        case 0:currDom=&star_meshes[i];break;//star
 
846
                        case 1:currDom=&diamond_meshes[i];break;//diam
 
847
                        case 2:currDom=&face_meshes[i];break;//face
 
848
                        }
 
849
                        /*assert(currDom->domain->vn==3);
 
850
                        assert(currDom->domain->fn==1);*/
 
851
                        bool inside=GetBaryFaceFromUV(*currDom->domain,u,v,currDom->ordered_faces,bary,chosen);
 
852
                        if (!inside)
 
853
                        {
 
854
                                /*#ifndef _MESHLAB*/
 
855
                                printf("\n OUTSIDE %f,%f \n",u,v);
 
856
                                /*#endif*/
 
857
                                vcg::Point2<ScalarType> UV=vcg::Point2<ScalarType>(u,v);
 
858
                                ForceInParam<MeshType>(UV,*currDom->domain);
 
859
                                u=UV.X();
 
860
                                v=UV.Y();
 
861
                                inside=GetBaryFaceFromUV(*currDom->domain,u,v,currDom->ordered_faces,bary,chosen);
 
862
                                //assert(0);
 
863
                        }
 
864
                        assert(inside);
 
865
                        OrigVert->father=chosen;
 
866
                        OrigVert->Bary=bary;
 
867
                }
 
868
                }
 
869
                        ///delete current mesh
 
870
                        delete(HRES_meshes[i]);
 
871
        }
 
872
 
 
873
        ///clear father and bary
 
874
        for (unsigned int i=0;i<domain->face.size();i++)
 
875
                domain->face[i].vertices_bary.clear();
 
876
 
 
877
        ///set face-vertex link
 
878
        for (unsigned int i=0;i<h_res_mesh->vert.size();i++)
 
879
        {
 
880
                BaseVertex *v=&h_res_mesh->vert[i];
 
881
                if (!v->IsD())
 
882
                {
 
883
                        BaseFace *f=v->father;
 
884
                        CoordType bary=v->Bary;
 
885
                        f->vertices_bary.push_back(std::pair<VertexType*,CoordType>(v,bary));
 
886
                }
 
887
        }       
 
888
}
 
889
 
 
890
//void EndOptimization()
 
891
//{
 
892
//      ///clear father and bary
 
893
//      for (unsigned int i=0;i<domain->face.size();i++)
 
894
//              domain->face[i].vertices_bary.resize(0);
 
895
//              
 
896
//      ///set face-vertex link
 
897
//      for (unsigned int i=0;i<h_res_mesh->vert.size();i++)
 
898
//      {
 
899
//              BaseVertex *v=&h_res_mesh->vert[i];
 
900
//              BaseFace *f=v->father;
 
901
//              CoordType bary=v->Bary;
 
902
//              f->vertices_bary.push_back(std::pair<VertexType*,CoordType>(v,bary));
 
903
//      }       
 
904
//
 
905
//}
 
906
 
 
907
int accuracy;
 
908
vcg::CallBackPos *cb;
 
909
int step;
 
910
 
 
911
public:
 
912
 
 
913
 
 
914
        void Init(MeshType &_domain,
 
915
                          MeshType &_h_res_mesh,
 
916
                          vcg::CallBackPos *_cb,
 
917
                          int _accuracy=1)
 
918
        {
 
919
                step=0;
 
920
                cb=_cb;         
 
921
                accuracy=_accuracy;
 
922
 
 
923
                vcg::tri::UpdateNormals<MeshType>::PerFaceNormalized(_domain);
 
924
 
 
925
                domain=&_domain;
 
926
                h_res_mesh=&_h_res_mesh;
 
927
                
 
928
                /*subdomain.resize(h_res_mesh->vert.size());*/
 
929
 
 
930
                ///get the average area per triangle
 
931
                /*ScalarType area=Area<MeshType>(_h_res_mesh);*/
 
932
 
 
933
                ///get esteemation of average area per triangle
 
934
                //ScalarType average_area=area/(ScalarType)_h_res_mesh.vn;
 
935
 
 
936
                ///initialize STARS
 
937
                star_meshes.resize(domain->vn);
 
938
                InitStarEquilateral();
 
939
                /*InitStarSubdivision();*/
 
940
 
 
941
                ///initialize DIAMONDS
 
942
                int num_edges=0;
 
943
                for (unsigned int i=0;i<domain->face.size();i++)
 
944
                {
 
945
                        if (!(domain->face[i].IsD()))
 
946
                        {
 
947
                                FaceType *f0=&domain->face[i];
 
948
                                //for each edge
 
949
                                for (int j=0;j<3;j++)
 
950
                                {
 
951
                                        FaceType * f1=f0->FFp(j);
 
952
                                        if (f1<f0)
 
953
                                                num_edges++;
 
954
                                }
 
955
                        }
 
956
                }
 
957
                diamond_meshes.resize(num_edges);
 
958
                InitDiamondEquilateral();
 
959
                
 
960
                ///initialize FACES
 
961
                face_meshes.resize(domain->fn);
 
962
                InitFaceEquilateral();
 
963
                
 
964
                ///init minimizer
 
965
                for (unsigned int i=0;i<h_res_mesh->vert.size();i++)
 
966
                        h_res_mesh->vert[i].P()=h_res_mesh->vert[i].RPos;
 
967
 
 
968
                //InitDampRestUV(*h_res_mesh);
 
969
        }
 
970
 
 
971
        
 
972
        void PrintAttributes()
 
973
        {
 
974
                /*ScalarType distArea=ApproxAreaDistortion<BaseMesh>(*h_res_mesh,domain->fn);
 
975
                ScalarType distAngle=ApproxAngleDistortion<BaseMesh>(*h_res_mesh);
 
976
                ScalarType distAggregate=geomAverage<ScalarType>(distArea+1.0,distAngle+1.0,3,1)-1;
 
977
                printf("\n AREA  distorsion:%lf;\n ANGLE distorsion:%lf;\n AGGREGATE distorsion:%lf \n\n",distArea,distAngle,distAggregate);*/
 
978
                int done=step;
 
979
                int total=6;
 
980
                ScalarType ratio=(ScalarType)done/total;
 
981
                int percent=(int)(ratio*(ScalarType)100);
 
982
                ScalarType distArea=ApproxAreaDistortion<BaseMesh>(*h_res_mesh,domain->fn);
 
983
                ScalarType distAngle=ApproxAngleDistortion<BaseMesh>(*h_res_mesh);
 
984
                char ret[200];
 
985
                sprintf(ret," PERFORM GLOBAL OPTIMIZATION  Area distorsion:%4f ; ANGLE distorsion:%4f ",distArea,distAngle);
 
986
                (*cb)(percent,ret);
 
987
        }
 
988
 
 
989
        void Optimize(ScalarType gap=0.5)
 
990
        {
 
991
                /*int t0=clock();*/
 
992
                int k=0;
 
993
                /*int opt_type=0;*/
 
994
                ScalarType distArea=ApproxAreaDistortion<BaseMesh>(*h_res_mesh,domain->fn);
 
995
                ScalarType distAngle=ApproxAngleDistortion<BaseMesh>(*h_res_mesh);
 
996
                ScalarType distAggregate0=geomAverage<ScalarType>(distArea+1.0,distAngle+1.0,3,1)-1;
 
997
                PrintAttributes();
 
998
                bool ContinueOpt=true;
 
999
                PrintAttributes();
 
1000
                PatchesOptimizer<BaseMesh> DomOpt(*domain,*h_res_mesh);
 
1001
                step++;
 
1002
                PrintAttributes();
 
1003
 
 
1004
                DomOpt.OptimizePatches();
 
1005
 
 
1006
        
 
1007
 
 
1008
                while (ContinueOpt)
 
1009
                {
 
1010
                        ///domain Optimization  
 
1011
                        k++;
 
1012
                        /*#ifndef _MESHLAB
 
1013
                        printf("\n DOING STAR\n");
 
1014
                        #endif*/
 
1015
                        InitStarSubdivision();
 
1016
                        MinimizeStep(0);
 
1017
                        //PrintAttributes();
 
1018
                /*      #ifndef _MESHLAB
 
1019
                        printf("\n DOING DIAMOND\n");
 
1020
                        #endif*/
 
1021
                        InitDiamondSubdivision();
 
1022
                        MinimizeStep(1);
 
1023
                        //PrintAttributes();
 
1024
                        /*#ifndef _MESHLAB
 
1025
                        printf("\n DOING FACES\n");
 
1026
                        #endif*/
 
1027
                        InitFaceSubdivision();
 
1028
                        MinimizeStep(2);
 
1029
                        step++;
 
1030
                        PrintAttributes();
 
1031
 
 
1032
                        distArea=ApproxAreaDistortion<BaseMesh>(*h_res_mesh,domain->fn);
 
1033
                        distAngle=ApproxAngleDistortion<BaseMesh>(*h_res_mesh);
 
1034
                        ScalarType distAggregate1=geomAverage<ScalarType>(distArea+1.0,distAngle+1.0,3,1)-1;
 
1035
                        ScalarType NewGap=((distAggregate0-distAggregate1)*100.0)/distAggregate0;
 
1036
                        /*#ifndef _MESHLAB
 
1037
                        PrintAttributes();
 
1038
                        printf("\n Step %d Gap %lf \n",k,NewGap);
 
1039
                        #endif*/
 
1040
                        if (NewGap<gap)
 
1041
                                ContinueOpt=false;
 
1042
                        distAggregate0=distAggregate1;
 
1043
                }
 
1044
                ///*EndOptimization();*/
 
1045
                //int t1=clock();
 
1046
                //#ifndef _MESHLAB
 
1047
                //printf("TIME OPTIMIZATION:%d \n",(t1-t0)/1000);
 
1048
                //#endif
 
1049
        }
 
1050
        
 
1051
        
 
1052
};
 
1053
#endif
 
 
b'\\ No newline at end of file'