quality.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 #ifndef __VCG_TRI_UPDATE_QUALITY
00024 #define __VCG_TRI_UPDATE_QUALITY
00025 #include <vcg/simplex/face/pos.h>
00026 #include <vcg/simplex/face/topology.h>
00027 #include <vcg/complex/algorithms/update/flag.h>
00028 #include <vcg/complex/algorithms/stat.h>
00029 
00030 namespace vcg {
00031 namespace tri {
00033 
00035 
00037 
00046 template <class UpdateMeshType>
00047 class UpdateQuality
00048 {
00049 public:
00050   typedef UpdateMeshType MeshType;
00051   typedef typename MeshType::ScalarType     ScalarType;
00052   typedef typename MeshType::VertexType     VertexType;
00053   typedef typename MeshType::VertexPointer  VertexPointer;
00054   typedef typename MeshType::VertexIterator VertexIterator;
00055   typedef typename MeshType::FaceType       FaceType;
00056   typedef typename MeshType::FacePointer    FacePointer;
00057   typedef typename MeshType::FaceIterator   FaceIterator;
00058 
00061 static void VertexConstant(MeshType &m, ScalarType q)
00062 {
00063   tri::RequirePerVertexQuality(m);
00064   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00065     (*vi).Q()=q;
00066 }
00067 
00070 static void VertexClamp(MeshType &m,
00071                         typename MeshType::VertexType::QualityType qmin,
00072                         typename MeshType::VertexType::QualityType qmax)
00073 {
00074   tri::RequirePerVertexQuality(m);
00075   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00076     (*vi).Q()=std::min(qmax, std::max(qmin,(*vi).Q()));
00077 }
00078 
00081 static void VertexNormalize(MeshType &m, float qmin=0.0, float qmax=1.0)
00082 {
00083   tri::RequirePerVertexQuality(m);
00084   ScalarType deltaRange = qmax-qmin;
00085   std::pair<ScalarType,ScalarType> minmax = tri::Stat<MeshType>::ComputePerVertexQualityMinMax(m);
00086   VertexIterator vi;
00087   for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
00088     (*vi).Q() = qmin+deltaRange*((*vi).Q() - minmax.first)/(minmax.second - minmax.first);
00089 }
00090 
00093 static void FaceNormalize(MeshType &m, float qmin=0.0, float qmax=1.0)
00094 {
00095   tri::RequirePerFaceQuality(m);
00096   ScalarType deltaRange = qmax-qmin;
00097   std::pair<ScalarType,ScalarType> minmax = tri::Stat<MeshType>::ComputePerFaceQualityMinMax(m);
00098   for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
00099     (*fi).Q() = qmin+deltaRange*((*fi).Q() - minmax.first)/(minmax.second - minmax.first);
00100 }
00101 
00104 static void FaceConstant(MeshType &m, float q)
00105 {
00106   tri::RequirePerFaceQuality(m);
00107   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00108     (*fi).Q()=q;
00109 }
00110 
00113 static void FaceArea(MeshType &m)
00114 {
00115   tri::RequirePerFaceQuality(m);
00116   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00117     (*fi).Q()=vcg::DoubleArea(*fi)/ScalarType(2.0);
00118 }
00119 
00120 static void VertexFromFace( MeshType &m, bool areaWeighted=true)
00121 {
00122   tri::RequirePerFaceQuality(m);
00123   tri::RequirePerVertexQuality(m);
00124   SimpleTempData<typename MeshType::VertContainer, ScalarType> TQ(m.vert,0);
00125   SimpleTempData<typename MeshType::VertContainer, ScalarType> TCnt(m.vert,0);
00126 
00127   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00128     if(!(*fi).IsD())
00129     {
00130       ScalarType weight=1.0;
00131       if(areaWeighted) weight = vcg::DoubleArea(*fi);
00132       for(int j=0;j<3;++j)
00133       {
00134         TQ[(*fi).V(j)]+=(*fi).Q()*weight;
00135         TCnt[(*fi).V(j)]+=weight;
00136       }
00137     }
00138 
00139   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
00140     if(!(*vi).IsD() && TCnt[*vi]>0 )
00141     {
00142       (*vi).Q() = TQ[*vi] / TCnt[*vi];
00143     }
00144 }
00145 
00146 template <class HandleScalar>
00147 static void VertexFromAttributeHandle(MeshType &m, typename MeshType::template PerVertexAttributeHandle<HandleScalar> &h)
00148 {
00149   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
00150     if(!(*vi).IsD())
00151       (*vi).Q()=ScalarType(h[vi]);
00152 }
00153 
00154 template <class HandleScalar>
00155 static void FaceFromAttributeHandle(MeshType &m, typename MeshType::template PerFaceAttributeHandle<HandleScalar> &h)
00156 {
00157   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
00158     (*fi).Q() =h[fi];
00159 }
00160 
00161 static void FaceFromVertex( MeshType &m)
00162 {
00163   tri::RequirePerFaceQuality(m);
00164   tri::RequirePerVertexQuality(m);
00165   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
00166   {
00167     (*fi).Q() = ((*fi).V(0)->Q()+(*fi).V(1)->Q()+(*fi).V(2)->Q())/3.0f;
00168   }
00169 }
00170 
00171 static void VertexFromPlane(MeshType &m, const Plane3<ScalarType> &pl)
00172 {
00173   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00174     (*vi).Q() =SignedDistancePlanePoint(pl,(*vi).cP());
00175 }
00176 
00177 static void VertexFromGaussianCurvatureHG(MeshType &m)
00178 {
00179   tri::RequirePerVertexQuality(m);
00180   tri::RequirePerVertexCurvature(m);
00181     for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00182         (*vi).Q() = (*vi).Kg();
00183 }
00184 
00185 static void VertexFromMeanCurvatureHG(MeshType &m)
00186 {
00187   tri::RequirePerVertexQuality(m);
00188   tri::RequirePerVertexCurvature(m);
00189     for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00190         (*vi).Q() = (*vi).Kh();
00191 }
00192 
00193 static void VertexFromGaussianCurvatureDir(MeshType &m)
00194 {
00195   tri::RequirePerVertexQuality(m);
00196   tri::RequirePerVertexCurvatureDir(m);
00197     for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00198       (*vi).Q() = (*vi).K1()*(*vi).K2();
00199 }
00200 
00201 static void VertexFromMeanCurvatureDir(MeshType &m)
00202 {
00203   tri::RequirePerVertexQuality(m);
00204   tri::RequirePerVertexCurvatureDir(m);
00205     for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00206         (*vi).Q() = ((*vi).K1()+(*vi).K2())/2.0f;
00207 }
00208 
00209 /*
00210  *  Absolute Curvature
00211  *
00212  *                  2|H|                if K >= 0
00213  *  |k1| + |k2| = <
00214  *                  2 * sqrt(|H|^2-K)   otherwise
00215  *
00216  * defs and formulas taken from
00217  *
00218  * Improved curvature estimation for watershed segmentation of 3-dimensional meshes
00219  * S Pulla, A Razdan, G Farin - Arizona State University, Tech. Rep, 2001
00220  * and from
00221  * Optimizing 3D triangulations using discrete curvature analysis
00222  * N Dyn, K Hormann, SJ Kim, D Levin - Mathematical Methods for Curves and Surfaces: Oslo, 2000
00223  */
00224 
00225 static void VertexFromAbsoluteCurvature(MeshType &m)
00226 {
00227     VertexIterator vi;
00228     for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00229     {
00230         if((*vi).Kg() >= 0)
00231                     (*vi).Q() = math::Abs( 2*(*vi).Kh() );
00232         else
00233               (*vi).Q() = 2*math::Sqrt(math::Abs( (*vi).Kh()*(*vi).Kh() - (*vi).Kg()));
00234     }
00235 }
00236 
00237 /*
00238  * RMS Curvature =   sqrt(4H^2-2K)
00239  * def and formula taken from
00240  *
00241  * Improved curvature estimation for watershed segmentation of 3-dimensional meshes
00242  * S Pulla, A Razdan, G Farin - Arizona State University, Tech. Rep, 2001
00243  */
00244 static void VertexFromRMSCurvature(MeshType &m)
00245 {
00246     VertexIterator vi;
00247     for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00248         (*vi).Q() = math::Sqrt(math::Abs( 4*(*vi).Kh()*(*vi).Kh() - 2*(*vi).Kg()));
00249 }
00250 
00251 /*
00252   Saturate the Face quality so that for each vertex the gradient of the quality is lower than the given threshold value (in absolute value)
00253   The saturation is done in a conservative way (quality is always decreased and never increased)
00254 
00255   Note: requires FF adjacency.
00256   */
00257 static void FaceSaturate(MeshType &m, ScalarType gradientThr=1.0)
00258 {
00259   typedef typename MeshType::CoordType CoordType;
00260   typedef typename MeshType::ScalarType ScalarType;
00261 
00262   UpdateFlags<MeshType>::FaceClearV(m);
00263   std::stack<FacePointer> st;
00264 
00265   st.push(&*m.face.begin());
00266 
00267   while(!st.empty())
00268     {
00269      FacePointer fc = st.top();  // the center
00270      //printf("Stack size %i\n",st.size());
00271      //printf("Pop elem %i %f\n",st.top() - &*m.vert.begin(), st.top()->Q());
00272      st.pop();
00273      fc->SetV();
00274      std::vector<FacePointer> star;
00275      typename std::vector<FacePointer>::iterator ffi;
00276      for (int i=0;i<3;i++)
00277      {
00278          FacePointer fnext=fc->FFp(i);
00279          if (fnext!=fc)star.push_back(fnext);
00280      }
00281      CoordType bary0=(fc->P(0)+fc->P(1)+fc->P(2))/3;
00282      for(ffi=star.begin();ffi!=star.end();++ffi )
00283      {
00284        assert(fc!=(*ffi));
00285        ScalarType &qi = (*ffi)->Q();
00286        CoordType bary1=((*ffi)->P(0)+(*ffi)->P(1)+(*ffi)->P(2))/3;
00287        ScalarType distGeom = Distance(bary0,bary1) / gradientThr;
00288        // Main test if the quality varies more than the geometric displacement we have to lower something.
00289        if( distGeom < fabs(qi - fc->Q()))
00290        {
00291          // center = 0  other=10 -> other =
00292          // center = 10 other=0
00293          if(fc->Q() > qi)  // first case: the center of the star has to be lowered (and re-inserted in the queue).
00294          {
00295            //printf("Reinserting center %i \n",vc - &*m.vert.begin());
00296            fc->Q() = qi+distGeom-(ScalarType)0.00001;
00297            assert( distGeom > fabs(qi - fc->Q()));
00298            st.push(fc);
00299            break;
00300          }
00301          else
00302          {
00303            // second case: you have to lower qi, the vertex under examination.
00304            assert( distGeom < fabs(qi - fc->Q()));
00305            assert(fc->Q() < qi);
00306            float newQi = fc->Q() + distGeom -(ScalarType)0.00001;
00307            assert(newQi <= qi);
00308            assert(fc->Q() < newQi);
00309            assert( distGeom > fabs(newQi - fc->Q()) );
00310 //             printf("distGeom %f, qi %f, vc->Q() %f, fabs(qi - vc->Q()) %f\n",distGeom,qi,vc->Q(),fabs(qi - vc->Q()));
00311            qi = newQi;
00312            (*ffi)->ClearV();
00313          }
00314        }
00315        if(!(*ffi)->IsV())
00316        {
00317          st.push( *ffi);
00318 //         printf("Reinserting side %i \n",*vvi - &*m.vert.begin());
00319          (*ffi)->SetV();
00320        }
00321      }
00322     }
00323   }
00324 
00325 /*
00326   Saturate the vertex quality so that for each vertex the gradient of the quality is lower than the given threshold value (in absolute value)
00327   The saturation is done in a conservative way (quality is always decreased and never increased)
00328 
00329   Note: requires VF adjacency.
00330   */
00331 static void VertexSaturate(MeshType &m, ScalarType gradientThr=1.0)
00332 {
00333   UpdateFlags<MeshType>::VertexClearV(m);
00334   std::stack<VertexPointer> st;
00335 
00336   st.push(&*m.vert.begin());
00337 
00338   while(!st.empty())
00339     {
00340      VertexPointer vc = st.top();  // the center
00341      //printf("Stack size %i\n",st.size());
00342      //printf("Pop elem %i %f\n",st.top() - &*m.vert.begin(), st.top()->Q());
00343      st.pop();
00344      vc->SetV();
00345      std::vector<VertexPointer> star;
00346      typename std::vector<VertexPointer>::iterator vvi;
00347      face::VVStarVF<FaceType>(vc,star);
00348      for(vvi=star.begin();vvi!=star.end();++vvi )
00349      {
00350        ScalarType &qi = (*vvi)->Q();
00351        ScalarType distGeom = Distance((*vvi)->cP(),vc->cP()) / gradientThr;
00352        // Main test if the quality varies more than the geometric displacement we have to lower something.
00353        if( distGeom < fabs(qi - vc->Q()))
00354        {
00355          // center = 0  other=10 -> other =
00356          // center = 10 other=0
00357          if(vc->Q() > qi)  // first case: the center of the star has to be lowered (and re-inserted in the queue).
00358          {
00359            //printf("Reinserting center %i \n",vc - &*m.vert.begin());
00360            vc->Q() = qi+distGeom-(ScalarType)0.00001;
00361            assert( distGeom > fabs(qi - vc->Q()));
00362            st.push(vc);
00363            break;
00364          }
00365          else
00366          {
00367            // second case: you have to lower qi, the vertex under examination.
00368            assert( distGeom < fabs(qi - vc->Q()));
00369            assert(vc->Q() < qi);
00370            float newQi = vc->Q() + distGeom -(ScalarType)0.00001;
00371            assert(newQi <= qi);
00372            assert(vc->Q() < newQi);
00373            assert( distGeom > fabs(newQi - vc->Q()) );
00374 //             printf("distGeom %f, qi %f, vc->Q() %f, fabs(qi - vc->Q()) %f\n",distGeom,qi,vc->Q(),fabs(qi - vc->Q()));
00375            qi = newQi;
00376            (*vvi)->ClearV();
00377          }
00378        }
00379        if(!(*vvi)->IsV())
00380        {
00381          st.push( *vvi);
00382 //         printf("Reinserting side %i \n",*vvi - &*m.vert.begin());
00383          (*vvi)->SetV();
00384        }
00385      }
00386     }
00387   }
00388 
00389 
00390 }; //end class
00391 } // end namespace
00392 } // end namespace
00393 #endif


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