From b84952427492fcf3afab88db26128e37050008d4 Mon Sep 17 00:00:00 2001 From: cignoni Date: Tue, 10 Sep 2013 10:49:01 +0000 Subject: [PATCH] Added Requirements. Refactored some funcs and uniformed naming of functions... --- vcg/complex/algorithms/stat.h | 360 +++++++++++++++++----------------- 1 file changed, 184 insertions(+), 176 deletions(-) diff --git a/vcg/complex/algorithms/stat.h b/vcg/complex/algorithms/stat.h index 7e866866..416db292 100644 --- a/vcg/complex/algorithms/stat.h +++ b/vcg/complex/algorithms/stat.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -52,60 +52,68 @@ Initial Commit namespace vcg { - namespace tri{ +namespace tri{ template class Stat { - public: - typedef StatMeshType MeshType; - typedef typename MeshType::VertexType VertexType; - typedef typename MeshType::VertexPointer VertexPointer; - typedef typename MeshType::VertexIterator VertexIterator; - typedef typename MeshType::ScalarType ScalarType; - typedef typename MeshType::FaceType FaceType; - typedef typename MeshType::FacePointer FacePointer; - typedef typename MeshType::FaceIterator FaceIterator; +public: + typedef StatMeshType MeshType; + typedef typename MeshType::VertexType VertexType; + typedef typename MeshType::VertexPointer VertexPointer; + typedef typename MeshType::VertexIterator VertexIterator; + typedef typename MeshType::ScalarType ScalarType; + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::FacePointer FacePointer; + typedef typename MeshType::FaceIterator FaceIterator; typedef typename MeshType::EdgeIterator EdgeIterator; - typedef typename MeshType::FaceContainer FaceContainer; - typedef typename vcg::Box3 Box3Type; - - static void ComputePerVertexQualityMinMax( MeshType & m, float &minV, float &maxV) - { - std::pair pp=ComputePerVertexQualityMinMax(m); - minV=pp.first; maxV=pp.second; - } - static std::pair ComputePerVertexQualityMinMax( MeshType & m) - { - std::pair minmax = std::make_pair(std::numeric_limits::max(),-std::numeric_limits::max()); - - VertexIterator vi; - for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) - if(!(*vi).IsD()) - { - if( (*vi).Q() < minmax.first) minmax.first=(*vi).Q(); - if( (*vi).Q() > minmax.second) minmax.second=(*vi).Q(); - } - return minmax; - } + typedef typename MeshType::FaceContainer FaceContainer; + typedef typename vcg::Box3 Box3Type; - static void ComputePerFaceQualityMinMax( MeshType & m, float &minV, float &maxV) - { - std::pair pp=ComputePerFaceQualityMinMax(m); - minV=pp.first; maxV=pp.second; - } - static std::pair ComputePerFaceQualityMinMax( MeshType & m) - { - std::pair minmax = std::make_pair(std::numeric_limits::max(),-std::numeric_limits::max()); - - FaceIterator fi; - for(fi = m.face.begin(); fi != m.face.end(); ++fi) - if(!(*fi).IsD()) - { - if( (*fi).Q() < minmax.first) minmax.first =(*fi).Q(); - if( (*fi).Q() > minmax.second) minmax.second=(*fi).Q(); - } - return minmax; - } + static void ComputePerVertexQualityMinMax( MeshType & m, float &minV, float &maxV) + { + std::pair pp=ComputePerVertexQualityMinMax(m); + minV=pp.first; maxV=pp.second; + } + static std::pair ComputePerVertexQualityMinMax( MeshType & m) + { +// assert(0); + tri::RequirePerVertexQuality(m); + typename MeshType::template PerMeshAttributeHandle < std::pair > mmqH; + mmqH = tri::Allocator::template GetPerMeshAttribute >(m,"minmaxQ"); + + std::pair minmax = std::make_pair(std::numeric_limits::max(),-std::numeric_limits::max()); + + for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if(!(*vi).IsD()) + { + if( (*vi).Q() < minmax.first) minmax.first=(*vi).Q(); + if( (*vi).Q() > minmax.second) minmax.second=(*vi).Q(); + } + + mmqH() = minmax; + return minmax; + } + + static void ComputePerFaceQualityMinMax( MeshType & m, float &minV, float &maxV) + { + std::pair pp=ComputePerFaceQualityMinMax(m); + minV=pp.first; maxV=pp.second; + } + + static std::pair ComputePerFaceQualityMinMax( MeshType & m) + { + tri::RequirePerFaceQuality(m); + std::pair minmax = std::make_pair(std::numeric_limits::max(),-std::numeric_limits::max()); + + FaceIterator fi; + for(fi = m.face.begin(); fi != m.face.end(); ++fi) + if(!(*fi).IsD()) + { + if( (*fi).Q() < minmax.first) minmax.first =(*fi).Q(); + if( (*fi).Q() > minmax.second) minmax.second=(*fi).Q(); + } + return minmax; + } /** \short compute the barycenter of the surface thin-shell. @@ -119,155 +127,155 @@ class Stat ScalarType areaSum=0; FaceIterator fi; for(fi = m.face.begin(); fi != m.face.end(); ++fi) - if(!(*fi).IsD()) - { - ScalarType area=DoubleArea(*fi); - barycenter += Barycenter(*fi)*area; - areaSum+=area; - } + if(!(*fi).IsD()) + { + ScalarType area=DoubleArea(*fi); + barycenter += Barycenter(*fi)*area; + areaSum+=area; + } return barycenter/areaSum; } - - static ScalarType ComputeMeshArea(MeshType & m) - { - ScalarType area=0; - - FaceIterator fi; - for(fi = m.face.begin(); fi != m.face.end(); ++fi) - if(!(*fi).IsD()) - area += DoubleArea(*fi); - - return area/ScalarType(2.0); - } - - static void ComputePerVertexQualityDistribution( MeshType & m, Distribution &h, bool selectionOnly = false) // V1.0 + + static ScalarType ComputeMeshArea(MeshType & m) + { + ScalarType area=0; + + for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + if(!(*fi).IsD()) + area += DoubleArea(*fi); + + return area/ScalarType(2.0); + } + + static void ComputePerVertexQualityDistribution( MeshType & m, Distribution &h, bool selectionOnly = false) // V1.0 + { + tri::RequirePerVertexQuality(m); + for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) { - VertexIterator vi; - for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) - if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) - { - assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); - h.Add((*vi).Q()); - } + assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); + h.Add((*vi).Q()); } + } - static void ComputePerFaceQualityDistribution( MeshType & m, Distribution &h, bool selectionOnly = false) // V1.0 + static void ComputePerFaceQualityDistribution( MeshType & m, Distribution &h, bool selectionOnly = false) // V1.0 + { + tri::RequirePerFaceQuality(m); + for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + if(!(*fi).IsD() && ((!selectionOnly) || (*fi).IsS()) ) { - FaceIterator fi; - for(fi = m.face.begin(); fi != m.face.end(); ++fi) - if(!(*fi).IsD() && ((!selectionOnly) || (*fi).IsS()) ) - { - assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); - h.Add((*fi).Q()); - } + assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); + h.Add((*fi).Q()); } + } - static void ComputePerFaceQualityHistogram( MeshType & m, Histogramf &h, bool selectionOnly=false,int HistSize=10000 ) - { - std::pair minmax = tri::Stat::ComputePerFaceQualityMinMax(m); - h.Clear(); - h.SetRange( minmax.first,minmax.second, HistSize ); - for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) - if(!(*fi).IsD() && ((!selectionOnly) || (*fi).IsS()) ){ - assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); - h.Add((*fi).Q()); - } + static void ComputePerFaceQualityHistogram( MeshType & m, Histogramf &h, bool selectionOnly=false,int HistSize=10000 ) + { + tri::RequirePerFaceQuality(m); + std::pair minmax = tri::Stat::ComputePerFaceQualityMinMax(m); + h.Clear(); + h.SetRange( minmax.first,minmax.second, HistSize ); + for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + if(!(*fi).IsD() && ((!selectionOnly) || (*fi).IsS()) ){ + assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); + h.Add((*fi).Q()); } + } - static void ComputePerVertexQualityHistogram( MeshType & m, Histogramf &h, bool selectionOnly = false, int HistSize=10000 ) // V1.0 + static void ComputePerVertexQualityHistogram( MeshType & m, Histogramf &h, bool selectionOnly = false, int HistSize=10000 ) // V1.0 + { + tri::RequirePerVertexQuality(m); + std::pair minmax = ComputePerVertexQualityMinMax(m); + + h.Clear(); + h.SetRange( minmax.first,minmax.second, HistSize); + for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) { - VertexIterator vi; - std::pair minmax = ComputePerVertexQualityMinMax(m); - - h.Clear(); - h.SetRange( minmax.first,minmax.second, HistSize); - for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) - if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) - { - assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); - h.Add((*vi).Q()); - } - // Sanity check; If some very wrong value has happened in the Q value, - // the histogram is messed. If a significant percentage (20% )of the values are all in a single bin - // we should try to solve the problem. No easy solution here. - // We choose to compute the get the 1percentile and 99 percentile values as new mixmax ranges - // and just to be sure enlarge the Histogram. - - if(h.MaxCount() > HistSize/5) - { - std::vector QV; - QV.reserve(m.vn); - for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) - if(!(*vi).IsD()) QV.push_back((*vi).Q()); - - std::nth_element(QV.begin(),QV.begin()+m.vn/100,QV.end()); - float newmin=*(QV.begin()+m.vn/100); - std::nth_element(QV.begin(),QV.begin()+m.vn-m.vn/100,QV.end()); - float newmax=*(QV.begin()+m.vn-m.vn/100); - - h.Clear(); - h.SetRange(newmin, newmax, HistSize*50); - for(vi = m.vert.begin(); vi != m.vert.end(); ++vi) - if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) - h.Add((*vi).Q()); - } + assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)"); + h.Add((*vi).Q()); } + // Sanity check; If some very wrong value has happened in the Q value, + // the histogram is messed. If a significant percentage (20% )of the values are all in a single bin + // we should try to solve the problem. No easy solution here. + // We choose to compute the get the 1percentile and 99 percentile values as new mixmax ranges + // and just to be sure enlarge the Histogram. - static void ComputeEdgeHistogram( MeshType & m, Histogramf &h) + if(h.MaxCount() > HistSize/5) + { + std::vector QV; + QV.reserve(m.vn); + for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if(!(*vi).IsD()) QV.push_back((*vi).Q()); + + std::nth_element(QV.begin(),QV.begin()+m.vn/100,QV.end()); + float newmin=*(QV.begin()+m.vn/100); + std::nth_element(QV.begin(),QV.begin()+m.vn-m.vn/100,QV.end()); + float newmax=*(QV.begin()+m.vn-m.vn/100); + + h.Clear(); + h.SetRange(newmin, newmax, HistSize*50); + for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) ) + h.Add((*vi).Q()); + } + } + + static void ComputeEdgeLengthHistogram( MeshType & m, Histogramf &h) + { + assert(m.edge.size()>0); + h.Clear(); + h.SetRange( 0, m.bbox.Diag(), 10000); + for(EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei) + { + if(!(*ei).IsD()) { - assert(m.edge.size()>0); - h.Clear(); - h.SetRange( 0, m.bbox.Diag(), 10000); - for(EdgeIterator ei = m.edge.begin(); ei != m.edge.end(); ++ei) + h.Add(Distance((*ei).V(0)->P(),(*ei).V(1)->P())); + } + } + } + + static ScalarType ComputeEdgeLengthAverage(MeshType & m) + { + Histogramf h; + ComputeEdgeLengthHistogram(m,h); + return h.Avg(); + } + + static void ComputeFaceEdgeLengthDistribution( MeshType & m, Distribution &h) + { + h.Clear(); + tri::UpdateFlags::FaceBorderFromNone(m); + for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + { + if(!(*fi).IsD()) + { + for(int i=0;i<3;++i) { - if(!(*ei).IsD()) - { - h.Add(Distance((*ei).V(0)->P(),(*ei).V(1)->P())); - } + h.Add(Distance(fi->P0(i),fi->P1(i))); + if(fi->IsB(i)) // to be uniform border edges must be added twice... + h.Add(Distance(fi->P0(i),fi->P1(i))); } } + } + } - static ScalarType ComputeEdgeAverage(MeshType & m) + static ScalarType ComputeFaceEdgeLengthAverage(MeshType & m) + { + double sum=0; + for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) + if(!(*fi).IsD()) { - Histogramf h; - ComputeEdgeHistogram(m,h); - return h.Avg(); + for(int i=0;i<3;++i) + sum+=double(Distance(fi->P0(i),fi->P1(i))); } - - static void ComputeFaceEdgeDistribution( MeshType & m, Distribution &h) - { - h.Clear(); - tri::UpdateFlags::FaceBorderFromNone(m); - for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) - { - if(!(*fi).IsD()) - { - for(int i=0;i<3;++i) - { - h.Add(Distance(fi->P0(i),fi->P1(i))); - if(fi->IsB(i)) // to be uniform border edges must be added twice... - h.Add(Distance(fi->P0(i),fi->P1(i))); - } - } - } - } - - static ScalarType ComputeFaceEdgeAverage(MeshType & m) - { - double sum=0; - for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) - if(!(*fi).IsD()) - { - for(int i=0;i<3;++i) - sum+=double(Distance(fi->P0(i),fi->P1(i))); - } - return sum/(m.fn*3.0); - } + return sum/(m.fn*3.0); + } }; // end class - - } //End Namespace tri + +} //End Namespace tri } // End Namespace vcg #endif