code refactoring for curvature colorize

added colorize equalizer dialog and
"Colorize by Quality" filter
some small bugfixes
removed color_curvature.h in favour of curvature.h
This commit is contained in:
Paolo Cignoni cignoni 2006-01-27 18:27:53 +00:00
parent 556e11f656
commit 2b3ef6238d
8 changed files with 834 additions and 360 deletions

View File

@ -1,335 +0,0 @@
/****************************************************************************
* MeshLab o o *
* A versatile mesh processing toolbox o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log$
Revision 1.4 2006/01/23 11:48:48 vannini
bugfix in AreaMix() (voronoi area)
Revision 1.3 2006/01/20 16:25:39 vannini
Added Absolute Curvature colorize
Revision 1.2 2006/01/20 14:46:44 vannini
Code refactoring
Added RMS Curvature colorize
Revision 1.1 2006/01/13 16:24:16 vannini
Moved gaussian and mean curvature functions into color_curvature.h
****************************************************************************/
#ifndef EXTRACOLOR_CURVATURE_H
#define EXTRACOLOR_CURVATURE_H
#include <iostream>
#include <QtGlobal>
#include <vcg/complex/trimesh/base.h>
#include <vcg/complex/trimesh/clean.h>
#include <vcg/space/triangle3.h>
#include <vcg/complex/trimesh/update/topology.h>
#include <vcg/math/histogram.h>
#include "../../meshlab/LogStream.h"
#define DEFAULT_HISTO_FRAC 0.1f
#define DEFAULT_HISTO_RANGE 10000
class histoMinMaxQ
{
public:
float minQ, maxQ;
};
namespace vcg
{
template<class MESH_TYPE> void AreaMix(MESH_TYPE &m)
{
typename MESH_TYPE::VertexIterator vi;
typename MESH_TYPE::FaceIterator fi;
float area0, area1, area2;
float angle0, angle1, angle2;
for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
(*vi).Q() = 0.0;
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
{
// angles
angle0 = math::Abs(Angle( (*fi).P(1)-(*fi).P(0),(*fi).P(2)-(*fi).P(0) ));
angle1 = math::Abs(Angle( (*fi).P(0)-(*fi).P(1),(*fi).P(2)-(*fi).P(1) ));
angle2 = M_PI-(angle0+angle1);
if((angle0 < M_PI/2) || (angle1 < M_PI/2) || (angle2 < M_PI/2)) // triangolo non ottuso
{
float e01 = SquaredDistance( (*fi).V(1)->P() , (*fi).V(0)->P() );
float e12 = SquaredDistance( (*fi).V(2)->P() , (*fi).V(1)->P() );
float e20 = SquaredDistance( (*fi).V(0)->P() , (*fi).V(2)->P() );
area0 = ( e20*(1.0/tan(angle1)) + e01*(1.0/tan(angle2)) ) / 8.0;
area1 = ( e01*(1.0/tan(angle2)) + e12*(1.0/tan(angle0)) ) / 8.0;
area2 = ( e12*(1.0/tan(angle0)) + e20*(1.0/tan(angle1)) ) / 8.0;
(*fi).V(0)->Q() += area0;
(*fi).V(1)->Q() += area1;
(*fi).V(2)->Q() += area2;
}
else // triangolo ottuso
{
(*fi).V(0)->Q() += vcg::DoubleArea<CFaceO>((*fi)) / 6.0;
(*fi).V(1)->Q() += vcg::DoubleArea<CFaceO>((*fi)) / 6.0;
(*fi).V(2)->Q() += vcg::DoubleArea<CFaceO>((*fi)) / 6.0;
}
}
}
template<class MESH_TYPE> histoMinMaxQ HK(MESH_TYPE &m, bool computeH, bool useHisto, float histo_frac=DEFAULT_HISTO_FRAC, int histo_range=DEFAULT_HISTO_RANGE)
{
// Calcola la curvatura gaussiana (K) oppure la media (H) in base a computeH
// e salva il risultato in Q
// Se useHisto è true approssima il risultato usando l'istogramma
float *area;
int i;
float area0, area1, area2, angle0, angle1, angle2, e01, e12, e20, t;
typename MESH_TYPE::VertexIterator vi;
typename MESH_TYPE::FaceIterator fi;
vcg::Histogram<float> histo;
histoMinMaxQ hmmq;
area = new float[m.vn];
hmmq.minQ = std::numeric_limits<float>::max();
hmmq.maxQ = -std::numeric_limits<float>::max();
AreaMix(m);
if (computeH)
t=0;
else
t=(float)(2.0 * M_PI);
i = 0;
for(vi=m.vert.begin();vi!=m.vert.end();++vi,++i) if(!(*vi).IsD())
{
area[i] = (*vi).Q();
(*vi).Q() = t;
}
if (computeH)
{
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
{
angle0 = math::Abs(Angle( (*fi).P(1)-(*fi).P(0),(*fi).P(2)-(*fi).P(0) ));
angle1 = math::Abs(Angle( (*fi).P(0)-(*fi).P(1),(*fi).P(2)-(*fi).P(1) ));
angle2 = M_PI-(angle0+angle1);
e01 = Distance( (*fi).V(1)->P() , (*fi).V(0)->P() );
e12 = Distance( (*fi).V(2)->P() , (*fi).V(1)->P() );
e20 = Distance( (*fi).V(0)->P() , (*fi).V(2)->P() );
area0 = ( e01*(1.0/tan(angle2)) + e20*(1.0/tan(angle1)) )/2;
area1 = ( e01*(1.0/tan(angle2)) + e12*(1.0/tan(angle0)) )/2;
area2 = ( e20*(1.0/tan(angle1)) + e20*(1.0/tan(angle0)) )/2;
(*fi).V(0)->Q() += area0;
(*fi).V(1)->Q() += area1;
(*fi).V(2)->Q() += area2;
}
}
else
{
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
{
float angle0 = math::Abs(Angle((*fi).P(1)-(*fi).P(0),(*fi).P(2)-(*fi).P(0)));
float angle1 = math::Abs(Angle((*fi).P(0)-(*fi).P(1),(*fi).P(2)-(*fi).P(1)));
float angle2 = M_PI-(angle0+angle1);
(*fi).V(0)->Q() -= angle0;
(*fi).V(1)->Q() -= angle1;
(*fi).V(2)->Q() -= angle2;
}
}
if (!useHisto)
{
i=0;
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi,++i) if(!(*vi).IsD())
{
if(area[i]<=std::numeric_limits<float>::epsilon())
(*vi).Q() = 0;
else
(*vi).Q() /= area[i];
}
delete[] area;
return hmmq;
}
i=0;
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi,++i) if(!(*vi).IsD())
{
if(area[i]<=std::numeric_limits<float>::epsilon())
(*vi).Q() = 0;
else
(*vi).Q() /= area[i];
if ((*vi).Q() < hmmq.minQ) hmmq.minQ = (*vi).Q();
if ((*vi).Q() > hmmq.maxQ) hmmq.maxQ = (*vi).Q();
}
histo.SetRange(hmmq.minQ, hmmq.maxQ, histo_range);
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD())
histo.Add((*vi).Q());
hmmq.minQ = histo.Percentile(histo_frac);
hmmq.maxQ = histo.Percentile(1.0f - histo_frac);
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD())
(*vi).Q() = math::Clamp((*vi).Q(), hmmq.minQ, hmmq.maxQ);
delete[] area;
return hmmq;
}
template<class MESH_TYPE> void ColorGaussian(MESH_TYPE &m, GLLogStream *log)
{
histoMinMaxQ result = HK(m,false,true);
if (log)
log->Log(GLLogStream::Info, "Gaussian Curvature: minQ=%f maxQ=%f", result.minQ, result.maxQ);
}
template<class MESH_TYPE> void ColorMean(MESH_TYPE &m, GLLogStream *log)
{
histoMinMaxQ result = HK(m,true,true);
if (log)
log->Log(GLLogStream::Info, "Mean Curvature: minQ=%f maxQ=%f", result.minQ, result.maxQ);
}
template<class MESH_TYPE> void ColorRMS(MESH_TYPE &m, GLLogStream *log)
{
float *HH4 = new float[m.vn];
int i;
typename MESH_TYPE::VertexIterator vi;
vcg::Histogram<float> histo;
float histo_frac=DEFAULT_HISTO_FRAC;
int histo_range=DEFAULT_HISTO_RANGE;
float minQ = std::numeric_limits<float>::max();
float maxQ = -std::numeric_limits<float>::max();
//Compute 4*(H^2)
HK(m,true,false);
i=0;
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi,++i) if(!(*vi).IsD())
HH4[i] = 4.0f * powf((*vi).Q(),2.0f);
//Compute K
HK(m,false,false);
//Compute sqrt(HH4-2K)
i=0;
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi,++i) if(!(*vi).IsD())
{
(*vi).Q()=math::Sqrt(HH4[i] - ( (*vi).Q() * 2.0) );
if ((*vi).Q() < minQ) minQ = (*vi).Q();
if ((*vi).Q() > maxQ) maxQ = (*vi).Q();
}
histo.SetRange(minQ, maxQ, histo_range);
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD())
histo.Add((*vi).Q());
minQ = histo.Percentile(histo_frac);
maxQ = histo.Percentile(1.0f - histo_frac);
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD())
(*vi).Q() = math::Clamp((*vi).Q(), minQ, maxQ);
if (log)
log->Log(GLLogStream::Info, "RMS Curvature: minQ=%f maxQ=%f", minQ, maxQ);
delete[] HH4;
}
template<class MESH_TYPE> void ColorAbsolute(MESH_TYPE &m, GLLogStream *log)
{
float *H = new float[m.vn];
int i;
typename MESH_TYPE::VertexIterator vi;
vcg::Histogram<float> histo;
float histo_frac=DEFAULT_HISTO_FRAC;
int histo_range=DEFAULT_HISTO_RANGE;
float minQ = std::numeric_limits<float>::max();
float maxQ = -std::numeric_limits<float>::max();
//Compute H
HK(m,true,false);
i=0;
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi,++i) if(!(*vi).IsD())
H[i] = (*vi).Q();
//Compute K
HK(m,false,false);
//Compute abs(H+sqrt(H*H-K)) + abs(H-sqrt(H*H-K))
i=0;
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi,++i) if(!(*vi).IsD())
{
(*vi).Q() = math::Abs(H[i] + math::Sqrt(powf(H[i], 2.0f) - (*vi).Q())) + math::Abs(H[i] - math::Sqrt(powf(H[i], 2.0f) - (*vi).Q()));
if ((*vi).Q() < minQ) minQ = (*vi).Q();
if ((*vi).Q() > maxQ) maxQ = (*vi).Q();
}
histo.SetRange(minQ, maxQ, histo_range);
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD())
histo.Add((*vi).Q());
minQ = histo.Percentile(histo_frac);
maxQ = histo.Percentile(1.0f - histo_frac);
for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi) if(!(*vi).IsD())
(*vi).Q() = math::Clamp((*vi).Q(), minQ, maxQ);
if (log)
log->Log(GLLogStream::Info, "Absolute Curvature: minQ=%f maxQ=%f", minQ, maxQ);
delete[] H;
}
}
#endif

