Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
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
00239
00240
00241
00242
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
00253
00254
00255
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();
00270
00271
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
00289 if( distGeom < fabs(qi - fc->Q()))
00290 {
00291
00292
00293 if(fc->Q() > qi)
00294 {
00295
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
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
00311 qi = newQi;
00312 (*ffi)->ClearV();
00313 }
00314 }
00315 if(!(*ffi)->IsV())
00316 {
00317 st.push( *ffi);
00318
00319 (*ffi)->SetV();
00320 }
00321 }
00322 }
00323 }
00324
00325
00326
00327
00328
00329
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();
00341
00342
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
00353 if( distGeom < fabs(qi - vc->Q()))
00354 {
00355
00356
00357 if(vc->Q() > qi)
00358 {
00359
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
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
00375 qi = newQi;
00376 (*vvi)->ClearV();
00377 }
00378 }
00379 if(!(*vvi)->IsV())
00380 {
00381 st.push( *vvi);
00382
00383 (*vvi)->SetV();
00384 }
00385 }
00386 }
00387 }
00388
00389
00390 };
00391 }
00392 }
00393 #endif