00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef VCG_PARAM_DISTORTION
00025 #define VCG_PARAM_DISTORTION
00026 #include <vcg/complex/algorithms/parametrization/uv_utils.h>
00027 #include <vcg/complex/algorithms/parametrization/tangent_field_operators.h>
00028
00029 namespace vcg {
00030 namespace tri{
00031 template <class MeshType, bool PerWedgeFlag>
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 class Distortion
00054 {
00055 public:
00056 typedef typename MeshType::FaceType FaceType;
00057 typedef typename MeshType::VertexType VertexType;
00058 typedef typename MeshType::CoordType CoordType;
00059 typedef typename MeshType::ScalarType ScalarType;
00060 typedef typename MeshType::FaceType::CurVecType CurVecType;
00061 typedef typename MeshType::FaceType::TexCoordType::ScalarType TexScalarType;
00062 typedef Point2<TexScalarType> TexCoordType;
00063
00064 static ScalarType Area3D(const FaceType *f)
00065 {
00066 return DoubleArea(*f)*(0.5);
00067 }
00068
00069 static ScalarType AreaUV(const FaceType *f)
00070 {
00071 TexCoordType uv0,uv1,uv2;
00072 if(PerWedgeFlag) {
00073 uv0=f->cWT(0).P();
00074 uv1=f->cWT(1).P();
00075 uv2=f->cWT(2).P();
00076 } else {
00077 uv0=f->cV(0)->T().P();
00078 uv1=f->cV(1)->T().P();
00079 uv2=f->cV(2)->T().P();
00080 }
00081 ScalarType AreaUV=((uv1-uv0)^(uv2-uv0))/2.0;
00082 return AreaUV;
00083 }
00084
00085 static ScalarType EdgeLenght3D(const FaceType *f,int e)
00086 {
00087 assert((e>=0)&&(e<3));
00088 ScalarType length=(f->cP0(e)-f->cP1(e)).Norm();
00089 return (length);
00090 }
00091
00092 static ScalarType EdgeLenghtUV(const FaceType *f,int e)
00093 {
00094 assert((e>=0)&&(e<3));
00095 Point2<TexScalarType> uv0,uv1;
00096 if(PerWedgeFlag) {
00097 uv0=f->cWT(e+0).P();
00098 uv1=f->cWT((e+1)%3).P();
00099 } else {
00100 uv0=f->cV0(e)->T().P();
00101 uv1=f->cV1(e)->T().P();
00102 }
00103 ScalarType UVlength=Distance(uv0,uv1);
00104 return UVlength;
00105 }
00106
00107 static ScalarType AngleCos3D(const FaceType *f,int e)
00108 {
00109 assert((e>=0)&&(e<3));
00110 CoordType p0=f->P((e+2)%3);
00111 CoordType p1=f->P(e);
00112 CoordType p2=f->P((e+1)%3);
00113 typedef typename CoordType::ScalarType ScalarType;
00114 CoordType dir0=p2-p1;
00115 CoordType dir1=p0-p1;
00116 dir0.Normalize();
00117 dir1.Normalize();
00118 ScalarType angle=dir0*dir1;
00119 return angle;
00120 }
00121
00122 static ScalarType AngleCosUV(const FaceType *f,int e)
00123 {
00124 Point2<ScalarType> uv0,uv1,uv2;
00125 if(PerWedgeFlag) {
00126 uv0=f->cWT((e+2)%3).P();
00127 uv1=f->cWT((e+0)%3).P();
00128 uv2=f->cWT((e+1)%3).P();
00129 } else {
00130 uv0=f->V2(e)->T().P();
00131 uv1=f->V0(e)->T().P();
00132 uv2=f->V1(e)->T().P();
00133 }
00134 vcg::Point2<ScalarType> dir0=uv2-uv1;
00135 vcg::Point2<ScalarType> dir1=uv0-uv1;
00136 dir0.Normalize();
00137 dir1.Normalize();
00138 ScalarType angle=dir0*dir1;
00139 return angle;
00140 }
00141
00142 static ScalarType AngleRad3D(const FaceType *f,int e)
00143 {
00144 assert((e>=0)&&(e<3));
00145 CoordType p0=f->cP((e+2)%3);
00146 CoordType p1=f->cP(e);
00147 CoordType p2=f->cP((e+1)%3);
00148 typedef typename CoordType::ScalarType ScalarType;
00149 CoordType dir0=p2-p1;
00150 CoordType dir1=p0-p1;
00151 return Angle(dir0,dir1);
00152 }
00153
00154 static ScalarType AngleRadUV(const FaceType *f,int e)
00155 {
00156 Point2<TexScalarType> uv0,uv1,uv2;
00157 if(PerWedgeFlag) {
00158 uv0=f->cWT((e+2)%3).P();
00159 uv1=f->cWT((e+0)%3).P();
00160 uv2=f->cWT((e+1)%3).P();
00161 } else {
00162 uv0=f->cV2(e)->T().P();
00163 uv1=f->cV0(e)->T().P();
00164 uv2=f->cV1(e)->T().P();
00165 }
00166 vcg::Point2<TexScalarType> dir0=uv2-uv1;
00167 vcg::Point2<TexScalarType> dir1=uv0-uv1;
00168 dir0.Normalize();
00169 dir1.Normalize();
00170 ScalarType t=dir0*dir1;
00171 if(t>1) t = 1;
00172 else if(t<-1) t = -1;
00173 return acos(t);
00174 }
00175
00176
00177 public:
00178 enum DistType{AreaDist,EdgeDist,AngleDist,CrossDist,L2Stretch,LInfStretch};
00179
00182 static ScalarType AngleCosDistortion(const FaceType *f,int e)
00183 {
00184 ScalarType Angle_3D=AngleCos3D(f,e);
00185 ScalarType Angle_UV=AngleCosUV(f,e);
00186 ScalarType diff=fabs(Angle_3D-Angle_UV);
00187 return diff;
00188 }
00191 static ScalarType AngleRadDistortion(const FaceType *f,int e)
00192 {
00193 ScalarType Angle_3D=AngleRad3D(f,e);
00194 ScalarType Angle_UV=AngleRadUV(f,e);
00195 ScalarType diff=fabs(Angle_3D-Angle_UV)/Angle_3D;
00196 return diff;
00197 }
00198
00201 static ScalarType AngleDistortion(const FaceType *f)
00202 {
00203 return (AngleRadDistortion(f,0) +
00204 AngleRadDistortion(f,1) +
00205 AngleRadDistortion(f,2))/3.0;
00206 }
00207
00209 static void MeshScalingFactor(const MeshType &m,
00210 ScalarType &AreaScale,
00211 ScalarType &EdgeScale)
00212 {
00213 ScalarType SumArea3D=0;
00214 ScalarType SumArea2D=0;
00215 ScalarType SumEdge3D=0;
00216 ScalarType SumEdge2D=0;
00217 for (size_t i=0;i<m.face.size();i++)
00218 {
00219 SumArea3D+=Area3D(&m.face[i]);
00220 SumArea2D+=AreaUV(&m.face[i]);
00221 for (int j=0;j<3;j++)
00222 {
00223 SumEdge3D+=EdgeLenght3D(&m.face[i],j);
00224 SumEdge2D+=EdgeLenghtUV(&m.face[i],j);
00225 }
00226 }
00227 AreaScale=SumArea3D/SumArea2D;
00228 EdgeScale=SumEdge3D/SumEdge2D;
00229 }
00230
00234 static ScalarType EdgeDistortion(const FaceType *f,int e,
00235 ScalarType EdgeScaleVal)
00236 {
00237 ScalarType edgeUV=EdgeLenghtUV(f,e)*EdgeScaleVal;
00238 ScalarType edge3D=EdgeLenght3D(f,e);
00239 assert(edge3D > 0);
00240 ScalarType diff=fabs(edge3D-edgeUV)/edge3D;
00241 assert(!math::IsNAN(diff));
00242 return diff;
00243 }
00244
00248 static ScalarType AreaDistortion(const FaceType *f,
00249 ScalarType AreaScaleVal)
00250 {
00251 ScalarType areaUV=AreaUV(f)*AreaScaleVal;
00252 ScalarType area3D=Area3D(f);
00253 assert(area3D > 0);
00254 ScalarType diff=fabs(areaUV-area3D)/area3D;
00255 assert(!math::IsNAN(diff));
00256 return diff;
00257 }
00258
00259 static ScalarType L2StretchEnergySquared(const FaceType *f,
00260 ScalarType AreaScaleVal)
00261 {
00262 TexCoordType p0 = (PerWedgeFlag)? f->cWT(0).P() : f->cV(0)->T().P() ;
00263 TexCoordType p1 = (PerWedgeFlag)? f->cWT(1).P() : f->cV(1)->T().P() ;
00264 TexCoordType p2 = (PerWedgeFlag)? f->cWT(2).P() : f->cV(2)->T().P() ;
00265
00266 CoordType q0 = f->cP(0);
00267 CoordType q1 = f->cP(1);
00268 CoordType q2 = f->cP(2);
00269
00270 TexScalarType A2 = ((p1-p0)^(p2-p0));
00271
00272 if (A2<0) A2 = 0;
00273
00274 CoordType Ss = ( q0 * ( p1[1]-p2[1] ) + q1 * (p2[1]-p0[1]) + q2 * (p0[1]-p1[1]) ) / A2;
00275 CoordType St = ( q0 * ( p2[0]-p1[0] ) + q1 * (p0[0]-p2[0]) + q2 * (p1[0]-p0[0]) ) / A2;
00276
00277 ScalarType a = Ss.SquaredNorm() / AreaScaleVal;
00278 ScalarType c = St.SquaredNorm() / AreaScaleVal;
00279
00280 return ((a+c)/2);
00281 }
00282
00283
00284
00285 static ScalarType LInfStretchEnergy(const FaceType *f, ScalarType AreaScaleVal)
00286 {
00287 TexCoordType p0 = (PerWedgeFlag)? f->cWT(0).P() : f->cV(0)->T().P() ;
00288 TexCoordType p1 = (PerWedgeFlag)? f->cWT(1).P() : f->cV(1)->T().P() ;
00289 TexCoordType p2 = (PerWedgeFlag)? f->cWT(2).P() : f->cV(2)->T().P() ;
00290
00291 CoordType q0 = f->cP(0);
00292 CoordType q1 = f->cP(1);
00293 CoordType q2 = f->cP(2);
00294
00295 TexScalarType A2 = ((p1-p0)^(p2-p0));
00296
00297 if (A2<0) A2 = 0;
00298
00299 CoordType Ss = ( q0 * ( p1[1]-p2[1] ) + q1 * (p2[1]-p0[1]) + q2 * (p0[1]-p1[1]) ) / A2;
00300 CoordType St = ( q0 * ( p2[0]-p1[0] ) + q1 * (p0[0]-p2[0]) + q2 * (p1[0]-p0[0]) ) / A2;
00301
00302 ScalarType a = Ss.SquaredNorm() / AreaScaleVal;
00303 ScalarType b = Ss*St / AreaScaleVal;
00304 ScalarType c = St.SquaredNorm() / AreaScaleVal;
00305
00306 ScalarType delta = sqrt((a-c)*(a-c)+4*b*b);
00307 ScalarType G = sqrt( (a+c+delta)/2 );
00308
00309 return G;
00310 }
00311
00312
00314 static bool Folded(const FaceType *f)
00315 {
00316 ScalarType areaUV=AreaUV(f);
00317
00318
00319 return (areaUV<0);
00320 }
00321
00322 static int Folded(const MeshType &m)
00323 {
00324 int folded=0;
00325 for (size_t i=0;i<m.face.size();i++)
00326 {
00327 if (m.face[i].IsD())continue;
00328 if(Folded(&m.face[i]))folded++;
00329 }
00330 return folded;
00331 }
00332
00333 static bool GloballyUnFolded(const MeshType &m)
00334 {
00335 int num=Folded(m);
00336 return (num>(m.fn)/2);
00337 }
00338
00339 static ScalarType MeshAngleDistortion(const MeshType &m)
00340 {
00341 ScalarType UDdist=0;
00342 for (int i=0;i<m.face.size();i++)
00343 {
00344 if (m.face[i].IsD())continue;
00345 const FaceType *f=&(m.face[i]);
00346 UDdist+=AngleDistortion(f)*Area3D(f);
00347 }
00348 return UDdist;
00349 }
00350
00351 static ScalarType SetFQAsCrossDirDistortion(MeshType &m)
00352 {
00353
00354 std::vector<CurVecType> Dir1,Dir2;
00355 for (size_t i=0;i<m.face.size();i++)
00356 {
00357 Dir1.push_back(m.face[i].PD1());
00358 Dir2.push_back(m.face[i].PD2());
00359 }
00360 vcg::tri::CrossField<MeshType>::InitDirFromWEdgeUV(m);
00361
00362 ScalarType tot = 0, totA = 0;
00363
00364
00365 for (size_t i=0;i<m.face.size();i++)
00366 {
00367
00368 FaceType &f( m.face[i] );
00369 CoordType transfPD1=vcg::tri::CrossField<MeshType>::K_PI(CoordType::Construct( Dir1[i] ),
00370 CoordType::Construct( f.PD1() ),
00371 f.N());
00372 transfPD1.Normalize();
00373 ScalarType AngleDeficit=vcg::Angle(transfPD1,CoordType::Construct( f.PD1() ));
00374 AngleDeficit=math::ToDeg(AngleDeficit);
00375 if ((AngleDeficit>45)||(AngleDeficit<0))
00376 {
00377 std::cout<<"Warnign A Deficit "<<AngleDeficit<<std::endl;
00378 }
00379
00380
00381
00382 ScalarType doubleArea = vcg::DoubleArea( f );
00383 ScalarType distortion = (AngleDeficit)/ 45 ;
00384
00385 m.face[i].Q()= distortion;
00386 tot += distortion * doubleArea;
00387 totA += doubleArea;
00388 }
00389
00390
00391 for (size_t i=0;i<m.face.size();i++)
00392 {
00393 m.face[i].PD1()=Dir1[i];
00394 m.face[i].PD2()=Dir2[i];
00395 }
00396
00397 return tot / totA;
00398 }
00399
00400 static ScalarType SetQasDistorsion(MeshType &m, DistType DType=AreaDist)
00401 {
00402 if (DType==CrossDist)
00403 {
00404 ScalarType res = SetFQAsCrossDirDistortion(m);
00405
00406 vcg::tri::UpdateQuality<MeshType>::VertexFromFace(m,true);
00407 return res;
00408 }
00409
00410 ScalarType edge_scale,area_scale;
00411 MeshScalingFactor(m,area_scale,edge_scale);
00412
00413 float tot = 0;
00414 float totA = 0;
00415
00416 for (int i=0;i<m.face.size();i++)
00417 {
00418 if (m.face[i].IsD())continue;
00419 ScalarType q;
00420 switch (DType) {
00421 case CrossDist:
00422
00423 q = 0;
00424 break;
00425 case AreaDist:
00426 q = AreaDistortion(&m.face[i],area_scale);
00427 break;
00428 case AngleDist:
00429 q = AngleDistortion(&m.face[i]);
00430 break;
00431 case EdgeDist:
00432 q =( EdgeDistortion(&m.face[i],0,edge_scale)+
00433 EdgeDistortion(&m.face[i],1,edge_scale)+
00434 EdgeDistortion(&m.face[i],2,edge_scale) )/3;
00435 break;
00436 case L2Stretch:
00437 q = L2StretchEnergySquared( &m.face[i],area_scale );
00438 break;
00439 case LInfStretch:
00440 q = LInfStretchEnergy( &m.face[i],area_scale );
00441 break;
00442 }
00443
00444 m.face[i].Q() = q;
00445
00446
00447 if (DType==LInfStretch) {
00448 tot = std::max( tot, q );
00449 } else {
00450 ScalarType a = Area3D(&m.face[i]);
00451 tot += q*a;
00452 totA += a;
00453 }
00454
00455 }
00456
00457 vcg::tri::UpdateQuality<MeshType>::VertexFromFace(m,true);
00458
00459 switch (DType) {
00460 case L2Stretch: return sqrt(tot/totA);
00461 case LInfStretch: return tot;
00462 default: return tot/totA;
00463 }
00464 }
00465 };
00466
00467 }}
00468
00469 #endif