added some useful functions on tetras
This commit is contained in:
parent
05764ee1c2
commit
2b7e5ba20b
|
|
@ -51,21 +51,27 @@ public:
|
|||
typedef typename MeshType::FacePointer FacePointer;
|
||||
typedef typename MeshType::FaceIterator FaceIterator;
|
||||
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;
|
||||
|
||||
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);
|
||||
minV=pp.first; maxV=pp.second;
|
||||
std::pair<ScalarType, ScalarType> pp = ComputePerVertexQualityMinMax(m);
|
||||
|
||||
minV=pp.first;
|
||||
maxV=pp.second;
|
||||
}
|
||||
static std::pair<float,float> ComputePerVertexQualityMinMax( MeshType & m)
|
||||
static std::pair<ScalarType, ScalarType> ComputePerVertexQualityMinMax(MeshType & m)
|
||||
{
|
||||
// assert(0);
|
||||
tri::RequirePerVertexQuality(m);
|
||||
typename MeshType::template PerMeshAttributeHandle < std::pair<float,float> > mmqH;
|
||||
mmqH = tri::Allocator<MeshType>::template GetPerMeshAttribute <std::pair<float,float> >(m,"minmaxQ");
|
||||
typename MeshType::template PerMeshAttributeHandle < std::pair<ScalarType, ScalarType> > mmqH;
|
||||
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)
|
||||
if(!(*vi).IsD())
|
||||
|
|
@ -78,10 +84,12 @@ public:
|
|||
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);
|
||||
minV=pp.first; maxV=pp.second;
|
||||
std::pair<ScalarType, ScalarType> pp = ComputePerFaceQualityMinMax(m);
|
||||
minV=pp.first;
|
||||
maxV=pp.second;
|
||||
}
|
||||
|
||||
static std::pair<ScalarType,ScalarType> ComputePerFaceQualityMinMax( MeshType & m)
|
||||
|
|
@ -99,6 +107,39 @@ public:
|
|||
return minmax;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
@ -195,6 +236,17 @@ public:
|
|||
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)
|
||||
{
|
||||
Inertia<MeshType> I(m);
|
||||
|
|
@ -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);
|
||||
std::pair<float,float> minmax = tri::Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||
std::pair<ScalarType, ScalarType> minmax = tri::Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||
h.Clear();
|
||||
h.SetRange( minmax.first,minmax.second, HistSize );
|
||||
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);
|
||||
std::pair<float,float> minmax = ComputePerVertexQualityMinMax(m);
|
||||
std::pair<ScalarType, ScalarType> minmax = ComputePerVertexQualityMinMax(m);
|
||||
|
||||
h.Clear();
|
||||
h.SetRange( minmax.first,minmax.second, HistSize);
|
||||
|
|
@ -284,15 +365,15 @@ public:
|
|||
|
||||
if(h.MaxCount() > HistSize/5)
|
||||
{
|
||||
std::vector<float> QV;
|
||||
std::vector<ScalarType> 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);
|
||||
ScalarType 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);
|
||||
ScalarType newmax=*(QV.begin()+m.vn-m.vn/100);
|
||||
|
||||
h.Clear();
|
||||
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);
|
||||
h.Clear();
|
||||
|
|
@ -331,7 +412,7 @@ public:
|
|||
});
|
||||
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;
|
||||
tri::UpdateTopology<MeshType>::FillUniqueEdgeVector(m,edgeVec,includeFauxEdge);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ public:
|
|||
typedef typename MeshType::FacePointer FacePointer;
|
||||
typedef typename MeshType::FaceIterator FaceIterator;
|
||||
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::CoordType CoordType;
|
||||
|
|
@ -73,7 +77,7 @@ public:
|
|||
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)
|
||||
{
|
||||
|
|
@ -91,7 +95,7 @@ public:
|
|||
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)
|
||||
{
|
||||
|
|
@ -108,6 +112,55 @@ public:
|
|||
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
|
||||
|
||||
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.
|
||||
*/
|
||||
static void PerVertexQualityRamp(MeshType &m, float minq=0, float maxq=0)
|
||||
static void PerVertexQualityRamp(MeshType &m, ScalarType minq = 0., ScalarType maxq = 0.)
|
||||
{
|
||||
RequirePerVertexQuality(m);
|
||||
RequirePerVertexColor(m);
|
||||
|
||||
if(minq == maxq)
|
||||
{
|
||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
||||
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
||||
minq=minmax.first;
|
||||
maxq=minmax.second;
|
||||
}
|
||||
|
|
@ -188,14 +241,14 @@ public:
|
|||
|
||||
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);
|
||||
RequirePerVertexColor(m);
|
||||
|
||||
if(minq == maxq)
|
||||
{
|
||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
||||
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
||||
minq=minmax.first;
|
||||
maxq=minmax.second;
|
||||
}
|
||||
|
|
@ -208,18 +261,40 @@ public:
|
|||
|
||||
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 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.
|
||||
|
||||
If no range of quality is passed it is automatically computed.
|
||||
*/
|
||||
static void PerFaceQualityRamp(MeshType &m, ScalarType minq = 0, ScalarType maxq = 0, bool selected = false)
|
||||
{
|
||||
RequirePerFaceColor(m);
|
||||
RequirePerFaceQuality(m);
|
||||
|
||||
if(minq == maxq)
|
||||
{
|
||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||
minq=minmax.first;
|
||||
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(!(*fi).IsD())
|
||||
if(!selected || (*fi).IsS())
|
||||
(*fi).C().SetColorRamp(minq, maxq, (*fi).Q());
|
||||
}
|
||||
|
|
@ -228,14 +303,14 @@ public:
|
|||
|
||||
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);
|
||||
RequirePerEdgeQuality(m);
|
||||
|
||||
if(minq == maxq)
|
||||
{
|
||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerEdgeQualityMinMax(m);
|
||||
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerEdgeQualityMinMax(m);
|
||||
minq=minmax.first;
|
||||
maxq=minmax.second;
|
||||
}
|
||||
|
|
@ -248,13 +323,13 @@ public:
|
|||
|
||||
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);
|
||||
RequirePerVertexQuality(m);
|
||||
if(minq==maxq)
|
||||
{
|
||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
||||
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
||||
minq=minmax.first;
|
||||
maxq=minmax.second;
|
||||
}
|
||||
|
|
@ -267,14 +342,14 @@ public:
|
|||
|
||||
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);
|
||||
RequirePerFaceQuality(m);
|
||||
|
||||
if(minq==maxq)
|
||||
{
|
||||
std::pair<float,float> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||
std::pair<ScalarType, ScalarType> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||
minq=minmax.first;
|
||||
maxq=minmax.second;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ static void TetraConstant(MeshType & m, const TetraQualityType q)
|
|||
t.Q() = q;
|
||||
});
|
||||
}
|
||||
static void TetraVolume(MeshType & m)
|
||||
static void TetraFromVolume(MeshType & m)
|
||||
{
|
||||
tri::RequirePerTetraQuality(m);
|
||||
ForEachTetra(m, [] (MeshType::TetraType & t) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue