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 <algorithm>
00027 #include <vector>
00028 #include <stack>
00029 #include <assert.h>
00030
00031 namespace vcg {
00032 namespace tri {
00034
00036
00038
00047 template <class UpdateMeshType>
00048 class UpdateQuality
00049 {
00050 public:
00051 typedef UpdateMeshType MeshType;
00052 typedef typename MeshType::ScalarType ScalarType;
00053 typedef typename MeshType::VertexType VertexType;
00054 typedef typename MeshType::VertexPointer VertexPointer;
00055 typedef typename MeshType::VertexIterator VertexIterator;
00056 typedef typename MeshType::FaceType FaceType;
00057 typedef typename MeshType::FacePointer FacePointer;
00058 typedef typename MeshType::FaceIterator FaceIterator;
00059
00060 class VQualityHeap
00061 {
00062 public:
00063 float q;
00064 VertexPointer p;
00065 inline VQualityHeap( VertexPointer np )
00066 {
00067 q = np->Q();
00068 p = np;
00069 }
00070
00071 inline bool operator < ( const VQualityHeap & vq ) const { return q > vq.q; }
00072 inline bool operator == ( const VQualityHeap & vq ) const { return q == vq.q; }
00073 inline bool operator > ( const VQualityHeap & vq ) const { return q < vq.q; }
00074 inline bool operator != ( const VQualityHeap & vq ) const { return q != vq.q; }
00075 inline bool operator <= ( const VQualityHeap & vq ) const { return q >= vq.q; }
00076 inline bool operator >= ( const VQualityHeap & vq ) const { return q <= vq.q; }
00077 inline bool is_valid() const { return q==p->Q(); }
00078 };
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00097
00105 static void VertexGeodesicFromBorder(MeshType &m)
00106 {
00107
00108 assert(m.HasVFTopology());
00109 assert(m.HasPerVertexQuality());
00110
00111 std::vector< VQualityHeap > heap;
00112 VertexIterator v;
00113 FaceIterator f;
00114 int j;
00115
00116 for(v=m.vert.begin();v!=m.vert.end();++v)
00117 (*v).Q() = -1;
00118 for(f=m.face.begin();f!=m.face.end();++f)
00119 if(!(*f).IsD())
00120 for(j=0;j<3;++j)
00121 if( (*f).IsB(j) )
00122 {
00123 for(int k=0;k<2;++k)
00124 {
00125 VertexPointer pv = (*f).V((j+k)%3);
00126 if( pv->Q()==-1 )
00127 {
00128 pv->Q() = 0;
00129 heap.push_back(VQualityHeap(pv));
00130 }
00131 }
00132 }
00133
00134 const ScalarType loc_eps=m.bbox.Diag()/ScalarType(100000);
00135 while( heap.size()!=0 )
00136 {
00137 VertexPointer pv;
00138 std::pop_heap(heap.begin(),heap.end());
00139 if( ! heap.back().is_valid() )
00140 {
00141 heap.pop_back();
00142 continue;
00143 }
00144 pv = heap.back().p;
00145 heap.pop_back();
00146
00147 for(face::VFIterator<FaceType> vfi(pv) ; !vfi.End(); ++vfi )
00148 {
00149 for(int k=0;k<2;++k)
00150 {
00151 VertexPointer pw;
00152 float d;
00153 if(k==0) pw = vfi.f->V1(vfi.z);
00154 else pw = vfi.f->V2(vfi.z);
00155 d = Distance(pv->P(),pw->P());
00156 if( pw->Q()==-1 || pw->Q() > pv->Q()+d + loc_eps)
00157 {
00158 pw->Q() = pv->Q()+d;
00159 heap.push_back(VQualityHeap(pw));
00160 std::push_heap(heap.begin(),heap.end());
00161 }
00162 }
00163 }
00164 }
00165
00166 for(v=m.vert.begin();v!=m.vert.end();++v)
00167 if(v->Q()==-1)
00168 v->Q() = 0;
00169 }
00170
00171
00174 static void VertexConstant(MeshType &m, float q)
00175 {
00176 VertexIterator vi;
00177 for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00178 (*vi).Q()=q;
00179 }
00180
00183 static void VertexClamp(MeshType &m, float qmin, float qmax)
00184 {
00185 VertexIterator vi;
00186 for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00187 (*vi).Q()=std::min(qmax, std::max(qmin,(*vi).Q()));
00188 }
00189
00192 static void FaceConstant(MeshType &m, float q)
00193 {
00194 FaceIterator fi;
00195 for(fi=m.face.begin();fi!=m.face.end();++fi)
00196 (*fi).Q()=q;
00197 }
00198
00199
00200 static void VertexFromGaussianCurvature(MeshType &m)
00201 {
00202 VertexIterator vi;
00203 for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00204 (*vi).Q() = (*vi).Kg();
00205 }
00206
00207 static void VertexFromMeanCurvature(MeshType &m)
00208 {
00209 VertexIterator vi;
00210 for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00211 (*vi).Q() = (*vi).Kh();
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 static void VertexFromAbsoluteCurvature(MeshType &m)
00231 {
00232 VertexIterator vi;
00233 for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00234 {
00235 if((*vi).Kg() >= 0)
00236 (*vi).Q() = math::Abs( 2*(*vi).Kh() );
00237 else
00238 (*vi).Q() = 2*math::Sqrt(math::Abs( (*vi).Kh()*(*vi).Kh() - (*vi).Kg()));
00239 }
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249 static void VertexFromRMSCurvature(MeshType &m)
00250 {
00251 VertexIterator vi;
00252 for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
00253 (*vi).Q() = math::Sqrt(math::Abs( 4*(*vi).Kh()*(*vi).Kh() - 2*(*vi).Kg()));
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 static void VertexSaturate(MeshType &m, ScalarType gradientThr=1.0)
00265 {
00266 UpdateFlags<MeshType>::VertexClearV(m);
00267 std::stack<VertexPointer> st;
00268
00269 st.push(&*m.vert.begin());
00270
00271 while(!st.empty())
00272 {
00273 VertexPointer vc = st.top();
00274
00275
00276 st.pop();
00277 vc->SetV();
00278 std::vector<VertexPointer> star;
00279 typename std::vector<VertexPointer>::iterator vvi;
00280 face::VVStarVF<FaceType>(vc,star);
00281 for(vvi=star.begin();vvi!=star.end();++vvi )
00282 {
00283 float &qi = (*vvi)->Q();
00284 float distGeom = Distance((*vvi)->cP(),vc->cP()) / gradientThr;
00285
00286 if( distGeom < fabs(qi - vc->Q()))
00287 {
00288
00289
00290 if(vc->Q() > qi)
00291 {
00292
00293 vc->Q() = qi+distGeom-0.00001f;
00294 assert( distGeom > fabs(qi - vc->Q()));
00295 st.push(vc);
00296 break;
00297 }
00298 else
00299 {
00300
00301 assert( distGeom < fabs(qi - vc->Q()));
00302 assert(vc->Q() < qi);
00303 float newQi = vc->Q() + distGeom -0.00001f;
00304 assert(newQi <= qi);
00305 assert(vc->Q() < newQi);
00306 assert( distGeom > fabs(newQi - vc->Q()) );
00307
00308 qi = newQi;
00309 (*vvi)->ClearV();
00310 }
00311 }
00312 if(!(*vvi)->IsV())
00313 {
00314 st.push( *vvi);
00315
00316 (*vvi)->SetV();
00317 }
00318 }
00319 }
00320 }
00321
00322
00323 };
00324 }
00325 }
00326 #endif