diff --git a/src/meshlabplugins/filter_sampling/filter_sampling.cpp b/src/meshlabplugins/filter_sampling/filter_sampling.cpp index e66ff1fa1..8334f163c 100644 --- a/src/meshlabplugins/filter_sampling/filter_sampling.cpp +++ b/src/meshlabplugins/filter_sampling/filter_sampling.cpp @@ -504,7 +504,11 @@ void FilterDocSampling::initParameterSet(QAction *action, MeshDocument & md, Fil } break; case FP_VORONOI_CLUSTERING : { - parlst.addInt ("SampleNum", md.mm()->cm.vn/10, "Target vertex number", + parlst.addInt ("SampleNum", md.mm()->cm.vn/100, "Target vertex number", + "The final number of vertices."); + parlst.addInt ("RelaxIter", 1, "Relaxing Iterations", + "The final number of vertices."); + parlst.addInt ("RandSeed", 1, "Random Seed", "The final number of vertices."); } break; @@ -752,17 +756,25 @@ bool FilterDocSampling::applyFilter(QAction *action, MeshDocument &md, FilterPar case FP_VORONOI_CLUSTERING : { int sampleNum = par.getInt("SampleNum"); + int relaxIter = par.getInt("RelaxIter"); + int randSeed = par.getInt("RandSeed"); CMeshO *cm = &md.mm()->cm; - MeshModel *clusteredMesh =md.addNewMesh("Offset mesh"); +// MeshModel *clusteredMesh =md.addNewMesh("Offset mesh"); vector seedVec; - - ClusteringSampler vc(&seedVec); - tri::SurfaceSampling >::VertexUniform(*cm,vc,sampleNum); - VoronoiProcessing::GeodesicVertexColoring(*cm, seedVec); - VoronoiProcessing::VoronoiClustering(*cm,clusteredMesh->cm,seedVec); + md.mm()->updateDataMask(MeshModel::MM_VERTMARK); + md.mm()->updateDataMask(MeshModel::MM_VERTCOLOR); + md.mm()->updateDataMask(MeshModel::MM_VERTQUALITY); + tri::Allocator::CompactVertexVector(md.mm()->cm); + tri::Allocator::CompactFaceVector(md.mm()->cm); - tri::UpdateBounding::Box(clusteredMesh->cm); - tri::UpdateNormals::PerVertexPerFace(clusteredMesh->cm); + ClusteringSampler vc(&seedVec); + if(randSeed!=0) tri::SurfaceSampling >::SamplingRandomGenerator().initialize(randSeed); + tri::SurfaceSampling >::VertexUniform(*cm,vc,sampleNum); + VoronoiProcessing::GeodesicVertexColoring(*cm, seedVec, relaxIter); + //VoronoiProcessing::VoronoiClustering(*cm,clusteredMesh->cm,seedVec); + + // tri::UpdateBounding::Box(clusteredMesh->cm); + // tri::UpdateNormals::PerVertexPerFace(clusteredMesh->cm); } break; diff --git a/src/meshlabplugins/filter_sampling/voronoi_clustering.h b/src/meshlabplugins/filter_sampling/voronoi_clustering.h index 424f9ff04..d4e2eacfb 100644 --- a/src/meshlabplugins/filter_sampling/voronoi_clustering.h +++ b/src/meshlabplugins/filter_sampling/voronoi_clustering.h @@ -67,23 +67,75 @@ class VoronoiProcessing typedef typename MeshType::FaceContainer FaceContainer; public: -static void GeodesicVertexColoring(MeshType &m, std::vector &seedVec) +static void GeodesicVertexColoring(MeshType &m, std::vector &seedVec, int relaxIter) { + for(int iter=0;iter g; float dist; VertexPointer farthest; - g.FarthestVertex(m,seedVec,farthest,dist); - for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) - (*vi).Q()=(*vi).IMark(); - - tri::UpdateColor::VertexQualityRamp(m); + // first run: find for each point what is the closest to one of the seeds. + typename MeshType::template PerVertexAttributeHandle sources; + sources = tri::Allocator::AddPerVertexAttribute (m,"sources"); + g.FarthestVertex(m,seedVec,farthest,dist,&sources); - /* + // find the vertexes of frontier faces + tri::UpdateFlags::VertexClearV(m); for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) { - + if( sources[(*fi).V(0)] != sources[(*fi).V(1)] || + sources[(*fi).V(0)] != sources[(*fi).V(2)] ) + { + for(int i=0;i<3;++i) + { + (*fi).V(i)->SetV(); + (*fi).V(i)->C() = Color4b::Black; + } + } } - */ + // Collect the frontier vertexes and run the geodesic using them as sources. + std::vector borderVec; + for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) + if((*vi).IsV()) borderVec.push_back(&*vi); + + g.FarthestVertex(m,borderVec,farthest,dist); + tri::UpdateColor::VertexQualityRamp(m); + + // Search the local maxima for each region and use them as new seeds + std::pair zz(0,0); + std::vector< std::pair > seedMaxima(m.vert.size(),zz); + for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) + { + int seedIndex = sources[vi] - &*m.vert.begin(); + if(seedMaxima[seedIndex].first < (*vi).Q()) + { + seedMaxima[seedIndex].first=(*vi).Q(); + seedMaxima[seedIndex].second=&*vi; + } + } + std::vector newSeeds; + for(int i=0;iC() = Color4b::Gray; + newSeeds.push_back(seedMaxima[i].second); + } + + tri::UpdateColor::VertexQualityRamp(m); + for(int i=0;iC() = Color4b::Black; + + for(int i=0;iC() = Color4b::Gray; + + swap(newSeeds,seedVec); + + for(int i=0;iC() = Color4b::White; + + tri::Allocator::DeletePerVertexAttribute (m,"sources"); + + } } // Base vertex voronoi coloring algorithm. // it assumes VF adjacency. No attempt of computing real geodesic distnace is done. Just a BFS visit starting from the seeds.