distortion.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
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  *  Energy types:
00036  *
00037  *    AreaDist : 0 for equiareal (equipotent) mappings
00038  *    EdgeDist (hack): 0 for isometric mappings (computed on edges only)
00039  *    AngleDist (hack): 0 for conformal mappings
00040  *    CrossDist : as above, but computed on tangent directions (not UVs)
00041  *    L2Stretch : 1 for isometric mappings (averaged case on the mesh),
00042  *                +inf on degenerate / folded cases
00043  *                Described in [1]
00044  *    LInfStretch : as above, but WORST case
00045  *                  (returns the worst stretch on any position and direction)
00046  *                  Described in [1]
00047  *
00048  * [1] Sander, P. V., Snyder, J., Gortler, S. J., & Hoppe, H.
00049  *     "Texture mapping progressive meshes."
00050  *      In Proc. ACM SIGGRAPH (pp. 409-416). 2001
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; // will be NAN, +infinity
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; // will be NAN, +infinity
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         //ScalarType g = sqrt( (a+c-delta)/2 ); // not needed
00309         return G;
00310     }
00311 
00312 
00314     static bool Folded(const FaceType *f)
00315     {
00316         ScalarType areaUV=AreaUV(f);
00317         /*if (areaUV<0)
00318                     printf("area %5.5f \n",areaUV);*/
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         //first save the old UV dir
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         //then compute angle deficit
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 //            assert(AngleDeficit<45);
00380 //            assert(AngleDeficit>=0);
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         //finally restore the original directions
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                 // make compiler happy
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; // note: for L2Stretch, we are puttning E^2 on Q
00445 
00446             // aggregate:
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 }} // namespace end
00468 
00469 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:30:43