added some useful functions on tetras
This commit is contained in:
parent
05764ee1c2
commit
2b7e5ba20b
|
|
@ -51,37 +51,45 @@ public:
|
||||||
typedef typename MeshType::FacePointer FacePointer;
|
typedef typename MeshType::FacePointer FacePointer;
|
||||||
typedef typename MeshType::FaceIterator FaceIterator;
|
typedef typename MeshType::FaceIterator FaceIterator;
|
||||||
typedef typename MeshType::FaceContainer FaceContainer;
|
typedef typename MeshType::FaceContainer FaceContainer;
|
||||||
|
typedef typename MeshType::TetraType TetraType;
|
||||||
|
typedef typename MeshType::TetraPointer TetraPointer;
|
||||||
|
typedef typename MeshType::TetraIterator TetraIterator;
|
||||||
|
typedef typename MeshType::TetraContainer TetraContainer;
|
||||||
typedef typename vcg::Box3<ScalarType> Box3Type;
|
typedef typename vcg::Box3<ScalarType> Box3Type;
|
||||||
|
|
||||||
static void ComputePerVertexQualityMinMax( MeshType & m, float &minV, float &maxV)
|
static void ComputePerVertexQualityMinMax(MeshType & m, ScalarType &minV, ScalarType &maxV)
|
||||||
{
|
{
|
||||||
std::pair<float,float> pp=ComputePerVertexQualityMinMax(m);
|
std::pair<ScalarType, ScalarType> pp = ComputePerVertexQualityMinMax(m);
|
||||||
minV=pp.first; maxV=pp.second;
|
|
||||||
|
minV=pp.first;
|
||||||
|
maxV=pp.second;
|
||||||
}
|
}
|
||||||
static std::pair<float,float> ComputePerVertexQualityMinMax( MeshType & m)
|
static std::pair<ScalarType, ScalarType> ComputePerVertexQualityMinMax(MeshType & m)
|
||||||
{
|
{
|
||||||
// assert(0);
|
// assert(0);
|
||||||
tri::RequirePerVertexQuality(m);
|
tri::RequirePerVertexQuality(m);
|
||||||
typename MeshType::template PerMeshAttributeHandle < std::pair<float,float> > mmqH;
|
typename MeshType::template PerMeshAttributeHandle < std::pair<ScalarType, ScalarType> > mmqH;
|
||||||
mmqH = tri::Allocator<MeshType>::template GetPerMeshAttribute <std::pair<float,float> >(m,"minmaxQ");
|
mmqH = tri::Allocator<MeshType>::template GetPerMeshAttribute <std::pair<ScalarType, ScalarType> >(m,"minmaxQ");
|
||||||
|
|
||||||
std::pair<float,float> minmax = std::make_pair(std::numeric_limits<float>::max(),-std::numeric_limits<float>::max());
|
std::pair<ScalarType, ScalarType> minmax = std::make_pair(std::numeric_limits<ScalarType>::max(), -std::numeric_limits<fScalarTypeloat>::max());
|
||||||
|
|
||||||
for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
||||||
if(!(*vi).IsD())
|
if(!(*vi).IsD())
|
||||||
{
|
{
|
||||||
if( (*vi).Q() < minmax.first) minmax.first=(*vi).Q();
|
if( (*vi).Q() < minmax.first) minmax.first = (*vi).Q();
|
||||||
if( (*vi).Q() > minmax.second) minmax.second=(*vi).Q();
|
if( (*vi).Q() > minmax.second) minmax.second = (*vi).Q();
|
||||||
}
|
}
|
||||||
|
|
||||||
mmqH() = minmax;
|
mmqH() = minmax;
|
||||||
return minmax;
|
return minmax;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ComputePerFaceQualityMinMax( MeshType & m, float &minV, float &maxV)
|
|
||||||
|
static void ComputePerFaceQualityMinMax(MeshType & m, ScalarType &minV, ScalarType &maxV)
|
||||||
{
|
{
|
||||||
std::pair<float,float> pp=ComputePerFaceQualityMinMax(m);
|
std::pair<ScalarType, ScalarType> pp = ComputePerFaceQualityMinMax(m);
|
||||||
minV=pp.first; maxV=pp.second;
|
minV=pp.first;
|
||||||
|
maxV=pp.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::pair<ScalarType,ScalarType> ComputePerFaceQualityMinMax( MeshType & m)
|
static std::pair<ScalarType,ScalarType> ComputePerFaceQualityMinMax( MeshType & m)
|
||||||
|
|
@ -93,13 +101,46 @@ public:
|
||||||
for(fi = m.face.begin(); fi != m.face.end(); ++fi)
|
for(fi = m.face.begin(); fi != m.face.end(); ++fi)
|
||||||
if(!(*fi).IsD())
|
if(!(*fi).IsD())
|
||||||
{
|
{
|
||||||
if( (*fi).Q() < minmax.first) minmax.first =(*fi).Q();
|
if( (*fi).Q() < minmax.first) minmax.first = (*fi).Q();
|
||||||
if( (*fi).Q() > minmax.second) minmax.second=(*fi).Q();
|
if( (*fi).Q() > minmax.second) minmax.second = (*fi).Q();
|
||||||
}
|
}
|
||||||
return minmax;
|
return minmax;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ScalarType ComputePerFaceQualityAvg( MeshType & m)
|
static void ComputerPerTetraQualityMinMax(MeshType & m, ScalarType & minQ, ScalarType & maxQ)
|
||||||
|
{
|
||||||
|
std::pair<ScalarType, ScalarType> minmax = ComputerPerTetraQualityMinMax(m);
|
||||||
|
|
||||||
|
minQ = minmax.first;
|
||||||
|
maxQ = minmax.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::pair<ScalarType, ScalarType> ComputerPerTetraQualityMinMax(MeshType & m)
|
||||||
|
{
|
||||||
|
tri::RequirePerTetraQuality(m);
|
||||||
|
std::pair<ScalarType, ScalarType> minmax = std::make_pair(std::numeric_limits<ScalarType>::max(), -std::numeric_limits<ScalarType>::max());
|
||||||
|
|
||||||
|
ForEachTetra(m, [&minmax] (TetraType & t) {
|
||||||
|
if (t.Q() < minmax.first) minmax.first = t.Q();
|
||||||
|
if (t.Q() > minmax.second) minmax.second = t.Q();
|
||||||
|
});
|
||||||
|
|
||||||
|
return minmax;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ScalarType ComputePerTetraQualityAvg(MeshType & m)
|
||||||
|
{
|
||||||
|
tri::RequirePerTetraQuality(m);
|
||||||
|
ScalarType avgQ = 0;
|
||||||
|
|
||||||
|
ForEachTetra(m, [&avgQ] (TetraType & t) {
|
||||||
|
avgQ += t.Q();
|
||||||
|
});
|
||||||
|
|
||||||
|
return avgQ /= (ScalarType) m.TN();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ScalarType ComputePerFaceQualityAvg(MeshType & m)
|
||||||
{
|
{
|
||||||
tri::RequirePerFaceQuality(m);
|
tri::RequirePerFaceQuality(m);
|
||||||
ScalarType AvgQ = 0;
|
ScalarType AvgQ = 0;
|
||||||
|
|
@ -195,6 +236,17 @@ public:
|
||||||
return barycenter/areaSum;
|
return barycenter/areaSum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ScalarType ComputeTetraMeshVolume(MeshType & m)
|
||||||
|
{
|
||||||
|
ScalarType V = 0;
|
||||||
|
|
||||||
|
ForEachTetra(m, [&V] (TetraType & t) {
|
||||||
|
V += Tetra::ComputeVolume(t);
|
||||||
|
});
|
||||||
|
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
static ScalarType ComputeMeshVolume(MeshType & m)
|
static ScalarType ComputeMeshVolume(MeshType & m)
|
||||||
{
|
{
|
||||||
Inertia<MeshType> I(m);
|
Inertia<MeshType> I(m);
|
||||||
|
|
@ -227,7 +279,7 @@ public:
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ComputePerVertexQualityDistribution( MeshType & m, Distribution<ScalarType> &h, bool selectionOnly = false) // V1.0
|
static void ComputePerVertexQualityDistribution(MeshType & m, Distribution<ScalarType> & h, bool selectionOnly = false) // V1.0
|
||||||
{
|
{
|
||||||
tri::RequirePerVertexQuality(m);
|
tri::RequirePerVertexQuality(m);
|
||||||
for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
||||||
|
|
@ -250,10 +302,39 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ComputePerFaceQualityHistogram( MeshType & m, Histogramf &h, bool selectionOnly=false,int HistSize=10000 )
|
static void ComputePerTetraQualityDistribution(MeshType & m, Distribution<ScalarType> & h, bool selectionOnly = false)
|
||||||
|
{
|
||||||
|
tri::RequirePerTetraQuality(m);
|
||||||
|
ForEachTetra(m, [&] (TetraType & t) {
|
||||||
|
if (!selectionOnly || t.IsS())
|
||||||
|
{
|
||||||
|
assert(!math::IsNAN(t.Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)");
|
||||||
|
h.Add(t.Q());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ComputePerTetraQualityHistogram(MeshType & m, Histogram<ScalarType> & h, bool selectionOnly = false, int HistSize = 10000)
|
||||||
|
{
|
||||||
|
tri::RequirePerTetraQuality(m);
|
||||||
|
std::pair<ScalarType, ScalarType> minmax = tri::Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||||
|
|
||||||
|
h.Clear();
|
||||||
|
h.SetRange(minmax.first, minmax.second, HistSize);
|
||||||
|
|
||||||
|
ForEachTetra(m, [&] (TetraType & t) {
|
||||||
|
if (!selectionOnly || t.IsS())
|
||||||
|
{
|
||||||
|
assert(!math::IsNAN(t.Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)");
|
||||||
|
h.Add(t.Q());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ComputePerFaceQualityHistogram( MeshType & m, Histogram<ScalarType> &h, bool selectionOnly=false,int HistSize=10000 )
|
||||||
{
|
{
|
||||||
tri::RequirePerFaceQuality(m);
|
tri::RequirePerFaceQuality(m);
|
||||||
std::pair<float,float> minmax = tri::Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
std::pair<ScalarType, ScalarType> minmax = tri::Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||||
h.Clear();
|
h.Clear();
|
||||||
h.SetRange( minmax.first,minmax.second, HistSize );
|
h.SetRange( minmax.first,minmax.second, HistSize );
|
||||||
for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
|
for(FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
|
||||||
|
|
@ -263,10 +344,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ComputePerVertexQualityHistogram( MeshType & m, Histogramf &h, bool selectionOnly = false, int HistSize=10000 ) // V1.0
|
static void ComputePerVertexQualityHistogram( MeshType & m, Histogram<ScalarType> &h, bool selectionOnly = false, int HistSize=10000 ) // V1.0
|
||||||
{
|
{
|
||||||
tri::RequirePerVertexQuality(m);
|
tri::RequirePerVertexQuality(m);
|
||||||
std::pair<float,float> minmax = ComputePerVertexQualityMinMax(m);
|
std::pair<ScalarType, ScalarType> minmax = ComputePerVertexQualityMinMax(m);
|
||||||
|
|
||||||
h.Clear();
|
h.Clear();
|
||||||
h.SetRange( minmax.first,minmax.second, HistSize);
|
h.SetRange( minmax.first,minmax.second, HistSize);
|
||||||
|
|
@ -284,15 +365,15 @@ public:
|
||||||
|
|
||||||
if(h.MaxCount() > HistSize/5)
|
if(h.MaxCount() > HistSize/5)
|
||||||
{
|
{
|
||||||
std::vector<float> QV;
|
std::vector<ScalarType> QV;
|
||||||
QV.reserve(m.vn);
|
QV.reserve(m.vn);
|
||||||
for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
||||||
if(!(*vi).IsD()) QV.push_back((*vi).Q());
|
if(!(*vi).IsD()) QV.push_back((*vi).Q());
|
||||||
|
|
||||||
std::nth_element(QV.begin(),QV.begin()+m.vn/100,QV.end());
|
std::nth_element(QV.begin(),QV.begin()+m.vn/100,QV.end());
|
||||||
float newmin=*(QV.begin()+m.vn/100);
|
ScalarType newmin=*(QV.begin()+m.vn/100);
|
||||||
std::nth_element(QV.begin(),QV.begin()+m.vn-m.vn/100,QV.end());
|
std::nth_element(QV.begin(),QV.begin()+m.vn-m.vn/100,QV.end());
|
||||||
float newmax=*(QV.begin()+m.vn-m.vn/100);
|
ScalarType newmax=*(QV.begin()+m.vn-m.vn/100);
|
||||||
|
|
||||||
h.Clear();
|
h.Clear();
|
||||||
h.SetRange(newmin, newmax, HistSize*50);
|
h.SetRange(newmin, newmax, HistSize*50);
|
||||||
|
|
@ -302,7 +383,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ComputeEdgeLengthHistogram( MeshType & m, Histogramf &h)
|
static void ComputeEdgeLengthHistogram(MeshType & m, Histogram<ScalarType> & h)
|
||||||
{
|
{
|
||||||
assert(m.edge.size()>0);
|
assert(m.edge.size()>0);
|
||||||
h.Clear();
|
h.Clear();
|
||||||
|
|
@ -331,7 +412,7 @@ public:
|
||||||
});
|
});
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
static void ComputeFaceEdgeLengthDistribution( MeshType & m, Distribution<float> &h, bool includeFauxEdge=false)
|
static void ComputeFaceEdgeLengthDistribution( MeshType & m, Distribution<ScalarType> & h, bool includeFauxEdge=false)
|
||||||
{
|
{
|
||||||
std::vector< typename tri::UpdateTopology<MeshType>::PEdge > edgeVec;
|
std::vector< typename tri::UpdateTopology<MeshType>::PEdge > edgeVec;
|
||||||
tri::UpdateTopology<MeshType>::FillUniqueEdgeVector(m,edgeVec,includeFauxEdge);
|
tri::UpdateTopology<MeshType>::FillUniqueEdgeVector(m,edgeVec,includeFauxEdge);
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,10 @@ public:
|
||||||
typedef typename MeshType::FacePointer FacePointer;
|
typedef typename MeshType::FacePointer FacePointer;
|
||||||
typedef typename MeshType::FaceIterator FaceIterator;
|
typedef typename MeshType::FaceIterator FaceIterator;
|
||||||
typedef typename MeshType::EdgeIterator EdgeIterator;
|
typedef typename MeshType::EdgeIterator EdgeIterator;
|
||||||
|
typedef typename MeshType::TetraType TetraType;
|
||||||
|
typedef typename MeshType::TetraPointer TetraPointer;
|
||||||
|
typedef typename MeshType::TetraIterator TetraIterator;
|
||||||
|
|
||||||
|
|
||||||
typedef typename MeshType::ScalarType ScalarType;
|
typedef typename MeshType::ScalarType ScalarType;
|
||||||
typedef typename MeshType::CoordType CoordType;
|
typedef typename MeshType::CoordType CoordType;
|
||||||
|
|
@ -73,7 +77,7 @@ public:
|
||||||
int cnt;
|
int cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief This function colores all (or the selected) the vertices of a mesh.
|
/*! \brief This function colors all (or the selected) the vertices of a mesh.
|
||||||
*/
|
*/
|
||||||
static int PerVertexConstant(MeshType &m, Color4b vs=Color4b::White,bool selected=false)
|
static int PerVertexConstant(MeshType &m, Color4b vs=Color4b::White,bool selected=false)
|
||||||
{
|
{
|
||||||
|
|
@ -91,7 +95,7 @@ public:
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief This function colores all (or the selected) faces of a mesh.
|
/*! \brief This function colors all (or the selected) faces of a mesh.
|
||||||
*/
|
*/
|
||||||
static int PerFaceConstant(MeshType &m, Color4b vs=Color4b::White,bool selected=false)
|
static int PerFaceConstant(MeshType &m, Color4b vs=Color4b::White,bool selected=false)
|
||||||
{
|
{
|
||||||
|
|
@ -108,6 +112,55 @@ public:
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief This function colors all (or the selected) tetras of a mesh.
|
||||||
|
*/
|
||||||
|
static int PerTetraConstant(MeshType & m, Color4b vs = Color4b::White, bool selected = false)
|
||||||
|
{
|
||||||
|
RequirePerTetraColor(m);
|
||||||
|
int cnt = 0;
|
||||||
|
ForEachTetra(m, [&] (TetraType & t) {
|
||||||
|
if (!selected || t.IsS())
|
||||||
|
{
|
||||||
|
t.C() = vs;
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Transfer tetra color onto vertex color
|
||||||
|
|
||||||
|
Plain average of the color of the tetras incident on a given vertex.
|
||||||
|
No adjacency required.
|
||||||
|
*/
|
||||||
|
static void PerVertexFromTetra(MeshType & m)
|
||||||
|
{
|
||||||
|
RequirePerTetraColor(m);
|
||||||
|
RequirePerVertexColor(m);
|
||||||
|
|
||||||
|
ColorAvgInfo csi;
|
||||||
|
csi.r = csi.g = csi.b = csi.cnt = 0;
|
||||||
|
SimpleTempData<typename MeshType::VertContainer, ColorAvgInfo> TD(m.vert, csi);
|
||||||
|
|
||||||
|
ForEachTetra(m, [&] (TetraType & t) {
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
TD[t.V(i)].r += t.C()[0];
|
||||||
|
TD[t.V(i)].g += t.C()[1];
|
||||||
|
TD[t.V(i)].b += t.C()[2];
|
||||||
|
TD[t.V(i)].a += t.C()[3];
|
||||||
|
TD[t.V(i)].cnt += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ForEachVertex(m, [&] (VertexType & v) {
|
||||||
|
v.C()[0] = TD[v].r / TD[v].cnt;
|
||||||
|
v.C()[1] = TD[v].g / TD[v].cnt;
|
||||||
|
v.C()[2] = TD[v].b / TD[v].cnt;
|
||||||
|
v.C()[3] = TD[v].a / TD[v].cnt;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** \brief Transfer face color onto vertex color
|
/** \brief Transfer face color onto vertex color
|
||||||
|
|
||||||
Plain average of the color of the faces incident on a given vertex.
|
Plain average of the color of the faces incident on a given vertex.
|
||||||
|
|
@ -167,14 +220,14 @@ public:
|
||||||
|
|
||||||
If no range of quality is passed it is automatically computed.
|
If no range of quality is passed it is automatically computed.
|
||||||
*/
|
*/
|
||||||
static void PerVertexQualityRamp(MeshType &m, float minq=0, float maxq=0)
|
static void PerVertexQualityRamp(MeshType &m, ScalarType minq = 0., ScalarType maxq = 0.)
|
||||||
{
|
{
|
||||||
RequirePerVertexQuality(m);
|
RequirePerVertexQuality(m);
|
||||||
RequirePerVertexColor(m);
|
RequirePerVertexColor(m);
|
||||||
|
|
||||||
if(minq==maxq)
|
if(minq == maxq)
|
||||||
{
|
{
|
||||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
||||||
minq=minmax.first;
|
minq=minmax.first;
|
||||||
maxq=minmax.second;
|
maxq=minmax.second;
|
||||||
}
|
}
|
||||||
|
|
@ -188,54 +241,76 @@ public:
|
||||||
|
|
||||||
If no range of quality is passed it is automatically computed.
|
If no range of quality is passed it is automatically computed.
|
||||||
*/
|
*/
|
||||||
static void PerVertexQualityRampParula(MeshType &m, float minq=0, float maxq=0)
|
static void PerVertexQualityRampParula(MeshType &m, ScalarType minq = 0., ScalarType maxq = 0.)
|
||||||
{
|
{
|
||||||
RequirePerVertexQuality(m);
|
RequirePerVertexQuality(m);
|
||||||
RequirePerVertexColor(m);
|
RequirePerVertexColor(m);
|
||||||
|
|
||||||
if(minq==maxq)
|
if(minq == maxq)
|
||||||
{
|
{
|
||||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
||||||
minq=minmax.first;
|
minq=minmax.first;
|
||||||
maxq=minmax.second;
|
maxq=minmax.second;
|
||||||
}
|
}
|
||||||
for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
|
for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
|
||||||
if(!(*vi).IsD())
|
if(!(*vi).IsD())
|
||||||
(*vi).C().SetColorRampParula(minq,maxq,(*vi).Q());
|
(*vi).C().SetColorRampParula(minq, maxq, (*vi).Q());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief This function colores all the faces of a mesh with a hue color shade dependent on the quality.
|
||||||
|
|
||||||
|
If no range of quality is passed it is automatically computed.
|
||||||
|
*/
|
||||||
|
static void PerTetraQualityRamp(MeshType &m, ScalarType minq = 0., ScalarType maxq = 0., bool selected = false)
|
||||||
|
{
|
||||||
|
RequirePerTetraColor(m);
|
||||||
|
RequirePerTetraQuality(m);
|
||||||
|
|
||||||
|
if(minq == maxq)
|
||||||
|
{
|
||||||
|
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputerPerTetraQualityMinMax(m);
|
||||||
|
minq=minmax.first;
|
||||||
|
maxq=minmax.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
ForEachTetra(m, [&] (TetraType & t){
|
||||||
|
if (!selected || t.IsS())
|
||||||
|
t.C().SetColorRamp(minq, maxq, t.Q());
|
||||||
|
});
|
||||||
|
}
|
||||||
/*! \brief This function colores all the faces of a mesh with a hue color shade dependent on the quality.
|
/*! \brief This function colores all the faces of a mesh with a hue color shade dependent on the quality.
|
||||||
|
|
||||||
If no range of quality is passed it is automatically computed.
|
If no range of quality is passed it is automatically computed.
|
||||||
*/
|
*/
|
||||||
static void PerFaceQualityRamp(MeshType &m, float minq=0, float maxq=0, bool selected=false)
|
static void PerFaceQualityRamp(MeshType &m, ScalarType minq = 0, ScalarType maxq = 0, bool selected = false)
|
||||||
{
|
{
|
||||||
RequirePerFaceColor(m);
|
RequirePerFaceColor(m);
|
||||||
RequirePerFaceQuality(m);
|
RequirePerFaceQuality(m);
|
||||||
|
|
||||||
if(minq==maxq)
|
if(minq == maxq)
|
||||||
{
|
{
|
||||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||||
minq=minmax.first;
|
minq=minmax.first;
|
||||||
maxq=minmax.second;
|
maxq=minmax.second;
|
||||||
}
|
}
|
||||||
for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
|
for(FaceIterator fi = m.face.begin();fi != m.face.end(); ++fi)
|
||||||
if(!selected || (*fi).IsS())
|
if(!(*fi).IsD())
|
||||||
(*fi).C().SetColorRamp(minq,maxq,(*fi).Q());
|
if(!selected || (*fi).IsS())
|
||||||
|
(*fi).C().SetColorRamp(minq, maxq, (*fi).Q());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief This function colores all the edges of a mesh with a hue color shade dependent on the quality.
|
/*! \brief This function colores all the edges of a mesh with a hue color shade dependent on the quality.
|
||||||
|
|
||||||
If no range of quality is passed it is automatically computed.
|
If no range of quality is passed it is automatically computed.
|
||||||
*/
|
*/
|
||||||
static void PerEdgeQualityRamp(MeshType &m, float minq=0, float maxq=0, bool selected=false)
|
static void PerEdgeQualityRamp(MeshType &m, ScalarType minq = 0, ScalarType maxq = 0, bool selected = false)
|
||||||
{
|
{
|
||||||
RequirePerEdgeColor(m);
|
RequirePerEdgeColor(m);
|
||||||
RequirePerEdgeQuality(m);
|
RequirePerEdgeQuality(m);
|
||||||
|
|
||||||
if(minq==maxq)
|
if(minq == maxq)
|
||||||
{
|
{
|
||||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerEdgeQualityMinMax(m);
|
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerEdgeQualityMinMax(m);
|
||||||
minq=minmax.first;
|
minq=minmax.first;
|
||||||
maxq=minmax.second;
|
maxq=minmax.second;
|
||||||
}
|
}
|
||||||
|
|
@ -248,13 +323,13 @@ public:
|
||||||
|
|
||||||
If no range of quality is passed it is automatically computed.
|
If no range of quality is passed it is automatically computed.
|
||||||
*/
|
*/
|
||||||
static void PerVertexQualityGray(MeshType &m, float minq, float maxq)
|
static void PerVertexQualityGray(MeshType &m, ScalarType minq = 0, ScalarType maxq = 0)
|
||||||
{
|
{
|
||||||
RequirePerVertexColor(m);
|
RequirePerVertexColor(m);
|
||||||
RequirePerVertexQuality(m);
|
RequirePerVertexQuality(m);
|
||||||
if(minq==maxq)
|
if(minq==maxq)
|
||||||
{
|
{
|
||||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
||||||
minq=minmax.first;
|
minq=minmax.first;
|
||||||
maxq=minmax.second;
|
maxq=minmax.second;
|
||||||
}
|
}
|
||||||
|
|
@ -267,14 +342,14 @@ public:
|
||||||
|
|
||||||
If no range of quality is passed it is automatically computed.
|
If no range of quality is passed it is automatically computed.
|
||||||
*/
|
*/
|
||||||
static void PerFaceQualityGray(MeshType &m, float minq=0, float maxq=0)
|
static void PerFaceQualityGray(MeshType &m, ScalarType minq = 0, ScalarType maxq = 0)
|
||||||
{
|
{
|
||||||
RequirePerFaceColor(m);
|
RequirePerFaceColor(m);
|
||||||
RequirePerFaceQuality(m);
|
RequirePerFaceQuality(m);
|
||||||
|
|
||||||
if(minq==maxq)
|
if(minq==maxq)
|
||||||
{
|
{
|
||||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||||
minq=minmax.first;
|
minq=minmax.first;
|
||||||
maxq=minmax.second;
|
maxq=minmax.second;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -148,11 +148,11 @@ static void TetraConstant(MeshType & m, const TetraQualityType q)
|
||||||
t.Q() = q;
|
t.Q() = q;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
static void TetraVolume(MeshType & m)
|
static void TetraFromVolume(MeshType & m)
|
||||||
{
|
{
|
||||||
tri::RequirePerTetraQuality(m);
|
tri::RequirePerTetraQuality(m);
|
||||||
ForEachTetra(m, [] (MeshType::TetraType & t) {
|
ForEachTetra(m, [] (MeshType::TetraType & t) {
|
||||||
t.Q() = TetraQualityType(vcg::Tetra::ComputeVolume(t));
|
t.Q() = TetraQualityType(vcg::Tetra::ComputeVolume(t));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue