added some useful functions on tetras

This commit is contained in:
T.Alderighi 2018-05-09 17:52:50 +02:00
parent 05764ee1c2
commit 2b7e5ba20b
3 changed files with 206 additions and 50 deletions

View File

@ -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);

View File

@ -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;
} }

View File

@ -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));
}); });
} }