Heavily restructured the voronoi clustering alg. Still to make it more robust and faster.

This commit is contained in:
Paolo Cignoni cignoni 2009-01-15 16:04:07 +00:00
parent 63a1a78293
commit 2bb48e41f5
2 changed files with 82 additions and 18 deletions

View File

@ -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;

View File

@ -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.