View File

@ -0,0 +1,266 @@
/****************************************************************************
* MeshLab o o *
* A versatile mesh processing toolbox o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log$
Revision 1.1 2006/01/27 18:27:53 vannini
code refactoring for curvature colorize
added colorize equalizer dialog and
"Colorize by Quality" filter
some small bugfixes
removed color_curvature.h in favour of curvature.h
****************************************************************************/
#ifndef CURVATURE_H
#define CURVATURE_H
#include <vcg/container/simple_temporary_data.h>
#include <vcg/complex/trimesh/base.h>
#include <vcg/complex/trimesh/clean.h>
#include <vcg/space/triangle3.h>
#include <vcg/complex/trimesh/update/topology.h>
#include <vcg/math/histogram.h>
#define DEFAULT_HISTO_FRAC 0.05f
#define DEFAULT_HISTO_RANGE 10000
namespace vcg
{
class CurvData
{
public:
float H;
float K;
};
class Frange
{
public:
float min;
float max;
};
template <class MESH_TYPE> class Curvature
{
typedef typename MESH_TYPE::FaceIterator FaceIterator;
typedef typename MESH_TYPE::VertexIterator VertexIterator;
typedef typename MESH_TYPE::VertContainer VertContainer;
private:
MESH_TYPE *ms;
SimpleTempData<VertContainer, CurvData> *TDPtr;
void ComputeHK()
{
float *areaH,*areaK;
int i;
float area0, area1, area2, angle0, angle1, angle2, e01, e12, e20, t;
FaceIterator fi;
VertexIterator vi;
//Calcola AreaMix in H (vale anche per K)
for(vi=(*ms).vert.begin(); vi!=(*ms).vert.end(); ++vi) if(!(*vi).IsD())
(*TDPtr)[*vi].H=0;
for(fi=(*ms).face.begin();fi!=(*ms).face.end();++fi) if(!(*fi).IsD())
{
// angles
angle0 = math::Abs(Angle( (*fi).P(1)-(*fi).P(0),(*fi).P(2)-(*fi).P(0) ));
angle1 = math::Abs(Angle( (*fi).P(0)-(*fi).P(1),(*fi).P(2)-(*fi).P(1) ));
angle2 = M_PI-(angle0+angle1);
if((angle0 < M_PI/2) || (angle1 < M_PI/2) || (angle2 < M_PI/2)) // triangolo non ottuso
{
float e01 = SquaredDistance( (*fi).V(1)->P() , (*fi).V(0)->P() );
float e12 = SquaredDistance( (*fi).V(2)->P() , (*fi).V(1)->P() );
float e20 = SquaredDistance( (*fi).V(0)->P() , (*fi).V(2)->P() );
area0 = ( e20*(1.0/tan(angle1)) + e01*(1.0/tan(angle2)) ) / 8.0;
area1 = ( e01*(1.0/tan(angle2)) + e12*(1.0/tan(angle0)) ) / 8.0;
area2 = ( e12*(1.0/tan(angle0)) + e20*(1.0/tan(angle1)) ) / 8.0;
(*TDPtr)[(*fi).V(0)].H += area0;
(*TDPtr)[(*fi).V(1)].H += area1;
(*TDPtr)[(*fi).V(2)].H += area2;
}
else // triangolo ottuso
{
(*TDPtr)[(*fi).V(0)].H += vcg::DoubleArea<CFaceO>((*fi)) / 6.0;
(*TDPtr)[(*fi).V(1)].H += vcg::DoubleArea<CFaceO>((*fi)) / 6.0;
(*TDPtr)[(*fi).V(2)].H += vcg::DoubleArea<CFaceO>((*fi)) / 6.0;
}
}
i = 0;
areaH = new float[(*ms).vn];
areaK = new float[(*ms).vn];
for(vi=(*ms).vert.begin(); vi!=(*ms).vert.end(); ++vi,++i) if(!(*vi).IsD())
{
areaH[i] = areaK[i] = (*TDPtr)[*vi].H; //Areamix è comune a H e a K
(*TDPtr)[*vi].H = 0;
(*TDPtr)[*vi].K = (float)(2.0 * M_PI);
}
for(fi=(*ms).face.begin();fi!=(*ms).face.end();++fi) if(!(*fi).IsD())
{
angle0 = math::Abs(Angle( (*fi).P(1)-(*fi).P(0),(*fi).P(2)-(*fi).P(0) ));
angle1 = math::Abs(Angle( (*fi).P(0)-(*fi).P(1),(*fi).P(2)-(*fi).P(1) ));
angle2 = M_PI-(angle0+angle1);
e01 = Distance( (*fi).V(1)->P() , (*fi).V(0)->P() );
e12 = Distance( (*fi).V(2)->P() , (*fi).V(1)->P() );
e20 = Distance( (*fi).V(0)->P() , (*fi).V(2)->P() );
area0 = ( e20*(1.0/tan(angle1)) + e01*(1.0/tan(angle2)) ) / 2.0;
area1 = ( e01*(1.0/tan(angle2)) + e12*(1.0/tan(angle0)) ) / 2.0;
area2 = ( e12*(1.0/tan(angle0)) + e20*(1.0/tan(angle1)) ) / 2.0;
(*TDPtr)[(*fi).V(0)].H += area0;
(*TDPtr)[(*fi).V(1)].H += area1;
(*TDPtr)[(*fi).V(2)].H += area2;
(*TDPtr)[(*fi).V(0)].K -= angle0;
(*TDPtr)[(*fi).V(1)].K -= angle1;
(*TDPtr)[(*fi).V(2)].K -= angle2;
}
i=0;
for(vi=(*ms).vert.begin(); vi!=(*ms).vert.end(); ++vi,++i) if(!(*vi).IsD())
{
if(areaH[i]<=std::numeric_limits<float>::epsilon())
(*TDPtr)[*vi].H = 0;
else
(*TDPtr)[*vi].H /= areaH[i];
if(areaK[i]<=std::numeric_limits<float>::epsilon())
(*TDPtr)[*vi].K = 0;
else
(*TDPtr)[*vi].K /= areaK[i];
}
delete[] areaH;
delete[] areaK;
}
public:
Curvature(MESH_TYPE &mt):ms(&mt)
{
TDPtr = new SimpleTempData<VertContainer, CurvData>((*ms).vert);
(*TDPtr).Start(CurvData());
ComputeHK();
}
~Curvature()
{
(*TDPtr).Stop();
}
void MapGaussianCurvatureIntoQuality()
{
VertexIterator vi;
for(vi=(*ms).vert.begin(); vi!=(*ms).vert.end(); ++vi) if(!(*vi).IsD())
(*vi).Q() = (*TDPtr)[*vi].K;
}
void MapMeanCurvatureIntoQuality()
{
VertexIterator vi;
for(vi=(*ms).vert.begin(); vi!=(*ms).vert.end(); ++vi) if(!(*vi).IsD())
(*vi).Q() = (*TDPtr)[*vi].H;
}
void MapRMSCurvatureIntoQuality()
{
VertexIterator vi;
//Compute sqrt(4*H^2-2K)
for(vi=(*ms).vert.begin(); vi!=(*ms).vert.end(); ++vi) if(!(*vi).IsD())
(*vi).Q()=math::Sqrt((4.0f * powf((*TDPtr)[*vi].H, 2.0f)) - ((*TDPtr)[*vi].K * 2.0f));
}
void MapAbsoluteCurvatureIntoQuality()
{
VertexIterator vi;
float t;
//Compute abs(H+sqrt(H*H-K)) + abs(H-sqrt(H*H-K))
for(vi=(*ms).vert.begin(); vi!=(*ms).vert.end(); ++vi) if(!(*vi).IsD())
{
t=math::Sqrt(powf((*TDPtr)[*vi].H, 2.0f) - (*TDPtr)[*vi].K);
(*vi).Q()= math::Abs((*TDPtr)[*vi].H + t) + math::Abs((*TDPtr)[*vi].H - t);
}
}
Frange minMaxQ()
{
VertexIterator vi;
Frange r;
r.min=std::numeric_limits<float>::max();
r.max=-std::numeric_limits<float>::max();
for(vi=(*ms).vert.begin(); vi!=(*ms).vert.end(); ++vi) if(!(*vi).IsD())
{
if ((*vi).Q() < r.min) r.min = (*vi).Q();
if ((*vi).Q() > r.max) r.max = (*vi).Q();
}
return r;
}
Frange histoPercentile(Frange Q, float histo_frac=DEFAULT_HISTO_FRAC, int histo_range=DEFAULT_HISTO_RANGE)
{
VertexIterator vi;
vcg::Histogram<float> histo;
histo.SetRange(Q.min, Q.max, histo_range);
for(vi=(*ms).vert.begin(); vi!=(*ms).vert.end(); ++vi) if(!(*vi).IsD())
histo.Add((*vi).Q());
Q.min = histo.Percentile(histo_frac);
Q.max = histo.Percentile(1.0f - histo_frac);
return Q;
}
void ColorizeByEqualizedQuality(Frange P)
{
VertexIterator vi;
for(vi=(*ms).vert.begin(); vi!=(*ms).vert.end(); ++vi) if(!(*vi).IsD())
(*vi).C().ColorRamp(P.min, P.max, (*vi).Q());
}
};
}
#endif // CURVATURE_H

