00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef __VCGLIB_TRIMESH_STAT
00039 #define __VCGLIB_TRIMESH_STAT
00040
00041
00042
00043
00044 #include <vcg/math/histogram.h>
00045 #include <vcg/simplex/face/pos.h>
00046 #include <vcg/simplex/face/topology.h>
00047 #include <vcg/complex/trimesh/base.h>
00048 #include <vcg/complex/trimesh/closest.h>
00049 #include <vcg/space/index/grid_static_ptr.h>
00050 #include <vcg/complex/trimesh/allocate.h>
00051
00052
00053 namespace vcg {
00054 namespace tri{
00055 template <class StatMeshType>
00056 class Stat
00057 {
00058 public:
00059 typedef StatMeshType MeshType;
00060 typedef typename MeshType::VertexType VertexType;
00061 typedef typename MeshType::VertexPointer VertexPointer;
00062 typedef typename MeshType::VertexIterator VertexIterator;
00063 typedef typename MeshType::ScalarType ScalarType;
00064 typedef typename MeshType::FaceType FaceType;
00065 typedef typename MeshType::FacePointer FacePointer;
00066 typedef typename MeshType::FaceIterator FaceIterator;
00067 typedef typename MeshType::FaceContainer FaceContainer;
00068 typedef typename vcg::Box3<ScalarType> Box3Type;
00069
00070 static std::pair<float,float> ComputePerVertexQualityMinMax( MeshType & m)
00071 {
00072 std::pair<float,float> minmax = std::make_pair(std::numeric_limits<float>::max(),-std::numeric_limits<float>::max());
00073
00074 VertexIterator vi;
00075 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
00076 if(!(*vi).IsD())
00077 {
00078 if( (*vi).Q() < minmax.first) minmax.first=(*vi).Q();
00079 if( (*vi).Q() > minmax.second) minmax.second=(*vi).Q();
00080 }
00081 return minmax;
00082 }
00083
00084 static std::pair<float,float> ComputePerFaceQualityMinMax( MeshType & m)
00085 {
00086 std::pair<float,float> minmax = std::make_pair(std::numeric_limits<float>::max(),-std::numeric_limits<float>::max());
00087
00088 FaceIterator fi;
00089 for(fi = m.face.begin(); fi != m.face.end(); ++fi)
00090 if(!(*fi).IsD())
00091 {
00092 if( (*fi).Q() < minmax.first) minmax.first =(*fi).Q();
00093 if( (*fi).Q() > minmax.second) minmax.second=(*fi).Q();
00094 }
00095 return minmax;
00096 }
00097
00098 static ScalarType ComputeMeshArea(MeshType & m)
00099 {
00100 ScalarType area=0;
00101
00102 FaceIterator fi;
00103 for(fi = m.face.begin(); fi != m.face.end(); ++fi)
00104 if(!(*fi).IsD())
00105 area += DoubleArea(*fi);
00106
00107 return area/ScalarType(2.0);
00108 }
00109
00110 static void ComputePerVertexQualityDistribution( MeshType & m, Distribution<float> &h, bool selectionOnly = false)
00111 {
00112 VertexIterator vi;
00113 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
00114 if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) )
00115 {
00116 assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)");
00117 h.Add((*vi).Q());
00118 }
00119 }
00120
00121 static void ComputePerFaceQualityDistribution( MeshType & m, Distribution<float> &h, bool selectionOnly = false)
00122 {
00123 FaceIterator fi;
00124 for(fi = m.face.begin(); fi != m.face.end(); ++fi)
00125 if(!(*fi).IsD() && ((!selectionOnly) || (*fi).IsS()) )
00126 {
00127 assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)");
00128 h.Add((*fi).Q());
00129 }
00130 }
00131
00132 static void ComputePerFaceQualityHistogram( MeshType & m, Histogramf &h, bool selectionOnly=false )
00133 {
00134 FaceIterator fi;
00135 int HistSize=10000;
00136 std::pair<float,float> minmax = tri::Stat<MeshType>::ComputePerFaceQualityMinMax(m);
00137 h.Clear();
00138 h.SetRange( minmax.first,minmax.second, HistSize );
00139 for(fi = m.face.begin(); fi != m.face.end(); ++fi)
00140 if(!(*fi).IsD() && ((!selectionOnly) || (*fi).IsS()) ){
00141 assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)");
00142 h.Add((*fi).Q());
00143 }
00144 }
00145
00146 static void ComputePerVertexQualityHistogram( MeshType & m, Histogramf &h, bool selectionOnly = false)
00147 {
00148 VertexIterator vi;
00149 int HistSize=10000;
00150 std::pair<float,float> minmax = ComputePerVertexQualityMinMax(m);
00151
00152 h.Clear();
00153 h.SetRange( minmax.first,minmax.second, HistSize);
00154 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
00155 if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) )
00156 {
00157 assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)");
00158 h.Add((*vi).Q());
00159 }
00160
00161
00162
00163
00164
00165
00166 if(h.MaxCount() > HistSize/5)
00167 {
00168 std::vector<float> QV;
00169 QV.reserve(m.vn);
00170 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
00171 if(!(*vi).IsD()) QV.push_back((*vi).Q());
00172
00173 std::nth_element(QV.begin(),QV.begin()+m.vn/100,QV.end());
00174 float newmin=*(QV.begin()+m.vn/100);
00175 std::nth_element(QV.begin(),QV.begin()+m.vn-m.vn/100,QV.end());
00176 float newmax=*(QV.begin()+m.vn-m.vn/100);
00177
00178 h.Clear();
00179 h.SetRange(newmin, newmax, HistSize*50);
00180 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
00181 if(!(*vi).IsD() && ((!selectionOnly) || (*vi).IsS()) )
00182 h.Add((*vi).Q());
00183 }
00184 }
00185
00186 static int ComputeEdgeHistogram( MeshType & m, Histogramf &h)
00187 {
00188 ScalarType Diag = m.bbox.Diag();
00189 h.Clear();
00190 h.SetRange( 0, Diag, 10000);
00191 FaceIterator fi;
00192 for(fi = m.face.begin(); fi != m.face.end(); ++fi)
00193 {
00194 if(!(*fi).IsD())
00195 {
00196 if( !(*fi).V(0)->IsS() && !(*fi).V(1)->IsS() )
00197 {
00198 h.Add(Distance<float>((*fi).V(0)->P(),(*fi).V(1)->P()));
00199 (*fi).V(0)->SetS();
00200 (*fi).V(1)->SetS();
00201 }
00202 if( !(*fi).V(1)->IsS() && !(*fi).V(2)->IsS())
00203 {
00204 h.Add(Distance<float>((*fi).V(1)->P(),(*fi).V(2)->P()));
00205 (*fi).V(2)->SetS();
00206 (*fi).V(1)->SetS();
00207 }
00208 if( !(*fi).V(2)->IsS() && !(*fi).V(0)->IsS())
00209 {
00210 h.Add(Distance<float>((*fi).V(2)->P(),(*fi).V(0)->P()));
00211 (*fi).V(0)->SetS();
00212 (*fi).V(2)->SetS();
00213 }
00214 }
00215 }
00216 VertexIterator vi;
00217 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi)
00218 (*vi).ClearS();
00219 return 0;
00220 }
00221 };
00222
00223 }
00224 }
00225
00226 #endif
00227