1 #ifndef _LOCAL_OPTIMIZATION
2 #define _LOCAL_OPTIMIZATION
3
4 #include "statistics.h"
5
6 enum EnergyType{EN_EXTMips,EN_MeanVal};
7
8 template <class MeshType>
9 bool UnFold(MeshType &mesh,int /*num_faces*/,bool fix_selected=false)
10 {
11 typedef typename MeshType::ScalarType ScalarType;
12 //static int folds=0;
13 std::vector<typename MeshType::FaceType*> folded_faces;
14 bool unfolded=NonFolded<MeshType>(mesh,folded_faces);
15 if (unfolded)return (true);
16 typedef typename vcg::tri::MIPSTexCoordFoldHealer<MeshType> UnfoldType;
17 UnfoldType opt(mesh);
18
19 opt.TargetCurrentGeometry();
20 opt.SetBorderAsFixed();
21 if (fix_selected)
22 for (unsigned int i=0;i<mesh.vert.size();i++)
23 if (mesh.vert[i].IsS())
24 opt.FixVertex(&mesh.vert[i]);
25
26
27
28 //ScalarType speed=(2.0/(sqrt((ScalarType)mesh.vn/num_faces)))*0.008;
29 ScalarType edge_esteem=GetSmallestUVHeight(mesh);
30 //ScalarType speed=edge_esteem*0.005;*/
31 //ScalarType edge_esteem=GetSmallestUVEdgeSize<MeshType>(mesh);
32
33 ScalarType speed=(ScalarType)(edge_esteem*0.05);
34 opt.SetSpeed(speed);
35 ///then iterate until unfolding
36 /*int iter=*/opt.IterateUntilConvergence();
37 //#ifndef _MESHLAB
38 // printf("[F:%d]",iter);
39 //#endif
40 return true;
41 }
42
43 ///return true if UV coordinates are OK
44 template <class MeshType>
testCoords(MeshType & m)45 bool testCoords(MeshType &m)
46 {
47 typedef typename MeshType::ScalarType ScalarType;
48 for (int i=0;i<m.vert.size();i++)
49 {
50 ScalarType u=m.vert[i].T().U();
51 ScalarType v=m.vert[i].T().V();
52 if (!((u>-1.0)&&(u<1.0)&&(v>-1.0)&&(v<1.0)))
53 return false;
54 }
55 return true;
56 }
57
58 template <class MeshType>
StarDistorsion(typename MeshType::VertexType * v)59 typename MeshType::ScalarType StarDistorsion(typename MeshType::VertexType *v)
60 {
61 typedef typename MeshType::VertexType VertexType;
62 typedef typename MeshType::FaceType FaceType;
63 typedef typename MeshType::CoordType CoordType;
64 typedef typename MeshType::ScalarType ScalarType;
65
66 std::vector<VertexType*> starCenter;
67 starCenter.push_back(v);
68 std::vector<FaceType*> ordered_faces;
69 std::vector<VertexType*> HresVert;
70 MeshType star_domain,hlev_mesh;
71
72 ///create star
73 CreateMeshVertexStar(starCenter,ordered_faces,star_domain);
74 ParametrizeStarEquilateral<MeshType>(star_domain);
75
76 ///get all the vertices in H definition that should be optimized
77 ///and initialize vertices with u,v coordinates
78 for (unsigned int index=0;index<ordered_faces.size();index++)
79 {
80 FaceType *parametric_face=&star_domain.face[index];
81 FaceType *test_face=ordered_faces[index];
82
83 ///parametrize HlevMesh
84 for (unsigned int i=0;i<test_face->vertices_bary.size();i++)
85 {
86 ///interpolate U V per vertex
87 CoordType bary=test_face->vertices_bary[i].second;
88 ScalarType u,v;
89 InterpolateUV<MeshType>(parametric_face,bary,u,v);
90
91 VertexType* to_parametrize=test_face->vertices_bary[i].first;
92 to_parametrize->T().U()=u;
93 to_parametrize->T().V()=v;
94
95 HresVert.push_back(to_parametrize);
96 }
97 }
98
99 ///get a copy of submesh
100 std::vector<typename MeshType::VertexType*> ordered_vertex;
101 CopyHlevMesh(ordered_faces,hlev_mesh,ordered_vertex);
102 UpdateTopologies<MeshType>(&hlev_mesh);
103 ScalarType val0=ApproxAreaDistortion<MeshType>(hlev_mesh,star_domain.fn);
104 ScalarType val1=ApproxAngleDistortion<MeshType>(hlev_mesh);
105 ScalarType val2=geomAverage<ScalarType>(val0+(ScalarType)1.0,val1+(ScalarType)1.0,3,1)-(ScalarType)1;
106 return val2;
107 }
108
109 ///optimize a single star
110 template <class MeshType>
111 void OptimizeStar(typename MeshType::VertexType *v,MeshType &domain,int accuracy=1,EnergyType En=EN_EXTMips)
112 {
113 typedef typename MeshType::VertexType VertexType;
114 typedef typename MeshType::FaceType FaceType;
115 typedef typename MeshType::CoordType CoordType;
116 typedef typename MeshType::ScalarType ScalarType;
117 #ifndef IMPLICIT
118 typedef typename vcg::tri::AreaPreservingTexCoordOptimization<MeshType> OptType;
119 typedef typename vcg::tri::MeanValueTexCoordOptimization<MeshType> OptType1;
120 #else
121 typedef typename PoissonSolver<MeshType> OptType;
122 #endif
123
124 std::vector<VertexType*> starCenter;
125 starCenter.push_back(v);
126 std::vector<FaceType*> ordered_faces;
127 std::vector<VertexType*> HresVert;
128 MeshType star_domain,hlev_mesh;
129
130 ///create star
131 CreateMeshVertexStar(starCenter,ordered_faces,star_domain);
132 ParametrizeStarEquilateral<MeshType>(star_domain);
133 assert(testParamCoords(star_domain));
134
135 ///get all the vertices in H definition that should be optimized
136 ///and initialize vertices with u,v coordinates
137 for (unsigned int index=0;index<ordered_faces.size();index++)
138 {
139 FaceType *parametric_face=&star_domain.face[index];
140 FaceType *test_face=ordered_faces[index];
141
142 ///parametrize HlevMesh
143 for (unsigned int i=0;i<test_face->vertices_bary.size();i++)
144 {
145 ///interpolate U V per vertex
146 CoordType bary=test_face->vertices_bary[i].second;
147 ScalarType u,v;
148 InterpolateUV<MeshType>(parametric_face,bary,u,v);
149
150 VertexType* to_parametrize=test_face->vertices_bary[i].first;
151 to_parametrize->T().U()=u;
152 to_parametrize->T().V()=v;
153 assert(testParamCoords<VertexType>(to_parametrize));
154 HresVert.push_back(to_parametrize);
155 }
156 }
157
158 #ifndef IMPLICIT
159 vcg::tri::SmoothTexCoords(hlev_mesh);
160 #endif
161 ///get a copy of submesh
162 std::vector<typename MeshType::VertexType*> ordered_vertex;
163 CopyHlevMesh(ordered_faces,hlev_mesh,ordered_vertex);
164 assert(testParamCoords(hlev_mesh));
165 UpdateTopologies<MeshType>(&hlev_mesh);
166
167 #ifndef IMPLICIT
168 InitDampRestUV(hlev_mesh);
169 assert(testParamCoords(hlev_mesh));
170 #endif
171
172
173 if (hlev_mesh.vn==0)
174 return;
175 if (hlev_mesh.fn==0)
176 return;
177
178 #ifndef IMPLICIT
179 bool b=UnFold<MeshType>(hlev_mesh,star_domain.fn);
180 bool isOK=testParamCoords(hlev_mesh);
181
182 if ((!b)||(!isOK))
183 RestoreRestUV(hlev_mesh);
184
185 bool b0=NonFolded<MeshType>(hlev_mesh);
186
187 #endif
188
189 #ifndef IMPLICIT
190 ///initialize optimization
191 if (En==EN_EXTMips)
192 {
193 OptType opt(hlev_mesh);
194 opt.TargetCurrentGeometry();
195 opt.SetBorderAsFixed();
196
197 ////SETTING SPEED
198 ScalarType edge_esteem=GetSmallestUVHeight(hlev_mesh);
199
200 ScalarType speed0=edge_esteem*0.5;//0.05;
201 ScalarType conv=edge_esteem*0.2;//edge_esteem*0.05;
202 if (accuracy>1)
203 conv*=1.0/(ScalarType)((accuracy-1)*10.0);
204
205 opt.SetSpeed(speed0);
206 opt.IterateUntilConvergence(conv);
207 }
208 else
209 if (En==EN_MeanVal)
210 {
211 OptType1 opt(hlev_mesh);
212 opt.TargetCurrentGeometry();
213 opt.SetBorderAsFixed();
214
215 ////SETTING SPEED
216 ScalarType edge_esteem=GetSmallestUVHeight(hlev_mesh);
217
218 ScalarType speed0=edge_esteem*0.5;//0.05;
219 ScalarType conv=edge_esteem*0.2;//edge_esteem*0.05;
220 if (accuracy>1)
221 conv*=1.0/(ScalarType)((accuracy-1)*10.0);
222
223 opt.SetSpeed(speed0);
224 opt.IterateUntilConvergence(conv);
225 }
226 #else
227 OptType opt(hlev_mesh);
228 opt.SetBorderAsFixed();
229 opt.SolvePoisson();
230 #endif
231 #ifdef IMPLICIT
232 assert(testParamCoords(hlev_mesh));
233 #else
234 if (!testParamCoords(hlev_mesh))
235 {
236 RestoreRestUV(hlev_mesh);
237 //return;///no modifications problems with optimization
238 }
239 ///folded during optimization
240 bool b1=NonFolded<MeshType>(hlev_mesh);
241 if ((b0)&&(!b1))
242 {
243 //return;
244 RestoreRestUV(hlev_mesh);
245 }
246 #endif
247 bool inside=true;
248
249 //test barycentric coords
250 std::vector<FaceType*> oldFath;
251 std::vector<CoordType> oldBary;
252 oldFath.reserve(hlev_mesh.vert.size());
253 oldBary.reserve(hlev_mesh.vert.size());
254
255 for (unsigned int i=0;i<hlev_mesh.vert.size();i++)
256 {
257 VertexType *parametrized=&hlev_mesh.vert[i];
258 ///save previous values
259 VertexType *to_reassing=ordered_vertex[i];
260 oldFath.push_back(to_reassing->father);
261 oldBary.push_back(to_reassing->Bary);
262
263 ///get UV coords
264 ScalarType U=parametrized->T().U();
265 ScalarType V=parametrized->T().V();
266 ///then get face falling into and estimate (alpha,beta,gamma)
267 CoordType bary;
268 FaceType* chosen;
269 inside=GetBaryFaceFromUV(star_domain,U,V,ordered_faces,bary,chosen);
270 if ((!inside)||(!testBaryCoords(bary)))
271 {
272 ///restore old coordinates and return
273 for (unsigned int k=0;k<oldFath.size();k++)
274 {
275 /*hlev_mesh.vert[k].father=oldFath[k];
276 assert(!oldFath[k]->IsD());
277 hlev_mesh.vert[k].Bary=oldBary[k];*/
278 AssingFather(hlev_mesh.vert[k],oldFath[k],oldBary[k],domain);
279 }
280 CoordType val;
281 bool found1=GetCoordFromUV(hlev_mesh,0,0,val,true);
282 if (found1)
283 v->RPos=val;
284 return;
285 }
286
287 //to_reassing->father=chosen;
288 //assert(!chosen->IsD());
289 //to_reassing->Bary=bary;
290 bool isOK=NormalizeBaryCoords(bary);
291 assert(isOK);
292 AssingFather(*to_reassing,chosen,bary,domain);
293 }
294
295 ///clear father and bary
296 for (unsigned int i=0;i<ordered_faces.size();i++)
297 ordered_faces[i]->vertices_bary.resize(0);
298
299 ///set face-vertex link
300 for (unsigned int i=0;i<HresVert.size();i++)
301 {
302 VertexType *v=HresVert[i];
303 FaceType *f=v->father;
304 CoordType bary=v->Bary;
305 /*if(!testBaryCoords(bary))
306 {
307 printf("BAry0 :%lf,%lf,%lf",bary.X(),bary.Y(),bary.Z());
308 system("pause");
309 }*/
310 f->vertices_bary.push_back(std::pair<VertexType*,CoordType>(v,bary));
311 }
312
313 ///update Rpos of V if it can
314 ///get UV coords of V that is (0,0)
315 //vcg::Point2f UVCenter=vcg::Point2f(0,0);
316 CoordType val;
317 bool found1=GetCoordFromUV(hlev_mesh,0,0,val,true);
318 if (found1)
319 v->RPos=val;
320 }
321
322
323 template <class MeshType>
324 bool SmartOptimizeStar(typename MeshType::VertexType *center,MeshType &base_domain,int accuracy=1,EnergyType En=EN_EXTMips)
325 {
326 typedef typename MeshType::VertexType VertexType;
327 typedef typename MeshType::FaceType FaceType;
328 typedef typename MeshType::ScalarType ScalarType;
329 std::vector<FaceType*> faces;
330 std::vector<VertexType*> centers;
331 centers.push_back(center);
332 ///find number of vertices falling into
333 getSharedFace<MeshType>(centers,faces);
334 centers.clear();
335 int sizeH=0;
336 for (unsigned int i=0;i<faces.size();i++)
337 sizeH+=faces[i]->vertices_bary.size();
338
339 ScalarType ratio=(ScalarType)sizeH/(ScalarType)faces.size();
340
341 if (ratio<=1)
342 return false;
343 else
344 OptimizeStar<MeshType>(center,base_domain,accuracy,En);
345 return true;
346 }
347 #endif
348