View File

@ -0,0 +1,69 @@
/****************************************************************************
* MeshLab o o *
* A versatile mesh processing toolbox o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log$
Revision 1.1 2006/01/27 18:27:53 vannini
code refactoring for curvature colorize
added colorize equalizer dialog and
"Colorize by Quality" filter
some small bugfixes
removed color_curvature.h in favour of curvature.h
****************************************************************************/
#include "equalizerDialog.h"
EqualizerDialog::EqualizerDialog(QWidget *parent): QDialog(parent)
{
ui.setupUi(this);
connect(ui.cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
connect(ui.applyButton, SIGNAL(clicked()), this, SLOT(accept()));
setFixedSize(338,232);
}
EqualizerDialog::~EqualizerDialog()
{
}
void EqualizerDialog::setValues(const EqualizerSettings& es)
{
settings=es;
QString qnum="%1";
ui.percentileSpinbox->setValue(settings.percentile);
ui.rangeSpinbox->setValue(settings.range);
ui.meshMinQlineEdit->setText(qnum.arg(settings.meshMinQ));
ui.meshMaxQlineEdit->setText(qnum.arg(settings.meshMaxQ));
ui.histoMinQlineEdit->setText(qnum.arg(settings.histoMinQ));
ui.histoMaxQlineEdit->setText(qnum.arg(settings.histoMaxQ));
}
EqualizerSettings EqualizerDialog::getValues()
{
settings.percentile = ui.percentileSpinbox->value();
settings.range=ui.rangeSpinbox->value();
return settings;
}

View File

@ -0,0 +1,77 @@
/****************************************************************************
* MeshLab o o *
* A versatile mesh processing toolbox o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log$
Revision 1.1 2006/01/27 18:27:53 vannini
code refactoring for curvature colorize
added colorize equalizer dialog and
"Colorize by Quality" filter
some small bugfixes
removed color_curvature.h in favour of curvature.h
****************************************************************************/
#ifndef EQUALIZERDIALOG_H
#define EQUALIZERDIALOG_H
#include <QWidget>
#include <QDialog>
#include "ui_equalizerDialog.h"
class EqualizerSettings
{
public:
int percentile;
int range;
float meshMaxQ;
float meshMinQ;
float histoMaxQ;
float histoMinQ;
EqualizerSettings()
{
percentile=20;
range=10000;
meshMaxQ=meshMinQ=histoMaxQ=histoMinQ=0.0f;
};
};
class EqualizerDialog : public QDialog
{
Q_OBJECT
private:
Ui::EqualizerDialogClass ui;
EqualizerSettings settings;
public:
EqualizerDialog(QWidget *parent = 0);
~EqualizerDialog();
void EqualizerDialog::setValues(const EqualizerSettings& es);
EqualizerSettings EqualizerDialog::getValues();
};
#endif // EQUALIZERDIALOG_H

View File

@ -0,0 +1,345 @@
<ui version="4.0" >
<author></author>
<comment></comment>
<exportmacro></exportmacro>
<class>EqualizerDialogClass</class>
<widget class="QWidget" name="EqualizerDialogClass" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>333</width>
<height>228</height>
</rect>
</property>
<property name="windowTitle" >
<string>equalizerDialog</string>
</property>
<widget class="QGroupBox" name="groupBox" >
<property name="geometry" >
<rect>
<x>10</x>
<y>90</y>
<width>321</width>
<height>101</height>
</rect>
</property>
<property name="title" >
<string>Mesh/Histogram values</string>
</property>
<widget class="QWidget" name="layoutWidget" >
<property name="geometry" >
<rect>
<x>10</x>
<y>30</y>
<width>301</width>
<height>48</height>
</rect>
</property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize" >
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text" >
<string>&lt;html>&lt;head>&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; />&lt;/head>&lt;body style=&quot; white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;&quot;>&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;>Min Q:&lt;/p>&lt;/body>&lt;/html></string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="meshMinQlineEdit" >
<property name="enabled" >
<bool>true</bool>
</property>
<property name="readOnly" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="histoMinQlineEdit" >
<property name="enabled" >
<bool>true</bool>
</property>
<property name="readOnly" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label_2" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize" >
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text" >
<string>&lt;html>&lt;head>&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; />&lt;/head>&lt;body style=&quot; white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;&quot;>&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;>Max Q:&lt;/p>&lt;/body>&lt;/html></string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="meshMaxQlineEdit" >
<property name="enabled" >
<bool>true</bool>
</property>
<property name="readOnly" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="histoMaxQlineEdit" >
<property name="readOnly" >
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<widget class="QGroupBox" name="groupBox_2" >
<property name="geometry" >
<rect>
<x>10</x>
<y>10</y>
<width>321</width>
<height>71</height>
</rect>
</property>
<property name="title" >
<string>Histogram Parameters</string>
</property>
<widget class="QWidget" name="layoutWidget_2" >
<property name="geometry" >
<rect>
<x>10</x>
<y>30</y>
<width>301</width>
<height>22</height>
</rect>
</property>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label_3" >
<property name="minimumSize" >
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text" >
<string>&lt;html>&lt;head>&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; />&lt;/head>&lt;body style=&quot; white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;&quot;>&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;>Percentile&lt;/p>&lt;/body>&lt;/html></string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="percentileSpinbox" >
<property name="minimumSize" >
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>65</width>
<height>16777215</height>
</size>
</property>
<property name="prefix" >
<string>1/</string>
</property>
<property name="maximum" >
<number>98</number>
</property>
<property name="minimum" >
<number>2</number>
</property>
<property name="value" >
<number>20</number>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>51</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_4" >
<property name="minimumSize" >
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text" >
<string>&lt;html>&lt;head>&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; />&lt;/head>&lt;body style=&quot; white-space: pre-wrap; font-family:MS Shell Dlg; font-weight:400; font-style:normal; text-decoration:none;&quot;>&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;>Range&lt;/p>&lt;/body>&lt;/html></string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="rangeSpinbox" >
<property name="minimumSize" >
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="maximumSize" >
<size>
<width>65</width>
<height>16777215</height>
</size>
</property>
<property name="maximum" >
<number>10000000</number>
</property>
<property name="minimum" >
<number>100</number>
</property>
<property name="singleStep" >
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="layoutWidget_3" >
<property name="geometry" >
<rect>
<x>10</x>
<y>200</y>
<width>321</width>
<height>25</height>
</rect>
</property>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<number>6</number>
</property>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="cancelButton" >
<property name="text" >
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="applyButton" >
<property name="text" >
<string>Apply</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<layoutdefault spacing="6" margin="11" />
<pixmapfunction></pixmapfunction>
<resources/>
<connections/>
</ui>

View File

@ -23,6 +23,13 @@
/****************************************************************************
History
$Log$
Revision 1.20 2006/01/27 18:27:53 vannini
code refactoring for curvature colorize
added colorize equalizer dialog and
"Colorize by Quality" filter
some small bugfixes
removed color_curvature.h in favour of curvature.h
Revision 1.19 2006/01/20 18:17:07 vannini
added Restore Color
@ -85,12 +92,13 @@ Added copyright info
#include <vcg/complex/trimesh/update/flag.h>
#include "meshcolorize.h"
#include "color_manifold.h"
#include "color_curvature.h"
#include "curvature.h"
using namespace vcg;
ExtraMeshColorizePlugin::ExtraMeshColorizePlugin() {
actionList << new QAction(ST(CP_GAUSSIAN), this);
actionList << new QAction(ST(CP_EQUALIZE), this);
actionList << new QAction(ST(CP_GAUSSIAN), this);
actionList << new QAction(ST(CP_MEAN), this);
actionList << new QAction(ST(CP_RMS), this);
actionList << new QAction(ST(CP_ABSOLUTE), this);
@ -102,14 +110,16 @@ ExtraMeshColorizePlugin::ExtraMeshColorizePlugin() {
const QString ExtraMeshColorizePlugin::ST(ColorizeType c) {
switch(c)
{
case CP_EQUALIZE:
return QString("Colorize by Quality");
case CP_GAUSSIAN:
return QString("Gaussian Curvature");
return QString("Gaussian Curvature (equalized)");
case CP_MEAN:
return QString("Mean Curvature");
return QString("Mean Curvature (equalized)");
case CP_RMS:
return QString("Root mean square Curvature");
return QString("Root mean square Curvature (equalized)");
case CP_ABSOLUTE:
return QString("Absolute Curvature");
return QString("Absolute Curvature (equalized)");
case CP_SELFINTERSECT:
return QString("Self Intersections");
case CP_BORDER:
@ -126,24 +136,29 @@ const ActionInfo &ExtraMeshColorizePlugin::Info(QAction *action)
{
static ActionInfo ai;
if( action->text() == ST(CP_GAUSSIAN) )
if( action->text() == ST(CP_EQUALIZE) )
{
ai.Help = tr("Colorize vertex and faces depending on gaussian curvature.");
ai.Help = tr("Colorize vertex and faces depending on quality field (manually equalized).");
ai.ShortHelp = tr("Colorize by quality");
}
if( action->text() == ST(CP_GAUSSIAN) )
{
ai.Help = tr("Colorize vertex and faces depending on equalized gaussian curvature.");
ai.ShortHelp = tr("Colorize by gaussian curvature");
}
if( action->text() == ST(CP_MEAN) )
{
ai.Help = tr("Colorize vertex and faces depending on mean curvature.");
ai.Help = tr("Colorize vertex and faces depending on equalized mean curvature.");
ai.ShortHelp = tr("Colorize by mean curvature");
}
if( action->text() == ST(CP_RMS) )
{
ai.Help = tr("Colorize vertex and faces depending on root mean square curvature.");
ai.Help = tr("Colorize vertex and faces depending on equalized root mean square curvature.");
ai.ShortHelp = tr("Colorize by root mean square curvature");
}
if( action->text() == ST(CP_ABSOLUTE) )
{
ai.Help = tr("Colorize vertex and faces depending on absolute curvature.");
ai.Help = tr("Colorize vertex and faces depending on equalize absolute curvature.");
ai.ShortHelp = tr("Colorize by absolute curvature");
}
if( action->text() == ST(CP_SELFINTERSECT) )
@ -163,7 +178,6 @@ const ActionInfo &ExtraMeshColorizePlugin::Info(QAction *action)
ai.Help = tr("Colorize only non manifold edges.");
ai.ShortHelp = tr("Colorize only non manifold edges");
}
if( action->text() == ST(CP_RESTORE_ORIGINAL) )
{
ai.Help = tr("Restore original per vertex color.");
@ -184,34 +198,62 @@ QList<QAction *> ExtraMeshColorizePlugin::actions() const {
return actionList;
}
void ExtraMeshColorizePlugin::Compute(QAction * mode, MeshModel &m, RenderMode &rm, GLArea *parent){
if(mode->text() == ST(CP_GAUSSIAN))
if(mode->text() == ST(CP_EQUALIZE))
{
ColorGaussian<CMeshO>(m.cm, log);
vcg::tri::UpdateColor<CMeshO>::VertexQuality(m.cm);
rm.colorMode = GLW::CMPerVert;
Curvature<CMeshO> c(m.cm);
Frange mmmq = c.minMaxQ();
eqSettings.meshMinQ = mmmq.min;
eqSettings.meshMaxQ = mmmq.max;
Frange hmmq=c.histoPercentile(mmmq, 1.0f / (float) eqSettings.percentile, eqSettings.range);
eqSettings.histoMinQ = hmmq.min;
eqSettings.histoMaxQ = hmmq.max;
EqualizerDialog eqdialog(parent);
eqdialog.setValues(eqSettings);
if (eqdialog.exec()!=QDialog::Accepted)
return;
eqSettings=eqdialog.getValues();
c.ColorizeByEqualizedQuality(c.histoPercentile(mmmq, 1.0f / (float) eqSettings.percentile, eqSettings.range));
rm.colorMode = GLW::CMPerVert;
return;
}
if(mode->text() == ST(CP_GAUSSIAN))
{
Curvature<CMeshO> c(m.cm);
c.MapGaussianCurvatureIntoQuality();
c.ColorizeByEqualizedQuality(c.histoPercentile(c.minMaxQ(), 1.0f / (float) eqSettings.percentile, eqSettings.range));
rm.colorMode = GLW::CMPerVert;
return;
}
if(mode->text() == ST(CP_MEAN))
{
ColorMean<CMeshO>(m.cm, log);
vcg::tri::UpdateColor<CMeshO>::VertexQuality(m.cm);
Curvature<CMeshO> c(m.cm);
c.MapMeanCurvatureIntoQuality();
c.ColorizeByEqualizedQuality(c.histoPercentile(c.minMaxQ(), 1.0f / (float) eqSettings.percentile, eqSettings.range));
rm.colorMode = GLW::CMPerVert;
return;
}
if(mode->text() == ST(CP_RMS))
{
ColorRMS<CMeshO>(m.cm, log);
vcg::tri::UpdateColor<CMeshO>::VertexQuality(m.cm);
Curvature<CMeshO> c(m.cm);
c.MapRMSCurvatureIntoQuality();
c.ColorizeByEqualizedQuality(c.histoPercentile(c.minMaxQ(), 1.0f / (float) eqSettings.percentile, eqSettings.range));
rm.colorMode = GLW::CMPerVert;
return;
}
if(mode->text() == ST(CP_ABSOLUTE))
{
ColorAbsolute<CMeshO>(m.cm, log);
vcg::tri::UpdateColor<CMeshO>::VertexQuality(m.cm);
Curvature<CMeshO> c(m.cm);
c.MapAbsoluteCurvatureIntoQuality();
c.ColorizeByEqualizedQuality(c.histoPercentile(c.minMaxQ(), 1.0f / (float) eqSettings.percentile, eqSettings.range));
rm.colorMode = GLW::CMPerVert;
return;
}

View File

@ -23,6 +23,13 @@
/****************************************************************************
History
$Log$
Revision 1.16 2006/01/27 18:27:53 vannini
code refactoring for curvature colorize
added colorize equalizer dialog and
"Colorize by Quality" filter
some small bugfixes
removed color_curvature.h in favour of curvature.h
Revision 1.15 2006/01/20 18:17:07 vannini
added Restore Color
@ -55,6 +62,7 @@ Moved gaussian and mean curvature functions into color_curvature.h
#include <vcg/math/histogram.h>
#include <vcg/space/triangle3.h>
#include <vcg/complex/trimesh/update/color.h>
#include "equalizerdialog.h"
class ExtraMeshColorizePlugin : public QObject, public MeshColorizeInterface
{
@ -63,7 +71,7 @@ class ExtraMeshColorizePlugin : public QObject, public MeshColorizeInterface
public:
enum ColorizeType {CP_GAUSSIAN,CP_MEAN,CP_RMS,CP_ABSOLUTE,CP_SELFINTERSECT,CP_BORDER,CP_COLORNM,CP_RESTORE_ORIGINAL};
enum ColorizeType {CP_EQUALIZE,CP_GAUSSIAN,CP_MEAN,CP_RMS,CP_ABSOLUTE,CP_SELFINTERSECT,CP_BORDER,CP_COLORNM,CP_RESTORE_ORIGINAL};
const QString ST(ColorizeType c);
ExtraMeshColorizePlugin();
@ -78,6 +86,7 @@ public:
protected:
GLLogStream *log;
QList <QAction *> actionList;
EqualizerSettings eqSettings;
};

View File

@ -2,13 +2,14 @@ TEMPLATE = lib
CONFIG += plugin
CONFIG += stl
INCLUDEPATH += ../.. ../../../../sf ../../../../code/lib/glew/include
HEADERS = meshcolorize.h
SOURCES = meshcolorize.cpp
HEADERS = meshcolorize.h curvature.h equalizerDialog.h
SOURCES = meshcolorize.cpp equalizerDialog.cpp
TARGET = meshcolorize
DESTDIR = ../../meshlab/plugins
# the following line is needed to avoid mismatch between
# the awful min/max macros of windows and the limits max
win32:DEFINES += NOMINMAX
FORMS = equalizerDialog.ui
unix{
QMAKE_CC = gcc-3.3