23 #ifndef __VCG_TRI_UPDATE_QUALITY
24 #define __VCG_TRI_UPDATE_QUALITY
25 #include <vcg/complex/algorithms/stat.h>
43 template <
class UpdateMeshType>
47 typedef UpdateMeshType MeshType;
48 typedef typename MeshType::ScalarType ScalarType;
49 typedef typename MeshType::CoordType CoordType;
50 typedef typename MeshType::VertexType VertexType;
51 typedef typename MeshType::VertexPointer VertexPointer;
52 typedef typename MeshType::VertexIterator VertexIterator;
53 typedef typename MeshType::FaceType FaceType;
54 typedef typename MeshType::FacePointer FacePointer;
55 typedef typename MeshType::FaceIterator FaceIterator;
56 typedef typename MeshType::VertexType::QualityType VertexQualityType;
57 typedef typename MeshType::FaceType::QualityType FaceQualityType;
58 typedef typename MeshType::TetraType TetraType;
59 typedef typename MeshType::TetraPointer TetraPointer;
60 typedef typename MeshType::TetraIterator TetraIterator;
61 typedef typename MeshType::TetraType::QualityType TetraQualityType;
69 tri::RequirePerVertexQuality(m);
70 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
78 tri::RequirePerVertexQuality(m);
80 for (
size_t i=0;i<m.face.size();i++)
82 if (m.face[i].IsD())
continue;
84 for (
int j=0;j<m.face[i].VN();j++)
86 VertexType *v=m.face[i].V(j);
95 VertexQualityType qmin,
96 VertexQualityType qmax)
98 tri::RequirePerVertexQuality(m);
99 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
100 (*vi).Q()=std::min(qmax, std::max(qmin,(*vi).Q()));
105 static void VertexNormalize(MeshType &m, VertexQualityType qmin=0.0, VertexQualityType qmax=1.0)
107 tri::RequirePerVertexQuality(m);
108 ScalarType deltaRange = qmax-qmin;
109 std::pair<ScalarType,ScalarType> minmax = tri::Stat<MeshType>::ComputePerVertexQualityMinMax(m);
111 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
112 (*vi).Q() = qmin+deltaRange*((*vi).Q() - minmax.first)/(minmax.second - minmax.first);
117 static void FaceNormalize(MeshType &m, FaceQualityType qmin=0.0, FaceQualityType qmax=1.0)
119 tri::RequirePerFaceQuality(m);
120 FaceQualityType deltaRange = qmax-qmin;
121 std::pair<FaceQualityType,FaceQualityType> minmax = tri::Stat<MeshType>::ComputePerFaceQualityMinMax(m);
122 for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
123 (*fi).Q() = qmin+deltaRange*((*fi).Q() - minmax.first)/(minmax.second - minmax.first);
130 tri::RequirePerFaceQuality(m);
131 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
139 tri::RequirePerFaceQuality(m);
140 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
141 (*fi).Q()=FaceQualityType(vcg::DoubleArea(*fi)/ScalarType(2.0));
144 static void TetraConstant(MeshType & m,
const TetraQualityType q)
146 tri::RequirePerTetraQuality(m);
151 static void TetraFromVolume(MeshType & m)
153 tri::RequirePerTetraQuality(m);
155 t.Q() = TetraQualityType(vcg::Tetra::ComputeVolume(t));
159 static void TetraFromAspectRatio(MeshType & m)
161 tri::RequirePerTetraQuality(m);
163 t.Q() = TetraQualityType(vcg::Tetra::AspectRatio(t));
167 static void VertexFromFace( MeshType &m,
bool areaWeighted=
true)
169 tri::RequirePerFaceQuality(m);
170 tri::RequirePerVertexQuality(m);
171 SimpleTempData<typename MeshType::VertContainer, ScalarType> TQ(m.vert,0);
172 SimpleTempData<typename MeshType::VertContainer, ScalarType> TCnt(m.vert,0);
174 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
177 VertexQualityType weight=1.0;
178 if(areaWeighted) weight = vcg::DoubleArea(*fi);
181 TQ[(*fi).V(j)]+=(*fi).Q()*weight;
182 TCnt[(*fi).V(j)]+=weight;
186 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
187 if(!(*vi).IsD() && TCnt[*vi]>0 )
189 (*vi).Q() = TQ[*vi] / TCnt[*vi];
193 static void VertexFromTetra(MeshType & m,
bool volumeWeighted =
true)
195 tri::RequirePerTetraQuality(m);
196 tri::RequirePerVertexQuality(m);
198 SimpleTempData<typename MeshType::VertContainer, ScalarType> TQ(m.vert, 0);
199 SimpleTempData<typename MeshType::VertContainer, ScalarType> TCnt(m.vert, 0);
202 TetraQualityType w = 1.;
204 w = vcg::Tetra::ComputeVolume(t);
206 for (
int i = 0; i < 4; ++i)
208 TQ[t.V(i)] += t.Q() * w;
214 v.Q() = TQ[v] / TCnt[v];
218 template <
class HandleScalar>
219 static void VertexFromAttributeHandle(MeshType &m,
typename MeshType::template PerVertexAttributeHandle<HandleScalar> &h)
221 tri::RequirePerVertexQuality(m);
222 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
224 (*vi).Q()=VertexQualityType(h[vi]);
227 static void VertexFromAttributeName(MeshType &m,
const std::string &AttrName)
229 tri::RequirePerVertexQuality(m);
230 auto KH = tri::Allocator<MeshType>:: template FindPerVertexAttribute<ScalarType> (m, AttrName);
231 if(!tri::Allocator<MeshType>::template IsValidHandle<ScalarType>(m, KH))
throw vcg::MissingPreconditionException(
"Required Attribute is non existent");
232 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
236 template <
class HandleScalar>
237 static void FaceFromAttributeHandle(MeshType &m,
typename MeshType::template PerFaceAttributeHandle<HandleScalar> &h)
239 tri::RequirePerFaceQuality(m);
240 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
241 (*fi).Q() =FaceQualityType(h[fi]);
244 static void FaceFromAttributeName(MeshType &m,
const std::string &AttrName)
246 tri::RequirePerFaceQuality(m);
247 auto KH = tri::Allocator<MeshType>:: template FindPerFaceAttribute<ScalarType> (m, AttrName);
248 if(!tri::Allocator<MeshType>::template IsValidHandle<ScalarType>(m, KH))
throw vcg::MissingPreconditionException(
"Required Attribute is non existent");
249 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
250 (*fi).Q() =FaceQualityType(KH[fi]);
253 static void FaceFromVertex( MeshType &m)
255 tri::RequirePerFaceQuality(m);
256 tri::RequirePerVertexQuality(m);
257 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if(!(*fi).IsD())
260 for (
int i=0;i<(*fi).VN();i++)
261 (*fi).Q() += (*fi).V(i)->Q();
262 (*fi).Q()/=(FaceQualityType)(*fi).VN();
266 static void VertexFromPlane(MeshType &m,
const Plane3<ScalarType> &pl)
268 tri::RequirePerVertexQuality(m);
269 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
270 (*vi).Q() =SignedDistancePlanePoint(pl,(*vi).cP());
273 static void VertexGaussianFromCurvatureDir(MeshType &m)
275 tri::RequirePerVertexQuality(m);
276 tri::RequirePerVertexCurvatureDir(m);
277 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
278 (*vi).Q() = (*vi).K1()*(*vi).K2();
281 static void VertexMeanFromCurvatureDir(MeshType &m)
283 tri::RequirePerVertexQuality(m);
284 tri::RequirePerVertexCurvatureDir(m);
285 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
286 (*vi).Q() = ((*vi).K1()+(*vi).K2())/2.0f;
288 static void VertexMinCurvFromCurvatureDir(MeshType &m)
290 tri::RequirePerVertexQuality(m);
291 tri::RequirePerVertexCurvatureDir(m);
292 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
293 (*vi).Q() = (*vi).K1();
295 static void VertexMaxCurvFromCurvatureDir(MeshType &m)
297 tri::RequirePerVertexQuality(m);
298 tri::RequirePerVertexCurvatureDir(m);
299 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
300 (*vi).Q() = (*vi).K2();
316 tri::RequirePerVertexQuality(m);
317 tri::RequirePerVertexCurvatureDir(m);
318 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
320 ScalarType k1=(*vi).K1();
321 ScalarType k2=(*vi).K2();
322 if(k1<k2) std::swap(k1,k2);
323 (*vi).Q() = (2.0/M_PI)*atan2(k1+k2,k1-k2);
338 tri::RequirePerVertexQuality(m);
339 tri::RequirePerVertexCurvatureDir(m);
340 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
342 const ScalarType k1=(*vi).K1();
343 const ScalarType k2=(*vi).K2();
345 (*vi).Q() = math::Sqrt((k1*k1+k2*k2)/2.0);
366 static void VertexAbsoluteCurvatureFromHGAttribute(MeshType &m)
368 tri::RequirePerVertexQuality(m);
371 for(
auto vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
374 (*vi).Q() = math::Abs( 2.0*KH[vi] );
376 (*vi).Q() = 2*math::Sqrt(math::Abs( KH[vi]*KH[vi] - KG[vi]));
387 static void VertexRMSCurvatureFromHGAttribute(MeshType &m)
389 tri::RequirePerVertexQuality(m);
392 for(
auto vi=m.vert.begin();vi!=m.vert.end();++vi)
if(!(*vi).IsD())
393 (*vi).Q() = math::Sqrt(math::Abs( 4*KH[vi]*KH[vi] - 2*KG[vi]));
402 static void FaceSaturate(MeshType &m, FaceQualityType gradientThr=1.0)
404 tri::RequirePerFaceQuality(m);
405 tri::RequireFFAdjacency(m);
406 UpdateFlags<MeshType>::FaceClearV(m);
407 std::stack<FacePointer> st;
409 st.push(&*m.face.begin());
413 FacePointer fc = st.top();
418 std::vector<FacePointer> star;
419 typename std::vector<FacePointer>::iterator ffi;
420 for (
int i=0;i<3;i++)
422 FacePointer fnext=fc->FFp(i);
423 if (fnext!=fc)star.push_back(fnext);
425 CoordType bary0=(fc->P(0)+fc->P(1)+fc->P(2))/3;
426 for(ffi=star.begin();ffi!=star.end();++ffi )
429 FaceQualityType &qi = (*ffi)->Q();
430 CoordType bary1=((*ffi)->P(0)+(*ffi)->P(1)+(*ffi)->P(2))/3;
431 FaceQualityType distGeom = Distance(bary0,bary1) / gradientThr;
433 if( distGeom < fabs(qi - fc->Q()))
440 fc->Q() = qi+distGeom-(ScalarType)0.00001;
441 assert( distGeom > fabs(qi - fc->Q()));
448 assert( distGeom < fabs(qi - fc->Q()));
449 assert(fc->Q() < qi);
450 FaceQualityType newQi = fc->Q() + distGeom -(FaceQualityType)0.00001;
452 assert(fc->Q() < newQi);
453 assert( distGeom > fabs(newQi - fc->Q()) );
478 tri::RequirePerVertexQuality(m);
479 tri::RequireVFAdjacency(m);
482 std::stack<VertexPointer> st;
484 st.push(&*m.vert.begin());
488 VertexPointer vc = st.top();
493 std::vector<VertexPointer> star;
494 face::VVStarVF<FaceType>(vc,star);
495 for(
auto vvi=star.begin();vvi!=star.end();++vvi )
497 ScalarType qi = (*vvi)->Q();
498 ScalarType distGeom = Distance((*vvi)->cP(),vc->cP()) / gradientThr;
500 if( distGeom < fabs(qi - vc->Q()))
507 VertexQualityType delta=std::min(ScalarType(0.00001),ScalarType(distGeom/2.0));
508 vc->Q() = VertexQualityType(qi+distGeom-delta);
509 assert( distGeom > fabs(qi - vc->Q()));
516 assert( distGeom < fabs(qi - vc->Q()));
517 assert(vc->Q() < qi);
518 VertexQualityType delta=std::min(VertexQualityType(0.00001),VertexQualityType(distGeom/2.0));
519 VertexQualityType newQi = vc->Q() + distGeom -delta;
521 assert(vc->Q() < newQi);
522 assert( distGeom > fabs(newQi - vc->Q()) );
Class to safely add and delete elements in a mesh.
Definition: allocate.h:97
Management, updating and computation of per-vertex and per-face flags (like border flags).
Definition: flag.h:44
Generation of per-vertex and per-face qualities.
Definition: quality.h:45
static void VertexClamp(MeshType &m, VertexQualityType qmin, VertexQualityType qmax)
Definition: quality.h:94
static void FaceArea(MeshType &m)
Definition: quality.h:137
static void VertexShapeIndexFromCurvatureDir(MeshType &m)
VertexShapeIndexFromCurvatureDir Compute from the current Curvature Direction the Shape Index S as de...
Definition: quality.h:314
static void VertexValence(UpdateMeshType &m)
Definition: quality.h:76
static void VertexCurvednessFromCurvatureDir(MeshType &m)
VertexCurvednessFromCurvatureDir Compute from the current Curvature Direction the Curvedness as defin...
Definition: quality.h:336
static void VertexConstant(MeshType &m, VertexQualityType q)
Definition: quality.h:67
static void FaceConstant(MeshType &m, FaceQualityType q)
Definition: quality.h:128
static void VertexSaturate(MeshType &m, ScalarType gradientThr=1.0)
Saturate Vertex Quality Saturate the vertex quality so that for each vertex the gradient of the quali...
Definition: quality.h:476
static void VertexNormalize(MeshType &m, VertexQualityType qmin=0.0, VertexQualityType qmax=1.0)
Definition: quality.h:105
static void FaceNormalize(MeshType &m, FaceQualityType qmin=0.0, FaceQualityType qmax=1.0)
Definition: quality.h:117
void ForEachTetra(const MeshType &m, Callable action)
Definition: foreach.h:270
void ForEachVertex(const MeshType &m, Callable action)
Definition: foreach.h:126
Definition: namespaces.dox:6