diff --git a/src/meshlabplugins/filter_sampling/filter_sampling.cpp b/src/meshlabplugins/filter_sampling/filter_sampling.cpp index eb1cf6f1e..8f8eb6200 100644 --- a/src/meshlabplugins/filter_sampling/filter_sampling.cpp +++ b/src/meshlabplugins/filter_sampling/filter_sampling.cpp @@ -698,10 +698,16 @@ void FilterDocSampling::initParameterList(const QAction *action, MeshDocument & } } -bool FilterDocSampling::applyFilter(const QAction *action, MeshDocument &md, std::map&, unsigned int& /*postConditionMask*/, const RichParameterList & par, vcg::CallBackPos *cb) -{ -switch(ID(action)) +bool FilterDocSampling::applyFilter( + const QAction *action, + MeshDocument &md, std::map& 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::VertexUniform(curMM->cm,mps,par.getInt("SampleNum")); break; - case 1 : tri::SurfaceSampling::EdgeUniform(curMM->cm,mps,par.getInt("SampleNum"),true); break; - case 2 : tri::SurfaceSampling::AllFace(curMM->cm,mps); break; + case 0 : tri::SurfaceSampling::VertexUniform(curMM->cm,mps,par.getInt("SampleNum")); break; + case 1 : tri::SurfaceSampling::EdgeUniform(curMM->cm,mps,par.getInt("SampleNum"),true); break; + case 2 : tri::SurfaceSampling::AllFace(curMM->cm,mps); break; } vcg::tri::UpdateBounding::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::EdgeMontecarlo(curMM->cm,mps,par.getInt("SampleNum"),false); @@ -798,11 +804,11 @@ switch(ID(action)) else tri::SurfaceSampling::MontecarloPoisson(curMM->cm,mps,par.getInt("SampleNum")); } - + vcg::tri::UpdateBounding::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::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::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::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::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::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::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::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::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::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::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::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::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 > ClusteringGrid; - ClusteringGrid.Init(curMM->cm.bbox,100000,threshold); - ClusteringGrid.AddPointSet(curMM->cm,selected); - ClusteringGrid.ExtractPointSet(mm->cm); - ClusteringGrid.SelectPointSet(curMM->cm); - tri::UpdateSelection::FaceFromVertexLoose(curMM->cm); - log("Similar Sampling created a new mesh of %i points", mm->cm.vn); - } break; - - case 1 : - { - vcg::tri::Clustering > ClusteringGrid; - ClusteringGrid.Init(curMM->cm.bbox,100000,threshold); - ClusteringGrid.AddPointSet(curMM->cm,selected); - ClusteringGrid.SelectPointSet(curMM->cm); - tri::UpdateSelection::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 > ClusteringGrid; + ClusteringGrid.Init(curMM->cm.bbox,100000,threshold); + ClusteringGrid.AddPointSet(curMM->cm,selected); + ClusteringGrid.ExtractPointSet(mm->cm); + ClusteringGrid.SelectPointSet(curMM->cm); + tri::UpdateSelection::FaceFromVertexLoose(curMM->cm); + log("Similar Sampling created a new mesh of %i points", mm->cm.vn); + } break; + + case 1 : + { + vcg::tri::Clustering > ClusteringGrid; + ClusteringGrid.Init(curMM->cm.bbox,100000,threshold); + ClusteringGrid.AddPointSet(curMM->cm,selected); + ClusteringGrid.SelectPointSet(curMM->cm); + tri::UpdateSelection::FaceFromVertexLoose(curMM->cm); + ClusteringGrid.ExtractPointSet(mm->cm); + log("Similar Sampling created a new mesh of %i points", mm->cm.vn); + } break; } vcg::tri::UpdateBounding::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::ComputePoissonDiskRadius(curMM->cm,sampleNum); else sampleNum = tri::SurfaceSampling::ComputePoissonSampleNum(curMM->cm,radius); - + if(par.getBool("ExactNumFlag") && radius==0) tri::SurfaceSampling::PoissonDiskPruningByNumber(mps, curMM->cm, sampleNum, radius,pp,0.005); else tri::SurfaceSampling::PoissonDiskPruning(mps, curMM->cm, radius,pp); - + log("Point Cloud Simplification created a new mesh of %i points", mm->cm.vn); UpdateBounding::Box(mm->cm); } break; - + case FP_POISSONDISK_SAMPLING : { MeshModel *curMM= md.mm(); @@ -935,18 +941,18 @@ switch(ID(action)) tri::SurfaceSampling::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::ComputePoissonDiskRadius(curMM->cm, sampleNum); else sampleNum = tri::SurfaceSampling::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.
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::PoissonDiskPruningByNumber(mps, *presampledMesh, sampleNum, radius,pp,0.005); else tri::SurfaceSampling::PoissonDiskPruning(mps, *presampledMesh, radius,pp); - + //tri::SurfaceSampling::PoissonDisk(curMM->cm, mps, *presampledMesh, radius,pp); vcg::tri::UpdateBounding::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::Matrix(mm0->cm, mm0->cm.Tr, true); if (mm1->cm.Tr != Matrix44m::Identity()) tri::UpdatePosition::Matrix(mm1->cm, mm1->cm.Tr, true); - + mm0->updateDataMask(MeshModel::MM_VERTQUALITY); mm1->updateDataMask(MeshModel::MM_VERTQUALITY); mm1->updateDataMask(MeshModel::MM_FACEMARK); tri::UpdateNormal::PerFaceNormalized(mm1->cm); - + MeshModel *samplePtMesh =0; MeshModel *closestPtMesh =0; HausdorffSampler 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 >::VertexUniform(mm0->cm,hs,par.getInt("SampleNum")); + tri::SurfaceSampling >::VertexUniform(mm0->cm,hs,par.getInt("SampleNum")); if(sampleEdge) - tri::SurfaceSampling >::EdgeUniform(mm0->cm,hs,par.getInt("SampleNum"),sampleFauxEdge); + tri::SurfaceSampling >::EdgeUniform(mm0->cm,hs,par.getInt("SampleNum"),sampleFauxEdge); if(sampleFace) - tri::SurfaceSampling >::Montecarlo(mm0->cm,hs,par.getInt("SampleNum")); - + tri::SurfaceSampling >::Montecarlo(mm0->cm,hs,par.getInt("SampleNum")); + // the meshes have to return to their original position if (mm0->cm.Tr != Matrix44m::Identity()) tri::UpdatePosition::Matrix(mm0->cm, Inverse(mm0->cm.Tr), true); if (mm1->cm.Tr != Matrix44m::Identity()) tri::UpdatePosition::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::Box(samplePtMesh->cm); - tri::UpdateBounding::Box(closestPtMesh->cm); - - tri::UpdateColor::PerVertexQualityRamp(samplePtMesh->cm); - tri::UpdateColor::PerVertexQualityRamp(closestPtMesh->cm); + tri::UpdateBounding::Box(samplePtMesh->cm); + tri::UpdateBounding::Box(closestPtMesh->cm); + + tri::UpdateColor::PerVertexQualityRamp(samplePtMesh->cm); + tri::UpdateColor::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::Matrix(mm0->cm, mm0->cm.Tr, true); if (mm1->cm.Tr != Matrix44m::Identity()) tri::UpdatePosition::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::PerFaceNormalized(mm1->cm); tri::UpdateNormal::PerVertexNormalized(mm1->cm); } - mm1->updateDataMask(MeshModel::MM_FACEMARK); - + mm1->updateDataMask(MeshModel::MM_FACEMARK); + SimpleDistanceSampler ds(&(mm1->cm), useSigned, maxDistABS); - + tri::SurfaceSampling::AllVertex(mm0->cm, ds); - + // the meshes have to return to their original position if (mm0->cm.Tr != Matrix44m::Identity()) tri::UpdatePosition::Matrix(mm0->cm, Inverse(mm0->cm.Tr), true); if (mm1->cm.Tr != Matrix44m::Identity()) tri::UpdatePosition::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::VertexClear(trgMesh->cm); tri::UpdateSelection::VertexFromFaceLoose(trgMesh->cm); } - + // the meshes have to be transformed if (srcMesh->cm.Tr != Matrix44m::Identity()) tri::UpdatePosition::Matrix(srcMesh->cm, srcMesh->cm.Tr, true); if (trgMesh->cm.Tr != Matrix44m::Identity()) tri::UpdatePosition::Matrix(trgMesh->cm, trgMesh->cm.Tr, true); - + srcMesh->updateDataMask(MeshModel::MM_FACEMARK); tri::UpdateNormal::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::VertexUniform(trgMesh->cm, rs, trgMesh->cm.vn, onlySelected); - + if(rs.coordFlag) tri::UpdateNormal::PerFaceNormalized(trgMesh->cm); - + // the meshes have to return to their original position if (srcMesh->cm.Tr != Matrix44m::Identity()) tri::UpdatePosition::Matrix(srcMesh->cm, Inverse(srcMesh->cm.Tr), true); if (trgMesh->cm.Tr != Matrix44m::Identity()) tri::UpdatePosition::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,
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::Resample(baseMesh->cm, offsetMesh->cm, volumeBox, volumeDim, voxelSize*3.5, offsetThr,discretizeFlag,multiSampleFlag,absDistFlag, cb); tri::UpdateBounding::Box(offsetMesh->cm); if(mergeCloseVert) @@ -1263,13 +1277,13 @@ switch(ID(action)) } tri::UpdateNormal::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::RemoveUnreferencedVertex(mmM->cm); tri::Allocator::CompactVertexVector(mmM->cm); tri::Allocator::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 vecV; // points to vertices of ColoredMesh; tri::VoronoiProcessing::SeedToVertexConversion (mmM->cm, vecP, vecV); log("Converted %ui points into %ui vertex ",vecP.size(),vecV.size()); tri::EuclideanDistance edFunc; tri::VoronoiProcessing::ComputePerVertexSources(mmM->cm,vecV,edFunc); - + for(uint i=0;iC()=Color4b::Red; tri::VoronoiProcessing::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 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; icP(),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; iQ() = 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::RemoveUnreferencedVertex(mmM->cm); tri::Allocator::CompactEveryVector(mmM->cm); - + tri::UpdateNormal::PerFaceNormalized(mmM->cm); std::vector pvec; - + tri::SurfaceSampling::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