1 #ifndef PARAM_FLIP
2 #define PARAM_FLIP
3 
4 #include <vcg/complex/algorithms/local_optimization/tri_edge_flip.h>
5 
6 namespace vcg{
7 namespace tri{
8 
9 ///Flip function
10 template <class BaseMesh>
11 class ParamEdgeFlip : public vcg::tri::PlanarEdgeFlip<BaseMesh, ParamEdgeFlip<BaseMesh> >
12 {
13     typedef typename BaseMesh::VertexType::EdgeType EdgeType;
14     typedef typename BaseMesh::VertexType BaseVertex;
15         typedef typename BaseMesh::VertexType VertexType;
16     typedef typename BaseMesh::FaceType   BaseFace;
17         typedef typename BaseMesh::FaceType   FaceType;
18         typedef typename BaseMesh::CoordType   CoordType;
19         typedef typename BaseMesh::ScalarType   ScalarType;
20         typedef vcg::tri::PlanarEdgeFlip<BaseMesh, ParamEdgeFlip<BaseMesh> > Super;
21     ScalarType diff;
22 
23     public:
24 
EType()25   static EnergyType &EType(){static EnergyType E;return E;}
26 
27     bool savedomain;
28 
IsFeasible(BaseParameterClass *)29     bool IsFeasible(BaseParameterClass *)
30     {
31         if(!vcg::face::CheckFlipEdge(*this->_pos.F(), this->_pos.E()))
32             return false;
33 
34         return (this->_priority>0);
35     }
36 
ParamEdgeFlip()37     inline ParamEdgeFlip() {}
38 
39     /*!
40      *	Constructor with <I>pos</I> type
41      */
ParamEdgeFlip(const typename Super::PosType pos,int mark,BaseParameterClass * pp)42   inline ParamEdgeFlip(const typename Super::PosType pos, int mark,BaseParameterClass *pp)
43     {
44         this->_pos = pos;
45         this->_localMark = mark;
46     this->_priority = this->ComputePriority(pp);
47         savedomain=false;
48     }
49 
50     ///do the effective flip
51     void ExecuteFlip(FaceType &f, const int &edge, BaseMesh *base_domain=NULL)
52     {
53         std::vector<FaceType*> faces;
54         faces.push_back(&f);
55         faces.push_back(f.FFp(edge));
56         std::vector<VertexType*> HresVert;
57         getHresVertex<FaceType>(faces,HresVert);
58         ///parametrize H_res mesh respect to diamond
59         for (unsigned int i=0;i<HresVert.size();i++)
60         {
61             VertexType* v=HresVert[i];
62             ///get father & bary
63             FaceType* father=v->father;
64             CoordType bary=v->Bary;
65             assert((father==faces[0])||(father==faces[1]));
66             vcg::Point2<ScalarType> t0=father->V(0)->T().P();
67             vcg::Point2<ScalarType> t1=father->V(1)->T().P();
68             vcg::Point2<ScalarType> t2=father->V(2)->T().P();
69 
70             //assert(testBaryCoords(bary));
71             if(!testBaryCoords(bary))
72         {
73             printf("BAry0 :%lf,%lf,%lf",bary.X(),bary.Y(),bary.Z());
74             //system("pause");
75         }
76 
77       InterpolateUV<BaseMesh>(father,bary,v->T().U(),v->T().V());
78         }
79 
80         ///update VF topology
81         FaceType *f1=f.FFp(edge);
82         FaceType *f0=&f;
83         vcg::face::VFDetach(*f1,0);
84         vcg::face::VFDetach(*f1,1);
85         vcg::face::VFDetach(*f1,2);
86         vcg::face::VFDetach(*f0,0);
87         vcg::face::VFDetach(*f0,1);
88         vcg::face::VFDetach(*f0,2);
89         ///then do the effective flip
90 
91         vcg::face::FlipEdge(f,edge);
92 
93 
94 
95         vcg::face::VFAppend(f1,0);
96         vcg::face::VFAppend(f1,1);
97         vcg::face::VFAppend(f1,2);
98         vcg::face::VFAppend(f0,0);
99         vcg::face::VFAppend(f0,1);
100         vcg::face::VFAppend(f0,2);
101         ///edh updating topology
102 
103 
104         ///set son->father new link
105         for (unsigned int i=0;i<HresVert.size();i++)
106         {
107             VertexType* v=HresVert[i];
108             ScalarType U=v->T().U();
109             ScalarType V=v->T().V();
110             CoordType bary;
111             int index;
112             bool found=GetBaryFaceFromUV(faces,U,V,bary,index);
113             if (!found)
114             {
115                 printf("\n U : %lf; V : %lf \n",U,V);
116                 //system("pause");
117             }
118             //assert(found);
119             //assert();
120             if(!testBaryCoords(bary))
121             {
122                 printf("\n PAR ERROR 1: bary coords exceeds: %f,%f,%f \n",bary.X(),bary.Y(),bary.Z());
123                 NormalizeBaryCoords(bary);
124             }
125             if (base_domain!=NULL)
126                 AssingFather(*v,faces[index],bary,*base_domain);
127             else
128             {
129                 v->father=faces[index];
130                 assert(!faces[index]->IsD());
131                 v->Bary=bary;
132             }
133         }
134 
135 
136 
137         ///set father->son new link
138         for (unsigned int i=0;i<faces.size();i++)
139             faces[i]->vertices_bary.clear();
140 
141         for (unsigned int i=0;i<HresVert.size();i++)
142         {
143             VertexType *son=HresVert[i];
144             FaceType *father=son->father;
145             CoordType bary=son->Bary;
146             father->vertices_bary.push_back(std::pair<BaseVertex*,vcg::Point3f>(son,bary));
147         }
148 
149     }
150 
EdgeDiff()151     ScalarType EdgeDiff()
152     {
153         /*
154              1
155             /|\
156            / | \
157          2 f0|f1 3
158            \ | /
159             \|/
160              0
161          */
162 
163         VertexType *v0, *v1, *v2, *v3;
164         int edge0 = this->_pos.E();
165         v0 = this->_pos.F()->V0(edge0);
166         v1 = this->_pos.F()->V1(edge0);
167         v2 = this->_pos.F()->V2(edge0);
168         v3 = this->_pos.F()->FFp(edge0)->V2(this->_pos.F()->FFi(edge0));
169         int edge1=this->_pos.F()->FFi(edge0);
170         FaceType* f0=this->_pos.F();
171         FaceType* f1=this->_pos.F()->FFp(edge0);
172 
173         ///parametrize all possible diamonds
174         ///diam0 & diam1
175         ///make a copy of the mesh
176         std::vector<FaceType*> OrdFace;
177         OrdFace.push_back(f0);
178         OrdFace.push_back(f1);
179 
180         BaseMesh Diam;
181         BaseMesh DiamHres;
182 
183         ///create a copy of the domain and of the H resolution
184         CopySubMeshLevels(OrdFace,Diam,DiamHres);
185 
186         ///parametrize domains
187         ParametrizeDiamondEquilateral(Diam,edge0,edge1);
188 
189         ///copy parametrization on original mesh
190 
191         FaceType* on_edge[2];
192         on_edge[0]=&Diam.face[0];
193         on_edge[1]=&Diam.face[1];
194         assert(Diam.face[0].FFp(edge0)==&Diam.face[1]);///test
195         assert(Diam.face[1].FFp(edge1)==&Diam.face[0]);///test
196 
197         ///Evaluate length of shared edge
198         ScalarType L0=EstimateLengthByParam<BaseMesh>(Diam.face[0].V(edge0),Diam.face[0].V((edge0+1)%3),on_edge);
199 
200         ///do the flip on the copied mesh do not affect the original mesh
201         ExecuteFlip(Diam.face[0],edge0);
202 
203         UpdateTopologies(&Diam);
204 
205         ///get the non border edge of face0
206         int NB_edge=-1;
207         if (!Diam.face[0].IsB(0))
208             NB_edge=0;
209         else
210         if (!Diam.face[0].IsB(1))
211             NB_edge=1;
212         else
213         if (!Diam.face[0].IsB(2))
214             NB_edge=2;
215         assert(NB_edge!=-1);
216 
217         ScalarType L1=EstimateLengthByParam<BaseMesh>(Diam.face[0].V(NB_edge),Diam.face[0].V((NB_edge+1)%3),on_edge);
218 
219         ScalarType value=L0-L1;
220         diff=value;
221         this->_priority = 1.0/value;
222         return (this->_priority);
223     }
224 
225 
Execute(BaseMesh & m,BaseParameterClass *)226     void Execute(BaseMesh &m,BaseParameterClass *)
227     {
228 
229         assert(this->_priority>0);
230         /*
231              1
232             /|\
233            / | \
234          2 f0|f1 3
235            \ | /
236             \|/
237              0
238          */
239         VertexType *v0, *v1, *v2, *v3;
240         int edge0 = this->_pos.E();
241         v0 = this->_pos.F()->V0(edge0);
242         v1 = this->_pos.F()->V1(edge0);
243         v2 = this->_pos.F()->V2(edge0);
244         v3 = this->_pos.F()->FFp(edge0)->V2(this->_pos.F()->FFi(edge0));
245         ///assign texcoords
246         ScalarType h=(sqrt((ScalarType)3.0)/(ScalarType)2.0);
247         v0->T().P()=vcg::Point2<ScalarType>(0,(ScalarType)-0.5);
248         v1->T().P()=vcg::Point2<ScalarType>(0,(ScalarType)0.5);
249         v2->T().P()=vcg::Point2<ScalarType>(-h,0);
250         v3->T().P()=vcg::Point2<ScalarType>(h,0);
251 
252 #ifndef _MESHLAB
253         ///save domain if need for demos
254         if (savedomain)
255         {
256             BaseMesh hlev_mesh;
257             std::vector<FaceType*> faces;
258             FaceType* f=this->_pos.F();
259             int edge=this->_pos.E();
260             faces.push_back(f);
261             faces.push_back(f->FFp(edge));
262             std::vector<VertexType*> HresVert;
263             getHresVertex<FaceType>(faces,HresVert);
264 
265             ///parametrize H_res mesh respect to diamond
266             std::vector<VertexType*> OrderedVertices;
267             std::vector<FaceType*> OrderedFaces;
268             CopyMeshFromVertices(HresVert,OrderedVertices,OrderedFaces,hlev_mesh);
269             //for (int i=0;i<hlev_mesh.vert.size();i++)
270                 //hlev_mesh.vert[i].C()=hlev_mesh.vert[i].OriginalCol;
271 
272             vcg::tri::io::ExporterPLY<BaseMesh>::Save(hlev_mesh,"c:/export_submeshes/FLIPHlev3D.ply",vcg::tri::io::Mask::IOM_VERTCOLOR);
273             for (unsigned int i=0;i<hlev_mesh.vert.size();i++)
274             {
275                 hlev_mesh.vert[i].P().X()=hlev_mesh.vert[i].T().U();
276                 hlev_mesh.vert[i].P().Y()=hlev_mesh.vert[i].T().V();
277                 hlev_mesh.vert[i].P().Z()=0;
278             }
279             vcg::tri::io::ExporterPLY<BaseMesh>::Save(hlev_mesh,"c:/export_submeshes/FLIPHlevUV.ply",vcg::tri::io::Mask::IOM_VERTCOLOR);
280         }
281 #endif
282 
283         ExecuteFlip(*this->_pos.F(),this->_pos.E(),&m);
284 
285         UpdateTopologies(&m);
286 
287         ///stars optimization
288         /*int t0=clock();*/
289         /*OptimizeStar<BaseMesh>(v0);
290         OptimizeStar<BaseMesh>(v1);
291         OptimizeStar<BaseMesh>(v2);
292         OptimizeStar<BaseMesh>(v3);*/
293 
294         SmartOptimizeStar<BaseMesh>(v0,m,Accuracy(),EType());
295         SmartOptimizeStar<BaseMesh>(v1,m,Accuracy(),EType());
296         SmartOptimizeStar<BaseMesh>(v2,m,Accuracy(),EType());
297         SmartOptimizeStar<BaseMesh>(v3,m,Accuracy(),EType());
298         /*int t1=clock();
299         time_opt+=(t1-t0);*/
300     }
301 
ComputePriority(BaseParameterClass *)302   ScalarType ComputePriority(BaseParameterClass *)
303     {
304     this->_priority=EdgeDiff();
305         return this->_priority;
306     }
307 
getF()308     BaseFace *getF()
309     {return this->_pos.F();}
310 
getE()311     int getE()
312     {return this->_pos.E();}
313 
314     public:
Accuracy()315     static int &Accuracy()
316     {
317         static int _acc;
318         return _acc;
319     }
320 
321 };
322 
323 }//end namespace tri
324 }//end namespace vcg
325 
326 #endif
327