mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-17 01:54:42 +00:00
Heavily restructured the voronoi clustering alg. Still to make it more robust and faster.
This commit is contained in:
parent
63a1a78293
commit
2bb48e41f5
@ -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<CMeshO::VertexType *> seedVec;
|
||||
|
||||
ClusteringSampler<CMeshO> vc(&seedVec);
|
||||
tri::SurfaceSampling<CMeshO, ClusteringSampler<CMeshO> >::VertexUniform(*cm,vc,sampleNum);
|
||||
VoronoiProcessing<CMeshO>::GeodesicVertexColoring(*cm, seedVec);
|
||||
VoronoiProcessing<CMeshO>::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<CMeshO>::CompactVertexVector(md.mm()->cm);
|
||||
tri::Allocator<CMeshO>::CompactFaceVector(md.mm()->cm);
|
||||
|
||||
tri::UpdateBounding<CMeshO>::Box(clusteredMesh->cm);
|
||||
tri::UpdateNormals<CMeshO>::PerVertexPerFace(clusteredMesh->cm);
|
||||
ClusteringSampler<CMeshO> vc(&seedVec);
|
||||
if(randSeed!=0) tri::SurfaceSampling<CMeshO, ClusteringSampler<CMeshO> >::SamplingRandomGenerator().initialize(randSeed);
|
||||
tri::SurfaceSampling<CMeshO, ClusteringSampler<CMeshO> >::VertexUniform(*cm,vc,sampleNum);
|
||||
VoronoiProcessing<CMeshO>::GeodesicVertexColoring(*cm, seedVec, relaxIter);
|
||||
//VoronoiProcessing<CMeshO>::VoronoiClustering(*cm,clusteredMesh->cm,seedVec);
|
||||
|
||||
// tri::UpdateBounding<CMeshO>::Box(clusteredMesh->cm);
|
||||
// tri::UpdateNormals<CMeshO>::PerVertexPerFace(clusteredMesh->cm);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
@ -67,23 +67,75 @@ class VoronoiProcessing
|
||||
typedef typename MeshType::FaceContainer FaceContainer;
|
||||
public:
|
||||
|
||||
static void GeodesicVertexColoring(MeshType &m, std::vector<VertexType *> &seedVec)
|
||||
static void GeodesicVertexColoring(MeshType &m, std::vector<VertexType *> &seedVec, int relaxIter)
|
||||
{
|
||||
for(int iter=0;iter<relaxIter;++iter)
|
||||
{
|
||||
tri::Geo<CMeshO> 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<CMeshO>::VertexQualityRamp(m);
|
||||
// first run: find for each point what is the closest to one of the seeds.
|
||||
typename MeshType::template PerVertexAttributeHandle<VertexPointer> sources;
|
||||
sources = tri::Allocator<CMeshO>::AddPerVertexAttribute<VertexPointer> (m,"sources");
|
||||
g.FarthestVertex(m,seedVec,farthest,dist,&sources);
|
||||
|
||||
/*
|
||||
// find the vertexes of frontier faces
|
||||
tri::UpdateFlags<CMeshO>::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<VertexPointer> 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<CMeshO>::VertexQualityRamp(m);
|
||||
|
||||
// Search the local maxima for each region and use them as new seeds
|
||||
std::pair<float,VertexPointer> zz(0,0);
|
||||
std::vector< std::pair<float,VertexPointer> > 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<VertexPointer> newSeeds;
|
||||
for(int i=0;i<seedMaxima.size();++i)
|
||||
if(seedMaxima[i].second)
|
||||
{
|
||||
seedMaxima[i].second->C() = Color4b::Gray;
|
||||
newSeeds.push_back(seedMaxima[i].second);
|
||||
}
|
||||
|
||||
tri::UpdateColor<CMeshO>::VertexQualityRamp(m);
|
||||
for(int i=0;i<seedVec.size();++i)
|
||||
seedVec[i]->C() = Color4b::Black;
|
||||
|
||||
for(int i=0;i<borderVec.size();++i)
|
||||
borderVec[i]->C() = Color4b::Gray;
|
||||
|
||||
swap(newSeeds,seedVec);
|
||||
|
||||
for(int i=0;i<seedVec.size();++i)
|
||||
seedVec[i]->C() = Color4b::White;
|
||||
|
||||
tri::Allocator<CMeshO>::DeletePerVertexAttribute<VertexPointer> (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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user