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