hausdorff filter returns values as map of <string, qvariant>

This commit is contained in:
alemuntoni 2020-11-13 18:14:41 +01:00
parent 633b5fe5b9
commit 0176d52f89

View File

@ -698,10 +698,16 @@ void FilterDocSampling::initParameterList(const QAction *action, MeshDocument &
}
}
bool FilterDocSampling::applyFilter(const QAction *action, MeshDocument &md, std::map<std::string, QVariant>&, unsigned int& /*postConditionMask*/, const RichParameterList & par, vcg::CallBackPos *cb)
{
switch(ID(action))
bool FilterDocSampling::applyFilter(
const QAction *action,
MeshDocument &md, std::map<std::string,
QVariant>& outputValues,
unsigned int& /*postConditionMask*/,
const RichParameterList & par,
vcg::CallBackPos *cb)
{
switch(ID(action))
{
case FP_ELEMENT_SUBSAMPLING :
{
MeshModel *curMM = md.mm();
@ -715,22 +721,22 @@ switch(ID(action))
errorMessage = "Mesh Element Sampling: cannot sample on faces/edges, mesh has no faces";
return false; // can't continue, mesh can't be processed
}
MeshModel *mm= md.addNewMesh("", "Element samples", true); // The new mesh is the current one
mm->updateDataMask(curMM);
BaseSampler mps(&(mm->cm));
switch(par.getEnum("Sampling"))
{
case 0 : tri::SurfaceSampling<CMeshO,BaseSampler>::VertexUniform(curMM->cm,mps,par.getInt("SampleNum")); break;
case 1 : tri::SurfaceSampling<CMeshO,BaseSampler>::EdgeUniform(curMM->cm,mps,par.getInt("SampleNum"),true); break;
case 2 : tri::SurfaceSampling<CMeshO,BaseSampler>::AllFace(curMM->cm,mps); break;
case 0 : tri::SurfaceSampling<CMeshO,BaseSampler>::VertexUniform(curMM->cm,mps,par.getInt("SampleNum")); break;
case 1 : tri::SurfaceSampling<CMeshO,BaseSampler>::EdgeUniform(curMM->cm,mps,par.getInt("SampleNum"),true); break;
case 2 : tri::SurfaceSampling<CMeshO,BaseSampler>::AllFace(curMM->cm,mps); break;
}
vcg::tri::UpdateBounding<CMeshO>::Box(mm->cm);
log("Mesh Element Sampling created a new mesh of %i points",mm->cm.vn);
} break;
case FP_TEXEL_SAMPLING :
{
MeshModel *curMM= md.mm();
@ -739,13 +745,13 @@ switch(ID(action))
errorMessage = "Texel Sampling requires a mesh with Per Wedge UV parametrization";
return false; // can't continue, mesh can't be processed
}
MeshModel *mm= md.addNewMesh("", "Texel samples", true); // The new mesh is the current one
bool RecoverColor = par.getBool("RecoverColor");
BaseSampler mps(&(mm->cm));
mps.texSamplingWidth=par.getInt("TextureW");
mps.texSamplingHeight=par.getInt("TextureH");
if(RecoverColor && curMM->cm.textures.size()>0)
{
mps.tex= new QImage(curMM->cm.textures[0].c_str());
@ -759,7 +765,7 @@ switch(ID(action))
mm->updateDataMask(MeshModel::MM_VERTNORMAL | MeshModel::MM_VERTCOLOR);
log("Texel Sampling created a new mesh of %i points", mm->cm.vn);
} break;
case FP_MONTECARLO_SAMPLING :
{
MeshModel *curMM = md.mm();
@ -778,13 +784,13 @@ switch(ID(action))
errorMessage = "Cannot do weighted samplimg, layer has no Vertex Quality value";
return false; // can't continue, mesh can't be processed
}
MeshModel *mm= md.addNewMesh("","Montecarlo Samples", true); // The new mesh is the current one
mm->updateDataMask(curMM);
BaseSampler mps(&(mm->cm));
mps.perFaceNormal = par.getBool("PerFaceNormal");
mps.perFaceNormal = par.getBool("PerFaceNormal");
if(par.getBool("EdgeSampling"))
{
tri::SurfaceSampling<CMeshO,BaseSampler>::EdgeMontecarlo(curMM->cm,mps,par.getInt("SampleNum"),false);
@ -798,11 +804,11 @@ switch(ID(action))
else
tri::SurfaceSampling<CMeshO,BaseSampler>::MontecarloPoisson(curMM->cm,mps,par.getInt("SampleNum"));
}
vcg::tri::UpdateBounding<CMeshO>::Box(mm->cm);
log("Sampling created a new mesh of %i points", mm->cm.vn);
} break;
case FP_STRATIFIED_SAMPLING :
{
MeshModel *curMM = md.mm();
@ -816,44 +822,44 @@ switch(ID(action))
errorMessage = "Number of Samples is 0, cannot do anything";
return false; // can't continue, mesh can't be processed
}
MeshModel *mm= md.addNewMesh("","Subdiv Samples", true); // The new mesh is the current one
mm->updateDataMask(curMM);
int samplingMethod = par.getEnum("Sampling");
BaseSampler mps(&(mm->cm));
switch(samplingMethod)
{
case 0:
tri::SurfaceSampling<CMeshO,BaseSampler>::FaceSimilar(curMM->cm,mps,par.getInt("SampleNum"), false ,par.getBool("Random"));
log("Similar Sampling created a new mesh of %i points", mm->cm.vn);
break;
case 1:
tri::SurfaceSampling<CMeshO,BaseSampler>::FaceSimilar(curMM->cm,mps,par.getInt("SampleNum"), true ,par.getBool("Random"));
log("Dual Similar Sampling created a new mesh of %i points", mm->cm.vn);
break;
case 2:
tri::SurfaceSampling<CMeshO,BaseSampler>::FaceSubdivision(curMM->cm,mps,par.getInt("SampleNum"), par.getBool("Random"));
log("Subdivision Sampling created a new mesh of %i points", mm->cm.vn);
break;
case 3:
tri::SurfaceSampling<CMeshO,BaseSampler>::EdgeUniform(curMM->cm,mps,par.getInt("SampleNum"), true);
log("Edge Sampling created a new mesh of %i points", mm->cm.vn);
break;
case 4:
tri::SurfaceSampling<CMeshO,BaseSampler>::EdgeUniform(curMM->cm,mps,par.getInt("SampleNum"), false);
log("Non Faux Edge Sampling created a new mesh of %i points", mm->cm.vn);
break;
case 0:
tri::SurfaceSampling<CMeshO,BaseSampler>::FaceSimilar(curMM->cm,mps,par.getInt("SampleNum"), false ,par.getBool("Random"));
log("Similar Sampling created a new mesh of %i points", mm->cm.vn);
break;
case 1:
tri::SurfaceSampling<CMeshO,BaseSampler>::FaceSimilar(curMM->cm,mps,par.getInt("SampleNum"), true ,par.getBool("Random"));
log("Dual Similar Sampling created a new mesh of %i points", mm->cm.vn);
break;
case 2:
tri::SurfaceSampling<CMeshO,BaseSampler>::FaceSubdivision(curMM->cm,mps,par.getInt("SampleNum"), par.getBool("Random"));
log("Subdivision Sampling created a new mesh of %i points", mm->cm.vn);
break;
case 3:
tri::SurfaceSampling<CMeshO,BaseSampler>::EdgeUniform(curMM->cm,mps,par.getInt("SampleNum"), true);
log("Edge Sampling created a new mesh of %i points", mm->cm.vn);
break;
case 4:
tri::SurfaceSampling<CMeshO,BaseSampler>::EdgeUniform(curMM->cm,mps,par.getInt("SampleNum"), false);
log("Non Faux Edge Sampling created a new mesh of %i points", mm->cm.vn);
break;
}
vcg::tri::UpdateBounding<CMeshO>::Box(mm->cm);
} break;
case FP_CLUSTERED_SAMPLING :
{
MeshModel *curMM= md.mm();
int samplingMethod = par.getEnum("Sampling");
float threshold = par.getAbsPerc("Threshold");
bool selected = par.getBool("Selected");
if (selected && curMM->cm.svn == 0 && curMM->cm.sfn == 0) // if no selection at all, fail
{
log("Clustered Sampling: Cannot apply only on selection: there is no selection");
@ -866,48 +872,48 @@ switch(ID(action))
tri::UpdateSelection<CMeshO>::VertexFromFaceStrict(curMM->cm);
}
log("Using only %i selected vertices", curMM->cm.svn);
MeshModel *mm= md.addNewMesh("", "Cluster samples", true); // The new mesh is the current one
switch(samplingMethod)
{
case 0 :
{
tri::Clustering<CMeshO, vcg::tri::AverageColorCell<CMeshO> > ClusteringGrid;
ClusteringGrid.Init(curMM->cm.bbox,100000,threshold);
ClusteringGrid.AddPointSet(curMM->cm,selected);
ClusteringGrid.ExtractPointSet(mm->cm);
ClusteringGrid.SelectPointSet(curMM->cm);
tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(curMM->cm);
log("Similar Sampling created a new mesh of %i points", mm->cm.vn);
} break;
case 1 :
{
vcg::tri::Clustering<CMeshO, vcg::tri::NearestToCenter<CMeshO> > ClusteringGrid;
ClusteringGrid.Init(curMM->cm.bbox,100000,threshold);
ClusteringGrid.AddPointSet(curMM->cm,selected);
ClusteringGrid.SelectPointSet(curMM->cm);
tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(curMM->cm);
ClusteringGrid.ExtractPointSet(mm->cm);
log("Similar Sampling created a new mesh of %i points", mm->cm.vn);
} break;
switch(samplingMethod)
{
case 0 :
{
tri::Clustering<CMeshO, vcg::tri::AverageColorCell<CMeshO> > ClusteringGrid;
ClusteringGrid.Init(curMM->cm.bbox,100000,threshold);
ClusteringGrid.AddPointSet(curMM->cm,selected);
ClusteringGrid.ExtractPointSet(mm->cm);
ClusteringGrid.SelectPointSet(curMM->cm);
tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(curMM->cm);
log("Similar Sampling created a new mesh of %i points", mm->cm.vn);
} break;
case 1 :
{
vcg::tri::Clustering<CMeshO, vcg::tri::NearestToCenter<CMeshO> > ClusteringGrid;
ClusteringGrid.Init(curMM->cm.bbox,100000,threshold);
ClusteringGrid.AddPointSet(curMM->cm,selected);
ClusteringGrid.SelectPointSet(curMM->cm);
tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(curMM->cm);
ClusteringGrid.ExtractPointSet(mm->cm);
log("Similar Sampling created a new mesh of %i points", mm->cm.vn);
} break;
}
vcg::tri::UpdateBounding<CMeshO>::Box(mm->cm);
} break;
case FP_POINTCLOUD_SIMPLIFICATION :
{
MeshModel *curMM= md.mm();
CMeshO::ScalarType radius = par.getAbsPerc("Radius");
int sampleNum = par.getInt("SampleNum");
if ((radius == 0.0) && (sampleNum == 0)){
log("Point Cloud Simplification: Number of Samples AND Radius are both 0, cannot do anything");
errorMessage = "Number of Samples AND Radius are both 0, cannot do anything";
return false; // can't continue, mesh can't be processed
}
MeshModel *mm= md.addNewMesh("", "Simplified cloud", true); // The new mesh is the current one
mm->updateDataMask(curMM);
BaseSampler mps(&(mm->cm));
@ -917,16 +923,16 @@ switch(ID(action))
radius = tri::SurfaceSampling<CMeshO,BaseSampler>::ComputePoissonDiskRadius(curMM->cm,sampleNum);
else
sampleNum = tri::SurfaceSampling<CMeshO,BaseSampler>::ComputePoissonSampleNum(curMM->cm,radius);
if(par.getBool("ExactNumFlag") && radius==0)
tri::SurfaceSampling<CMeshO,BaseSampler>::PoissonDiskPruningByNumber(mps, curMM->cm, sampleNum, radius,pp,0.005);
else
tri::SurfaceSampling<CMeshO,BaseSampler>::PoissonDiskPruning(mps, curMM->cm, radius,pp);
log("Point Cloud Simplification created a new mesh of %i points", mm->cm.vn);
UpdateBounding<CMeshO>::Box(mm->cm);
} break;
case FP_POISSONDISK_SAMPLING :
{
MeshModel *curMM= md.mm();
@ -935,18 +941,18 @@ switch(ID(action))
tri::SurfaceSampling<CMeshO, BaseSampler>::PoissonDiskParam pp;
pp.radiusVariance = par.getFloat("RadiusVariance");
bool subsampleFlag = par.getBool("Subsample");
if ((radius == 0.0) && (sampleNum == 0)){
log("Poisson disk Sampling: Number of Samples AND Radius are both 0, cannot do anything");
errorMessage = "Number of Samples AND Radius are both 0, cannot do anything";
return false; // can't continue, mesh can't be processed
}
if (radius == 0)
radius = tri::SurfaceSampling<CMeshO, BaseSampler>::ComputePoissonDiskRadius(curMM->cm, sampleNum);
else
sampleNum = tri::SurfaceSampling<CMeshO, BaseSampler>::ComputePoissonSampleNum(curMM->cm, radius);
if (pp.radiusVariance != 1.0)
{
if (!curMM->hasDataMask(MeshModel::MM_VERTQUALITY)) {
@ -957,22 +963,22 @@ switch(ID(action))
pp.adaptiveRadiusFlag = true;
log("Variable Density variance is %f, radius can vary from %f to %f", pp.radiusVariance, radius / pp.radiusVariance, radius*pp.radiusVariance);
}
if (curMM->cm.fn == 0 && subsampleFlag == false)
{
log("Poisson disk Sampling: Current mesh has no triangles. We cannot create a montecarlo sampling of the surface. Please select the Subsample flag");
errorMessage = "Current mesh has no triangles. We cannot create a montecarlo sampling of the surface.<br> Please select the Subsample flag";
return false; // cannot continue
}
MeshModel *mm= md.addNewMesh("","Poisson-disk Samples", true); // The new mesh is the current one
mm->updateDataMask(curMM);
log("Computing %i Poisson Samples for an expected radius of %f",sampleNum,radius);
// first of all generate montecarlo samples for fast lookup
CMeshO *presampledMesh=0;
CMeshO MontecarloMesh; // this mesh is used only if we need real poisson sampling (and therefore we need to choose points different from the starting mesh vertices)
if(subsampleFlag)
presampledMesh = &(curMM->cm);
@ -986,7 +992,7 @@ switch(ID(action))
}
else
presampledMesh=&MontecarloMesh;
QElapsedTimer tt;tt.start();
BaseSampler sampler(presampledMesh);
sampler.qualitySampling=true;
@ -997,7 +1003,7 @@ switch(ID(action))
presampledMesh->bbox = curMM->cm.bbox; // we want the same bounding box
log("Generated %i Montecarlo Samples (%i msec)",presampledMesh->vn,tt.elapsed());
}
BaseSampler mps(&(mm->cm));
if(par.getBool("RefineFlag"))
{
@ -1011,14 +1017,14 @@ switch(ID(action))
tri::SurfaceSampling<CMeshO,BaseSampler>::PoissonDiskPruningByNumber(mps, *presampledMesh, sampleNum, radius,pp,0.005);
else
tri::SurfaceSampling<CMeshO,BaseSampler>::PoissonDiskPruning(mps, *presampledMesh, radius,pp);
//tri::SurfaceSampling<CMeshO,BaseSampler>::PoissonDisk(curMM->cm, mps, *presampledMesh, radius,pp);
vcg::tri::UpdateBounding<CMeshO>::Box(mm->cm);
Point3i &g=pp.pds.gridSize;
log("Grid size was %i %i %i (%i allocated on %i)",g[0],g[1],g[2], pp.pds.gridCellNum, g[0]*g[1]*g[2]);
log("Poisson Disk Sampling created a new mesh of %i points", mm->cm.vn);
} break;
case FP_HAUSDORFF_DISTANCE :
{
MeshModel* mm0 = par.getMesh("SampledMesh"); // surface where we choose the random samples
@ -1029,13 +1035,13 @@ switch(ID(action))
bool sampleFauxEdge=par.getBool("SampleFauxEdge");
bool sampleFace=par.getBool("SampleFace");
float distUpperBound = par.getAbsPerc("MaxDist");
if (mm0 == mm1){
log("Hausdorff Distance: cannot compute, it is the same mesh");
errorMessage = "Cannot compute, it is the same mesh";
return false; // can't continue, mesh can't be processed
}
if(sampleEdge && mm0->cm.fn==0) {
log("Disabled edge sampling. Meaningless when sampling point clouds");
sampleEdge=false;
@ -1044,86 +1050,94 @@ switch(ID(action))
log("Disabled face sampling. Meaningless when sampling point clouds");
sampleFace=false;
}
// the meshes have to be transformed
if (mm0->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(mm0->cm, mm0->cm.Tr, true);
if (mm1->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(mm1->cm, mm1->cm.Tr, true);
mm0->updateDataMask(MeshModel::MM_VERTQUALITY);
mm1->updateDataMask(MeshModel::MM_VERTQUALITY);
mm1->updateDataMask(MeshModel::MM_FACEMARK);
tri::UpdateNormal<CMeshO>::PerFaceNormalized(mm1->cm);
MeshModel *samplePtMesh =0;
MeshModel *closestPtMesh =0;
HausdorffSampler<CMeshO> hs(&(mm1->cm));
if(saveSampleFlag)
{
closestPtMesh=md.addNewMesh("","Hausdorff Closest Points", false); // the new mesh is NOT the current one (byproduct of measurement)
closestPtMesh->updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY);
samplePtMesh = md.addNewMesh("", "Hausdorff Sample Point", false); // the new mesh is NOT the current one (byproduct of measurement)
samplePtMesh->updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY);
hs.init(&(samplePtMesh->cm),&(closestPtMesh->cm));
closestPtMesh=md.addNewMesh("","Hausdorff Closest Points", false); // the new mesh is NOT the current one (byproduct of measurement)
closestPtMesh->updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY);
samplePtMesh = md.addNewMesh("", "Hausdorff Sample Point", false); // the new mesh is NOT the current one (byproduct of measurement)
samplePtMesh->updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY);
hs.init(&(samplePtMesh->cm),&(closestPtMesh->cm));
}
hs.dist_upper_bound = distUpperBound;
qDebug("Sampled mesh has %7i vert %7i face",mm0->cm.vn,mm0->cm.fn);
qDebug("Searched mesh has %7i vert %7i face",mm1->cm.vn,mm1->cm.fn);
qDebug("Max sampling distance %f on a bbox diag of %f",distUpperBound,mm1->cm.bbox.Diag());
if(sampleVert)
tri::SurfaceSampling<CMeshO,HausdorffSampler<CMeshO> >::VertexUniform(mm0->cm,hs,par.getInt("SampleNum"));
tri::SurfaceSampling<CMeshO,HausdorffSampler<CMeshO> >::VertexUniform(mm0->cm,hs,par.getInt("SampleNum"));
if(sampleEdge)
tri::SurfaceSampling<CMeshO,HausdorffSampler<CMeshO> >::EdgeUniform(mm0->cm,hs,par.getInt("SampleNum"),sampleFauxEdge);
tri::SurfaceSampling<CMeshO,HausdorffSampler<CMeshO> >::EdgeUniform(mm0->cm,hs,par.getInt("SampleNum"),sampleFauxEdge);
if(sampleFace)
tri::SurfaceSampling<CMeshO,HausdorffSampler<CMeshO> >::Montecarlo(mm0->cm,hs,par.getInt("SampleNum"));
tri::SurfaceSampling<CMeshO,HausdorffSampler<CMeshO> >::Montecarlo(mm0->cm,hs,par.getInt("SampleNum"));
// the meshes have to return to their original position
if (mm0->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(mm0->cm, Inverse(mm0->cm.Tr), true);
if (mm1->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(mm1->cm, Inverse(mm1->cm.Tr), true);
log("Hausdorff Distance computed");
log(" Sampled %i pts (rng: 0) on %s searched closest on %s",hs.n_total_samples,qUtf8Printable(mm0->label()),qUtf8Printable(mm1->label()));
log(" min : %f max %f mean : %f RMS : %f",hs.getMinDist(),hs.getMaxDist(),hs.getMeanDist(),hs.getRMSDist());
float d = mm0->cm.bbox.Diag();
log("Values w.r.t. BBox Diag (%f)",d);
log(" min : %f max %f mean : %f RMS : %f\n",hs.getMinDist()/d,hs.getMaxDist()/d,hs.getMeanDist()/d,hs.getRMSDist()/d);
outputValues.clear();
outputValues["n_samples"] = QVariant(hs.n_total_samples);
outputValues["min"] = QVariant(hs.getMinDist());
outputValues["max"] = QVariant(hs.getMaxDist());
outputValues["mean"] = QVariant(hs.getMeanDist());
outputValues["RMS"] = QVariant(hs.getRMSDist());
outputValues["diag_mesh_0"] = QVariant(d);
outputValues["diag_mesh_1"] = QVariant(mm1->cm.bbox.Diag());
if(saveSampleFlag)
{
tri::UpdateBounding<CMeshO>::Box(samplePtMesh->cm);
tri::UpdateBounding<CMeshO>::Box(closestPtMesh->cm);
tri::UpdateColor<CMeshO>::PerVertexQualityRamp(samplePtMesh->cm);
tri::UpdateColor<CMeshO>::PerVertexQualityRamp(closestPtMesh->cm);
tri::UpdateBounding<CMeshO>::Box(samplePtMesh->cm);
tri::UpdateBounding<CMeshO>::Box(closestPtMesh->cm);
tri::UpdateColor<CMeshO>::PerVertexQualityRamp(samplePtMesh->cm);
tri::UpdateColor<CMeshO>::PerVertexQualityRamp(closestPtMesh->cm);
}
} break;
case FP_DISTANCE_REFERENCE:
{
MeshModel* mm0 = par.getMesh("MeasureMesh"); // this mesh gets measured.
MeshModel* mm1 = par.getMesh("RefMesh"); // this is the reference mesh
bool useSigned = par.getBool("SignedDist");
float maxDistABS = par.getAbsPerc("MaxDist");
if (mm0 == mm1){
log("Distance from Reference: cannot compute, it is the same mesh");
errorMessage = "Cannot compute, it is the same mesh";
return false; // can't continue, mesh can't be processed
}
// the meshes have to return to their original position
if (mm0->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(mm0->cm, mm0->cm.Tr, true);
if (mm1->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(mm1->cm, mm1->cm.Tr, true);
// add quality to vertex of measured mesh
mm0->updateDataMask(MeshModel::MM_VERTQUALITY);
// if reference has faces, recompute and normalize normals
@ -1132,24 +1146,24 @@ switch(ID(action))
tri::UpdateNormal<CMeshO>::PerFaceNormalized(mm1->cm);
tri::UpdateNormal<CMeshO>::PerVertexNormalized(mm1->cm);
}
mm1->updateDataMask(MeshModel::MM_FACEMARK);
mm1->updateDataMask(MeshModel::MM_FACEMARK);
SimpleDistanceSampler ds(&(mm1->cm), useSigned, maxDistABS);
tri::SurfaceSampling<CMeshO, SimpleDistanceSampler>::AllVertex(mm0->cm, ds);
// the meshes have to return to their original position
if (mm0->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(mm0->cm, Inverse(mm0->cm.Tr), true);
if (mm1->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(mm1->cm, Inverse(mm1->cm.Tr), true);
log("Distance from Reference Mesh computed");
log(" Sampled %i vertices on %s searched closest on %s", mm0->cm.vn, qUtf8Printable(mm0->label()), qUtf8Printable(mm1->label()));
log(" min : %f max %f mean : %f RMS : %f", ds.getMaxDist(), ds.getMaxDist(), ds.getMeanDist(), ds.getRMSDist());
} break;
case FP_VERTEX_RESAMPLING :
{
MeshModel* srcMesh = par.getMesh("SourceMesh"); // mesh whose attribute are read
@ -1162,7 +1176,7 @@ switch(ID(action))
bool qualityT = par.getBool("QualityTransfer");
bool selectionT = par.getBool("SelectionTransfer");
bool distquality = par.getBool("QualityDistance");
if (srcMesh == trgMesh){
log("Vertex Attribute Transfer: cannot compute, it is the same mesh");
errorMessage = "Cannot compute, it is the same mesh";
@ -1174,7 +1188,7 @@ switch(ID(action))
errorMessage = QString("You have to choose at least one attribute to be sampled");
return false;
}
if (onlySelected && trgMesh->cm.svn == 0 && trgMesh->cm.sfn == 0) // if no selection at all, fail
{
log("Vertex Attribute Transfer: Cannot apply only on selection: there is no selection");
@ -1186,19 +1200,19 @@ switch(ID(action))
tri::UpdateSelection<CMeshO>::VertexClear(trgMesh->cm);
tri::UpdateSelection<CMeshO>::VertexFromFaceLoose(trgMesh->cm);
}
// the meshes have to be transformed
if (srcMesh->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(srcMesh->cm, srcMesh->cm.Tr, true);
if (trgMesh->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(trgMesh->cm, trgMesh->cm.Tr, true);
srcMesh->updateDataMask(MeshModel::MM_FACEMARK);
tri::UpdateNormal<CMeshO>::PerFaceNormalized(srcMesh->cm);
LocalRedetailSampler rs;
rs.init(&(srcMesh->cm),cb,trgMesh->cm.vn);
rs.dist_upper_bound = upperbound;
rs.colorFlag = colorT;
rs.coordFlag = geomT;
@ -1206,25 +1220,25 @@ switch(ID(action))
rs.qualityFlag = qualityT;
rs.selectionFlag = selectionT;
rs.storeDistanceAsQualityFlag = distquality;
if(rs.colorFlag) trgMesh->updateDataMask(MeshModel::MM_VERTCOLOR);
if(rs.qualityFlag) trgMesh->updateDataMask(MeshModel::MM_VERTQUALITY);
qDebug("Source mesh has %7i vert %7i face",srcMesh->cm.vn,srcMesh->cm.fn);
qDebug("Target mesh has %7i vert %7i face",trgMesh->cm.vn,trgMesh->cm.fn);
tri::SurfaceSampling<CMeshO, LocalRedetailSampler>::VertexUniform(trgMesh->cm, rs, trgMesh->cm.vn, onlySelected);
if(rs.coordFlag) tri::UpdateNormal<CMeshO>::PerFaceNormalized(trgMesh->cm);
// the meshes have to return to their original position
if (srcMesh->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(srcMesh->cm, Inverse(srcMesh->cm.Tr), true);
if (trgMesh->cm.Tr != Matrix44m::Identity())
tri::UpdatePosition<CMeshO>::Matrix(trgMesh->cm, Inverse(trgMesh->cm.Tr), true);
} break;
case FP_UNIFORM_MESH_RESAMPLING :
{
if (md.mm()->cm.fn==0) {
@ -1232,27 +1246,27 @@ switch(ID(action))
errorMessage = "Uniform Mesh Resampling requires a mesh with faces,<br> it does not work on Point Clouds";
return false; // can't continue, mesh can't be processed
}
CMeshO::ScalarType voxelSize = par.getAbsPerc("CellSize");
float offsetThr = par.getAbsPerc("Offset");
bool discretizeFlag = par.getBool("discretize");
bool multiSampleFlag = par.getBool("multisample");
bool absDistFlag = par.getBool("absDist");
bool mergeCloseVert = par.getBool("mergeCloseVert");
MeshModel *baseMesh= md.mm();
MeshModel *offsetMesh = md.addNewMesh("", "Offset mesh", true); // the new mesh is the current one
baseMesh->updateDataMask(MeshModel::MM_FACEMARK);
Point3i volumeDim;
Box3m volumeBox = baseMesh->cm.bbox;
volumeBox.Offset(volumeBox.Diag()/10.0f+abs(offsetThr));
BestDim(volumeBox , voxelSize, volumeDim );
log("Resampling mesh using a volume of %i x %i x %i",volumeDim[0],volumeDim[1],volumeDim[2]);
log(" VoxelSize is %f, offset is %f ", voxelSize,offsetThr);
log(" Mesh Box is %f %f %f",baseMesh->cm.bbox.DimX(),baseMesh->cm.bbox.DimY(),baseMesh->cm.bbox.DimZ() );
tri::Resampler<CMeshO,CMeshO>::Resample(baseMesh->cm, offsetMesh->cm, volumeBox, volumeDim, voxelSize*3.5, offsetThr,discretizeFlag,multiSampleFlag,absDistFlag, cb);
tri::UpdateBounding<CMeshO>::Box(offsetMesh->cm);
if(mergeCloseVert)
@ -1263,13 +1277,13 @@ switch(ID(action))
}
tri::UpdateNormal<CMeshO>::PerVertexPerFace(offsetMesh->cm);
} break;
case FP_VORONOI_COLORING :
{
MeshModel* mmM = par.getMesh("ColoredMesh"); // surface where we choose the random samples
MeshModel* mmV = par.getMesh("VertexMesh"); // surface that is sought for the closest point to each sample.
bool backwardFlag = par.getBool("backward");
tri::Clean<CMeshO>::RemoveUnreferencedVertex(mmM->cm);
tri::Allocator<CMeshO>::CompactVertexVector(mmM->cm);
tri::Allocator<CMeshO>::CompactFaceVector(mmM->cm);
@ -1278,17 +1292,17 @@ switch(ID(action))
// Fills the point vector with the position of the Point cloud
for(CMeshO::VertexIterator vi= mmV->cm.vert.begin(); vi!= mmV->cm.vert.end(); ++vi) if(!(*vi).IsD())
vecP.push_back((*vi).cP());
vector<CMeshO::VertexPointer> vecV; // points to vertices of ColoredMesh;
tri::VoronoiProcessing<CMeshO>::SeedToVertexConversion (mmM->cm, vecP, vecV);
log("Converted %ui points into %ui vertex ",vecP.size(),vecV.size());
tri::EuclideanDistance<CMeshO> edFunc;
tri::VoronoiProcessing<CMeshO>::ComputePerVertexSources(mmM->cm,vecV,edFunc);
for(uint i=0;i<vecV.size();++i) vecV[i]->C()=Color4b::Red;
tri::VoronoiProcessing<CMeshO>::VoronoiColoring(mmM->cm,backwardFlag);
} break;
case FP_DISK_COLORING :
{
MeshModel* mmM = par.getMesh("ColoredMesh");
@ -1304,31 +1318,31 @@ switch(ID(action))
sht.Set(mmM->cm.vert.begin(),mmM->cm.vert.end());
std::vector<CMeshO::VertexType*> closests;
float radius = par.getDynamicFloat("Radius");
for(CMeshO::VertexIterator viv = mmV->cm.vert.begin(); viv!= mmV->cm.vert.end(); ++viv) if(!(*viv).IsD())
{
Point3m p = viv->cP();
if(sampleRadiusFlag) radius = viv->Q();
Box3m bb(p-Point3m(radius,radius,radius),p+Point3m(radius,radius,radius));
GridGetInBox(sht, markerFunctor, bb, closests);
for(size_t i=0; i<closests.size(); ++i)
{
float dist;
if(approximateGeodeticFlag)
dist = ApproximateGeodesicDistance(viv->cP(),viv->cN(),closests[i]->cP(),closests[i]->cN());
else
dist = Distance(p,closests[i]->cP());
if(dist < radius && closests[i]->Q() > dist)
Point3m p = viv->cP();
if(sampleRadiusFlag) radius = viv->Q();
Box3m bb(p-Point3m(radius,radius,radius),p+Point3m(radius,radius,radius));
GridGetInBox(sht, markerFunctor, bb, closests);
for(size_t i=0; i<closests.size(); ++i)
{
closests[i]->Q() = dist;
closests[i]->C().lerp(Color4b::White,Color4b::Red,dist/radius);
float dist;
if(approximateGeodeticFlag)
dist = ApproximateGeodesicDistance(viv->cP(),viv->cN(),closests[i]->cP(),closests[i]->cN());
else
dist = Distance(p,closests[i]->cP());
if(dist < radius && closests[i]->Q() > dist)
{
closests[i]->Q() = dist;
closests[i]->C().lerp(Color4b::White,Color4b::Red,dist/radius);
}
}
}
}
} break;
case FP_REGULAR_RECURSIVE_SAMPLING :
{
if (md.mm()->cm.fn==0) {
@ -1338,24 +1352,24 @@ switch(ID(action))
}
float CellSize = par.getAbsPerc("CellSize");
float offset=par.getAbsPerc("Offset");
MeshModel *mmM= md.mm();
MeshModel *mm= md.addNewMesh("","Recursive Samples",true); // the new mesh is the current one
tri::Clean<CMeshO>::RemoveUnreferencedVertex(mmM->cm);
tri::Allocator<CMeshO>::CompactEveryVector(mmM->cm);
tri::UpdateNormal<CMeshO>::PerFaceNormalized(mmM->cm);
std::vector<Point3m> pvec;
tri::SurfaceSampling<CMeshO,LocalRedetailSampler>::RegularRecursiveOffset(mmM->cm,pvec, offset, CellSize);
qDebug("Generated %i points",int(pvec.size()));
tri::BuildMeshFromCoordVector(mm->cm,pvec);
} break;
default : assert(0);
}
return true;
}
return true;
}
FilterPluginInterface::FilterClass FilterDocSampling::getClass(const QAction *action) const