Further clean up of the voronoi relaxation framework. changed the old VoronoiClustering to ConvertToDelaunayTriangulation (for coherence with the other function) and rewrote its code.

This commit is contained in:
Paolo Cignoni 2013-12-20 11:44:18 +00:00
parent 91946b7847
commit 2df9b39d16
1 changed files with 44 additions and 31 deletions

View File

@ -74,8 +74,10 @@ struct VoronoiProcessingParameter
geodesicRelaxFlag = true; geodesicRelaxFlag = true;
} }
int colorStrategy; int colorStrategy;
float areaThresholdPerc; float areaThresholdPerc;
bool deleteUnreachedRegionFlag; bool deleteUnreachedRegionFlag;
bool unbiasedSeedFlag; bool unbiasedSeedFlag;
bool constrainSelectedSeed; /// If true the selected vertexes define a constraining domain: bool constrainSelectedSeed; /// If true the selected vertexes define a constraining domain:
/// During relaxation all selected seeds are constrained to move /// During relaxation all selected seeds are constrained to move
@ -83,12 +85,15 @@ struct VoronoiProcessingParameter
/// In this way you can constrain some seed to move only on certain /// In this way you can constrain some seed to move only on certain
/// domains, for example moving only along some linear features /// domains, for example moving only along some linear features
/// like border of creases. /// like border of creases.
bool preserveFixedSeed; /// If true the 'fixed' seeds are not moved during relaxation. bool preserveFixedSeed; /// If true the 'fixed' seeds are not moved during relaxation.
/// \see FixVertexVector function to see how to fix a set of seeds. /// \see FixVertexVector function to see how to fix a set of seeds.
bool triangulateRegion; bool triangulateRegion;
bool collapseShortEdge; bool collapseShortEdge;
float collapseShortEdgePerc; float collapseShortEdgePerc;
bool geodesicRelaxFlag; bool geodesicRelaxFlag;
}; };
@ -494,7 +499,6 @@ static void ConvertVoronoiDiagramToMesh(MeshType &m,
{ {
pos.Set(borderCornerVec[i],j,borderCornerVec[i]->V(j)); pos.Set(borderCornerVec[i],j,borderCornerVec[i]->V(j));
AllFaceVisited =false; AllFaceVisited =false;
printf("SearchForBorder\n");
} }
} }
if(AllFaceVisited) break; if(AllFaceVisited) break;
@ -592,6 +596,7 @@ static void ConvertVoronoiDiagramToMesh(MeshType &m,
// ******************* star to tri conversion ********* // ******************* star to tri conversion *********
if(vpp.triangulateRegion) if(vpp.triangulateRegion)
{ {
printf("Seedvec.size %i\n",seedVec.size());
for(FaceIterator fi=outMesh.face.begin();fi!=outMesh.face.end();++fi) if(!fi->IsD()) for(FaceIterator fi=outMesh.face.begin();fi!=outMesh.face.end();++fi) if(!fi->IsD())
{ {
for(int i=0;i<3;++i) for(int i=0;i<3;++i)
@ -603,8 +608,14 @@ static void ConvertVoronoiDiagramToMesh(MeshType &m,
{ {
// if(b0==b1) // if(b0==b1)
if(!seedVec[tri::Index(outMesh,fi->V(i))]->IsS()) if(!seedVec[tri::Index(outMesh,fi->V(i))]->IsS())
face::FFEdgeCollapse(outMesh, *fi,i); if(face::FFLinkCondition(outMesh, *fi, i))
break; {
printf("collapse %i\n",tri::Index(outMesh,fi->V(i)));
tri::io::ExporterPLY<MeshType>::Save(outMesh,"pre.ply");
face::FFEdgeCollapse(outMesh, *fi,i);
tri::io::ExporterPLY<MeshType>::Save(outMesh,"post.ply");
break;
}
} }
} }
} }
@ -1073,41 +1084,43 @@ static void TopologicalVertexColoring(MeshType &m, std::vector<VertexType *> &se
} }
// Drastic Simplification algorithm.
// Similar in philosopy to the classic grid clustering but using a voronoi partition instead of the regular grid.
//
// This function assumes that in the mOld mesh, for each vertex you have a quality that denotes the index of the cluster
// mNew is created by collasping onto a single vertex all the vertices that lies in the same cluster.
// Non degenerate triangles are preserved.
static void VoronoiClustering(MeshType &mOld, MeshType &mNew, std::vector<VertexType *> &seedVec) static void ConvertDelaunayTriangulationToMesh(MeshType &m,
MeshType &outMesh,
std::vector<VertexType *> &seedVec,
DistanceFunctor &df, VoronoiProcessingParameter &vpp )
{ {
std::set<Point3i> clusteredFace; typename MeshType::template PerVertexAttributeHandle<VertexPointer> sources;
sources = tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
FaceIterator fi; tri::Geodesic<MeshType>::Compute(m,seedVec, df,std::numeric_limits<ScalarType>::max(),0,&sources);
for(fi=mOld.face.begin();fi!=mOld.face.end();++fi) outMesh.Clear();
{ tri::UpdateTopology<MeshType>::FaceFace(m);
if( (fi->V(0)->Q() != fi->V(1)->Q() ) && tri::UpdateFlags<MeshType>::FaceBorderFromFF(m);
(fi->V(0)->Q() != fi->V(2)->Q() ) &&
(fi->V(1)->Q() != fi->V(2)->Q() ) )
clusteredFace.insert( Point3i(int(fi->V(0)->Q()), int(fi->V(1)->Q()), int(fi->V(2)->Q())));
}
tri::Allocator<MeshType>::AddVertices(mNew,seedVec.size()); std::map<VertexPointer, int> seedMap; // It says if a given vertex of m is a seed (and its index in seedVec)
for(size_t i=0;i< seedVec.size();++i) for(size_t i=0;i<m.vert.size();++i)
mNew.vert[i].ImportData(*(seedVec[i])); seedMap[&(m.vert[i])]=-1;
for(size_t i=0;i<seedVec.size();++i)
seedMap[seedVec[i]]=i;
tri::Allocator<MeshType>::AddFaces(mNew,clusteredFace.size()); std::vector<FacePointer> innerCornerVec, // Faces adjacent to three different regions
std::set<Point3i>::iterator fsi; ; borderCornerVec; // Faces that are on the border and adjacent to at least two regions.
GetFaceCornerVec(m, sources, innerCornerVec, borderCornerVec);
for(fi=mNew.face.begin(),fsi=clusteredFace.begin(); fsi!=clusteredFace.end();++fsi,++fi) // First add all the needed vertices: seeds and corners
{ for(size_t i=0;i<seedVec.size();++i)
(*fi).V(0) = & mNew.vert[(int)(fsi->V(0)-1)]; tri::Allocator<MeshType>::AddVertex(outMesh, seedVec[i]->P(),Color4b::White);
(*fi).V(1) = & mNew.vert[(int)(fsi->V(1)-1)];
(*fi).V(2) = & mNew.vert[(int)(fsi->V(2)-1)]; // Now just add a face for each inner corner
} for(size_t i=0;i<innerCornerVec.size();++i)
{
VertexPointer v0 = & outMesh.vert[seedMap[sources[innerCornerVec[i]->V(0)]]];
VertexPointer v1 = & outMesh.vert[seedMap[sources[innerCornerVec[i]->V(1)]]];
VertexPointer v2 = & outMesh.vert[seedMap[sources[innerCornerVec[i]->V(2)]]];
tri::Allocator<MeshType>::AddFace(outMesh,v0,v1,v2);
}
} }
}; // end class VoronoiProcessing }; // end class VoronoiProcessing
} // end namespace tri } // end namespace tri