voronoi_processing.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * MeshLab                                                           o o     *
00003 * A versatile mesh processing toolbox                             o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2005                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 
00024 #ifndef VORONOI_PROCESSING_H
00025 #define VORONOI_PROCESSING_H
00026 
00027 #include<vcg/complex/algorithms/geodesic.h>
00028 #include<vcg/complex/algorithms/update/color.h>
00029 #include<vcg/complex/algorithms/refine.h>
00030 #include<vcg/complex/algorithms/smooth.h>
00031 #include<vcg/space/fitting3.h>
00032 #include<wrap/callback.h>
00033 
00034 namespace vcg
00035 {
00036 namespace tri
00037 {
00038 
00039 struct VoronoiProcessingParameter
00040 {
00041   enum {
00042     None=0,
00043     DistanceFromSeed=1,
00044     DistanceFromBorder=2,
00045     RegionArea=3
00046   };
00047 
00048   VoronoiProcessingParameter()
00049   {
00050     colorStrategy = DistanceFromSeed;
00051     areaThresholdPerc=0;
00052     deleteUnreachedRegionFlag=false;
00053     constrainSelectedSeed=false;
00054     preserveFixedSeed=false;
00055     collapseShortEdge=false;
00056     collapseShortEdgePerc = 0.01f;
00057     triangulateRegion=false;
00058     unbiasedSeedFlag = true;
00059     geodesicRelaxFlag = true;
00060     relaxOnlyConstrainedFlag=false;
00061     refinementRatio = 5.0f;
00062     seedPerturbationProbability=0;
00063     seedPerturbationAmount = 0.001f;
00064 
00065   }
00066   int colorStrategy;
00067 
00068   float areaThresholdPerc;
00069   bool deleteUnreachedRegionFlag;
00070 
00071   bool unbiasedSeedFlag;
00072   bool constrainSelectedSeed;   
00073 
00074 
00075 
00076 
00077 
00078 
00079   bool relaxOnlyConstrainedFlag;
00080 
00081   bool preserveFixedSeed;       
00082 
00083 
00084   float refinementRatio;        
00085 
00086 
00087 
00088   float seedPerturbationProbability;      
00089   float seedPerturbationAmount;      
00090 
00091   // Convertion to Voronoi Diagram Parameters
00092 
00093   bool triangulateRegion;       
00094 
00095 
00096 
00097   bool collapseShortEdge;
00098   float collapseShortEdgePerc;
00099 
00100   bool geodesicRelaxFlag;
00101 };
00102 
00103 template <class MeshType, class DistanceFunctor = EuclideanDistance<MeshType> >
00104 class VoronoiProcessing
00105 {
00106   typedef typename MeshType::CoordType                          CoordType;
00107   typedef typename MeshType::ScalarType                         ScalarType;
00108   typedef typename MeshType::VertexType                         VertexType;
00109   typedef typename MeshType::VertexPointer              VertexPointer;
00110   typedef typename MeshType::VertexIterator             VertexIterator;
00111   typedef typename MeshType::FacePointer                        FacePointer;
00112   typedef typename MeshType::FaceIterator                       FaceIterator;
00113   typedef typename MeshType::FaceType                                   FaceType;
00114   typedef typename MeshType::FaceContainer              FaceContainer;
00115   typedef typename tri::Geodesic<MeshType>::VertDist VertDist;
00116 
00117   static math::MarsenneTwisterRNG &RandomGenerator()
00118   {
00119       static math::MarsenneTwisterRNG rnd;
00120       return rnd;
00121   }
00122 
00123 public:
00124 
00125   typedef typename MeshType::template PerVertexAttributeHandle<VertexPointer> PerVertexPointerHandle;
00126   typedef typename MeshType::template PerVertexAttributeHandle<bool> PerVertexBoolHandle;
00127   typedef typename MeshType::template PerVertexAttributeHandle<float> PerVertexFloatHandle;
00128   typedef typename MeshType::template PerFaceAttributeHandle<VertexPointer> PerFacePointerHandle;
00129 
00130 
00131 
00132 // Given a vector of point3f it finds the closest vertices on the mesh.
00133 static void SeedToVertexConversion(MeshType &m,std::vector<CoordType> &seedPVec,std::vector<VertexType *> &seedVVec, bool compactFlag = true)
00134 {
00135     typedef typename vcg::SpatialHashTable<VertexType, ScalarType> HashVertexGrid;
00136     seedVVec.clear();
00137 
00138     HashVertexGrid HG;
00139     HG.Set(m.vert.begin(),m.vert.end());
00140 
00141     const float dist_upper_bound=m.bbox.Diag()/10.0;
00142 
00143     typename std::vector<CoordType>::iterator pi;
00144     for(pi=seedPVec.begin();pi!=seedPVec.end();++pi)
00145         {
00146             ScalarType dist;
00147             VertexPointer vp;
00148             vp=tri::GetClosestVertex<MeshType,HashVertexGrid>(m, HG, *pi, dist_upper_bound, dist);
00149             if(vp)
00150                 {
00151                     seedVVec.push_back(vp);
00152                 }
00153         }
00154     if(compactFlag)
00155     {
00156       std::sort(seedVVec.begin(),seedVVec.end());
00157       typename std::vector<VertexType *>::iterator vi = std::unique(seedVVec.begin(),seedVVec.end());
00158       seedVVec.resize( std::distance(seedVVec.begin(),vi) );
00159     }
00160 }
00161 
00162 
00163 static void ComputePerVertexSources(MeshType &m, std::vector<VertexType *> &seedVec, DistanceFunctor &df)
00164 {
00165   tri::Allocator<MeshType>::DeletePerVertexAttribute(m,"sources"); // delete any conflicting handle regardless of the type...
00166   PerVertexPointerHandle vertexSources =  tri::Allocator<MeshType>:: template AddPerVertexAttribute<VertexPointer> (m,"sources");
00167 
00168   tri::Allocator<MeshType>::DeletePerFaceAttribute(m,"sources"); // delete any conflicting handle regardless of the type...
00169   tri::Allocator<MeshType>::template AddPerFaceAttribute<VertexPointer> (m,"sources");
00170 
00171   assert(tri::Allocator<MeshType>::IsValidHandle(m,vertexSources));
00172 
00173   tri::Geodesic<MeshType>::Compute(m,seedVec,df,std::numeric_limits<ScalarType>::max(),0,&vertexSources);
00174 }
00175 
00176 static void VoronoiColoring(MeshType &m, bool frontierFlag=true)
00177 {
00178   PerVertexPointerHandle sources =  tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
00179   assert(tri::Allocator<MeshType>::IsValidHandle(m,sources));
00180 
00181   if(frontierFlag)
00182   {
00183     //static_cast<VertexPointer>(NULL) has been introduced just to avoid an error in the MSVS2010's compiler confusing pointer with int. You could use nullptr to avoid it, but it's not supported by all compilers.
00184     //The error should have been removed from MSVS2012
00185     std::pair<float,VertexPointer> zz(0.0f,static_cast<VertexPointer>(NULL));
00186     std::vector< std::pair<float,VertexPointer> > regionArea(m.vert.size(),zz);
00187     std::vector<VertexPointer> frontierVec;
00188     GetAreaAndFrontier(m, sources,  regionArea, frontierVec);
00189     tri::Geodesic<MeshType>::Compute(m,frontierVec);
00190   }
00191   float minQ =  std::numeric_limits<float>::max();
00192   float maxQ = -std::numeric_limits<float>::max();
00193   
00194   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
00195     if(sources[*vi])
00196     {
00197       if( (*vi).Q() < minQ) minQ=(*vi).Q();
00198       if( (*vi).Q() > maxQ) maxQ=(*vi).Q();
00199     }
00200   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
00201     if(sources[*vi])
00202           (*vi).C().SetColorRamp(minQ,maxQ,(*vi).Q());
00203   else 
00204       (*vi).C()=Color4b::DarkGray;
00205   
00206 //  tri::UpdateColor<MeshType>::PerVertexQualityRamp(m);
00207 }
00208 
00209 static void VoronoiAreaColoring(MeshType &m,std::vector<VertexType *> &seedVec,
00210                                 std::vector< std::pair<float,VertexPointer> > &regionArea)
00211 {
00212   PerVertexPointerHandle vertexSources =  tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
00213   float meshArea = tri::Stat<MeshType>::ComputeMeshArea(m);
00214   float expectedArea = meshArea/float(seedVec.size());
00215   for(size_t i=0;i<m.vert.size();++i)
00216       m.vert[i].C()=Color4b::ColorRamp(expectedArea *0.75f ,expectedArea*1.25f, regionArea[tri::Index(m,vertexSources[i])].first);
00217 }
00218 // It associates the faces with a given vertex according to the vertex associations
00219 //
00220 // It READS  the PerVertex attribute 'sources'
00221 // It WRITES the PerFace attribute 'sources'
00222 
00223 static void FaceAssociateRegion(MeshType &m)
00224 {
00225   PerFacePointerHandle   faceSources =  tri::Allocator<MeshType>:: template GetPerFaceAttribute<VertexPointer> (m,"sources");
00226   PerVertexPointerHandle vertexSources =  tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
00227   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00228   {
00229     faceSources[fi]=0;
00230     std::vector<VertexPointer> vp(3);
00231     for(int i=0;i<3;++i) vp[i]=vertexSources[fi->V(i)];
00232 
00233     for(int i=0;i<3;++i) // First try to associate to the most reached vertex
00234     {
00235       if(vp[0]==vp[1] && vp[0]==vp[2]) faceSources[fi] = vp[0];
00236       else
00237       {
00238         if(vp[0]==vp[1] && vp[0]->Q()< vp[2]->Q()) faceSources[fi] = vp[0];
00239         if(vp[0]==vp[2] && vp[0]->Q()< vp[1]->Q()) faceSources[fi] = vp[0];
00240         if(vp[1]==vp[2] && vp[1]->Q()< vp[0]->Q()) faceSources[fi] = vp[1];
00241       }
00242     }
00243   }
00244   tri::UpdateTopology<MeshType>::FaceFace(m);
00245   int unassCnt=0;
00246   do
00247   {
00248     unassCnt=0;
00249     for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00250     {
00251       if(faceSources[fi]==0)
00252       {
00253         std::vector<VertexPointer> vp(3);
00254         for(int i=0;i<3;++i)
00255           vp[i]=faceSources[fi->FFp(i)];
00256 
00257         if(vp[0]!=0 && (vp[0]==vp[1] || vp[0]==vp[2]))
00258           faceSources[fi] = vp[0];
00259         else if(vp[1]!=0 && (vp[1]==vp[2]))
00260           faceSources[fi] = vp[1];
00261         else
00262           faceSources[fi] = std::max(vp[0],std::max(vp[1],vp[2]));
00263         if(faceSources[fi]==0) unassCnt++;
00264       }
00265     }
00266   }
00267   while(unassCnt>0);
00268 }
00269 
00270 // Select all the faces with a given source vertex <vp>
00271 // It reads the PerFace attribute 'sources'
00272 
00273 static int FaceSelectAssociateRegion(MeshType &m, VertexPointer vp)
00274 {
00275   PerFacePointerHandle sources =  tri::Allocator<MeshType>:: template FindPerFaceAttribute<VertexPointer> (m,"sources");
00276   assert(tri::Allocator<MeshType>::IsValidHandle(m,sources));
00277   tri::UpdateSelection<MeshType>::Clear(m);
00278   int selCnt=0;
00279   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00280   {
00281     if(sources[fi]==vp)
00282     {
00283       fi->SetS();
00284       ++selCnt;
00285     }
00286   }
00287   return selCnt;
00288 }
00289 
00290 // Given a seed <vp>, it selects all the faces that have the minimal distance vertex sourced by the given <vp>.
00291 // <vp> can be null (it search for unreached faces...)
00292 // returns the number of selected faces;
00293 //
00294 // It reads the PerVertex attribute 'sources'
00295 static int FaceSelectRegion(MeshType &m, VertexPointer vp)
00296 {
00297   PerVertexPointerHandle sources =  tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
00298   assert(tri::Allocator<MeshType>::IsValidHandle(m,sources));
00299   tri::UpdateSelection<MeshType>::Clear(m);
00300   int selCnt=0;
00301   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00302   {
00303     int minInd = 0; float minVal=std::numeric_limits<float>::max();
00304     for(int i=0;i<3;++i)
00305     {
00306       if((*fi).V(i)->Q()<minVal)
00307       {
00308         minInd=i;
00309         minVal=(*fi).V(i)->Q();
00310       }
00311     }
00312 
00313     if( sources[(*fi).V(minInd)] == vp)
00314     {
00315       fi->SetS();
00316       selCnt++;
00317     }
00318   }
00319   return selCnt;
00320 }
00321 
00329 
00330 static void GetAreaAndFrontier(MeshType &m, PerVertexPointerHandle &sources,
00331                                std::vector< std::pair<float, VertexPointer> > &regionArea, // for each seed we store area
00332                                std::vector<VertexPointer> &frontierVec)
00333 {
00334   tri::UpdateFlags<MeshType>::VertexClearV(m);
00335   frontierVec.clear();
00336   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00337   {
00338     VertexPointer s0 = sources[(*fi).V(0)];
00339     VertexPointer s1 = sources[(*fi).V(1)];
00340     VertexPointer s2 = sources[(*fi).V(2)];
00341     assert(s0 && s1 && s2);
00342     if((s0 != s1) || (s0 != s2) )
00343     {
00344       for(int i=0;i<3;++i)
00345         if(!fi->V(i)->IsV())
00346         {
00347           frontierVec.push_back(fi->V(i));
00348           fi->V(i)->SetV();
00349         }
00350     }
00351     else // the face belongs to a single region; accumulate area;
00352     {
00353       if(s0 != 0)
00354       {
00355         int seedIndex = tri::Index(m,s0);
00356         regionArea[seedIndex].first+=DoubleArea(*fi)*0.5f;
00357         regionArea[seedIndex].second=s0;
00358       }
00359     }
00360   }
00361 }
00362 
00363 
00368 
00369 static void GetFaceCornerVec(MeshType &m, PerVertexPointerHandle &sources,
00370                                std::vector<FacePointer> &cornerVec,
00371                                std::vector<FacePointer> &borderCornerVec)
00372 {
00373   tri::UpdateFlags<MeshType>::VertexClearV(m);
00374   cornerVec.clear();
00375   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00376   {
00377     VertexPointer s0 = sources[(*fi).V(0)];
00378     VertexPointer s1 = sources[(*fi).V(1)];
00379     VertexPointer s2 = sources[(*fi).V(2)];
00380     assert(s0 && s1 && s2);
00381     if(s1!=s2 && s0!=s1 && s0!=s2) {
00382         cornerVec.push_back(&*fi);
00383       }
00384     else
00385     {
00386       if(isBorderCorner(&*fi,sources))
00387           borderCornerVec.push_back(&*fi);
00388     }
00389   }
00390 }
00391 
00392 static bool isBorderCorner(FaceType *f, typename MeshType::template PerVertexAttributeHandle<VertexPointer> &sources)
00393 {
00394   for(int i=0;i<3;++i)
00395   {
00396     if(sources[(*f).V0(i)] != sources[(*f).V1(i)] && f->IsB(i))
00397       return true;
00398   }
00399   return false;
00400 }
00401 
00402 // Given two supposedly adjacent border corner faces it finds the source common to them;
00403 static VertexPointer CommonSourceBetweenBorderCorner(FacePointer f0, FacePointer f1,  typename MeshType::template PerVertexAttributeHandle<VertexPointer> &sources)
00404 {
00405   assert(isBorderCorner(f0,sources));
00406   assert(isBorderCorner(f1,sources));
00407   int b0 =-1,b1=-1;
00408   for(int i=0;i<3;++i)
00409   {
00410     if(face::IsBorder(*f0,i)) b0=i;
00411     if(face::IsBorder(*f1,i)) b1=i;
00412   }
00413   assert(b0!=-1 && b1!=-1);
00414 
00415   if( (sources[f0->V0(b0)] == sources[f1->V0(b1)]) || (sources[f0->V0(b0)] == sources[f1->V1(b1)]) )
00416     return sources[f0->V0(b0)];
00417 
00418   if( (sources[f0->V1(b0)] == sources[f1->V0(b1)]) || (sources[f0->V1(b0)] == sources[f1->V1(b1)]) )
00419     return sources[f0->V1(b0)];
00420 
00421   assert(0);
00422   return 0;
00423 }
00424 
00425 
00426 static void ConvertVoronoiDiagramToMesh(MeshType &m,
00427                                         MeshType &outMesh, MeshType &outPoly,
00428                                         std::vector<VertexType *> &seedVec,
00429                                         VoronoiProcessingParameter &vpp )
00430 {
00431   tri::RequirePerVertexAttribute(m,"sources");
00432   PerVertexPointerHandle sources = tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
00433   outMesh.Clear();
00434   outPoly.Clear();
00435   tri::UpdateTopology<MeshType>::FaceFace(m);
00436   tri::UpdateFlags<MeshType>::FaceBorderFromFF(m);
00437 
00438   std::vector<FacePointer> innerCornerVec,   // Faces adjacent to three different regions
00439                            borderCornerVec;  // Faces that are on the border and adjacent to at least two regions.
00440   GetFaceCornerVec(m, sources, innerCornerVec, borderCornerVec);
00441 
00442   // For each seed collect all the vertices and build
00443   for(size_t i=0;i<seedVec.size();++i)
00444     tri::Allocator<MeshType>::AddVertex(outMesh,seedVec[i]->P(),Color4b::DarkGray);
00445 
00446   for(size_t i=0;i<seedVec.size();++i)
00447   {
00448     VertexPointer curSeed=seedVec[i];
00449     vector<CoordType> pt;
00450     for(size_t j=0;j<innerCornerVec.size();++j)
00451       for(int qq=0;qq<3;qq++)
00452         if(sources[innerCornerVec[j]->V(qq)] == curSeed)
00453         {
00454           pt.push_back(Barycenter(*innerCornerVec[j]));
00455           break;
00456         }
00457     for(size_t j=0;j<borderCornerVec.size();++j)
00458       for(int qq=0;qq<3;qq++)
00459         if(sources[borderCornerVec[j]->V(qq)] == curSeed)
00460         {
00461           CoordType edgeCenter;
00462           for(int jj=0;jj<3;++jj) if(face::IsBorder(*(borderCornerVec[j]),jj))
00463             edgeCenter=(borderCornerVec[j]->P0(jj)+borderCornerVec[j]->P1(jj))/2.0f;
00464           pt.push_back(edgeCenter);
00465           break;
00466         }
00467     Plane3<ScalarType> pl;
00468     pt.push_back(curSeed->P());
00469     FitPlaneToPointSet(pt,pl);
00470     pt.pop_back();
00471     CoordType nZ = pl.Direction();
00472     CoordType nX = (pt[0]-curSeed->P()).Normalize();
00473     CoordType nY = (nX^nZ).Normalize();
00474     vector<std::pair<float,int> > angleVec(pt.size());
00475     for(size_t j=0;j<pt.size();++j)
00476     {
00477       CoordType p = (pt[j]-curSeed->P()).Normalize();
00478       float angle = 180.0f+math::ToDeg(atan2(p*nY,p*nX));
00479       angleVec[j] = make_pair(angle,j);
00480     }
00481     std::sort(angleVec.begin(),angleVec.end());
00482     // Now build another piece of mesh.
00483     int curRegionStart=outMesh.vert.size();
00484 
00485 
00486     for(size_t j=0;j<pt.size();++j)
00487       tri::Allocator<MeshType>::AddVertex(outMesh,pt[angleVec[j].second],Color4b::LightGray);
00488 
00489     for(size_t j=0;j<pt.size();++j){
00490       float curAngle = angleVec[(j+1)%pt.size()].first - angleVec[j].first;
00491 //      printf("seed %4i (%i) - face %i angle %5.1f %5.1f %5.1f\n",i,curRegionStart,j,angleVec[j].first,angleVec[(j+1)%pt.size()].first,curAngle);
00492       if(curAngle < 0) curAngle += 360.0;
00493       if(curAngle < 170.0)
00494         tri::Allocator<MeshType>::AddFace(outMesh,
00495                                           &outMesh.vert[i   ],
00496                                           &outMesh.vert[curRegionStart + j ],
00497             &outMesh.vert[curRegionStart + ((j+1)%pt.size())]);
00498        outMesh.face.back().SetF(0);
00499        outMesh.face.back().SetF(2);
00500     }
00501   } // end for each seed.
00502   tri::Clean<MeshType>::RemoveDuplicateVertex(outMesh);
00503   tri::UpdateTopology<MeshType>::FaceFace(outMesh);
00504   bool oriented,orientable;
00505   tri::Clean<MeshType>::OrientCoherentlyMesh(outMesh,oriented,orientable);
00506   tri::UpdateTopology<MeshType>::FaceFace(outMesh);
00507 
00508   // last loop to remove faux edges bit that are now on the boundary.
00509   for(FaceIterator fi=outMesh.face.begin();fi!=outMesh.face.end();++fi)
00510     for(int i=0;i<3;++i)
00511       if(face::IsBorder(*fi,i) && fi->IsF(i)) fi->ClearF(i);
00512 
00513   std::vector< typename tri::UpdateTopology<MeshType>::PEdge> EdgeVec;
00514 
00515   // ******************* star to tri conversion *********
00516   // If requested the voronoi regions are converted from a star arragned polygon
00517   // with vertex on the seed to a simple triangulated polygon by mean of a simple edge collapse
00518   if(vpp.triangulateRegion)
00519   {
00520     tri::UpdateFlags<MeshType>::FaceBorderFromFF(outMesh);
00521     tri::UpdateFlags<MeshType>::VertexBorderFromFaceBorder(outMesh);
00522     for(FaceIterator fi=outMesh.face.begin();fi!=outMesh.face.end();++fi) if(!fi->IsD())
00523     {
00524       for(int i=0;i<3;++i)
00525       {
00526         bool b0 = fi->V0(i)->IsB();
00527         bool b1 = fi->V1(i)->IsB();
00528         if( ((b0  && b1) || (fi->IsF(i) && !b0) ) &&
00529             tri::Index(outMesh,fi->V0(i))<seedVec.size())
00530         {
00531           if(!seedVec[tri::Index(outMesh,fi->V0(i))]->IsS())
00532             if(face::FFLinkCondition(*fi, i))
00533             {
00534               face::FFEdgeCollapse(outMesh, *fi,i); // we delete vertex fi->V0(i)
00535               break;
00536             }
00537         }
00538       }
00539     }
00540   }
00541 
00542   // Now a plain conversion of the non faux edges into a polygonal mesh
00543   tri::UpdateTopology<MeshType>::FillUniqueEdgeVector(outMesh,EdgeVec,false);
00544   tri::UpdateTopology<MeshType>::AllocateEdge(outMesh);
00545   for(size_t i=0;i<outMesh.vert.size();++i)
00546     tri::Allocator<MeshType>::AddVertex(outPoly,outMesh.vert[i].P());
00547   for(size_t i=0;i<EdgeVec.size();++i)
00548   {
00549     size_t e0 = tri::Index(outMesh,EdgeVec[i].v[0]);
00550     size_t e1 = tri::Index(outMesh,EdgeVec[i].v[1]);
00551     assert(e0<outPoly.vert.size());
00552     tri::Allocator<MeshType>::AddEdge(outPoly,&(outPoly.vert[e0]),&(outPoly.vert[e1]));
00553   }
00554 
00555 }
00556 
00566 
00567 static void ConvertVoronoiDiagramToMeshOld(MeshType &m,
00568                                         MeshType &outMesh, MeshType &outPoly,
00569                                         std::vector<VertexType *> &seedVec,
00570                                         VoronoiProcessingParameter &vpp )
00571 {
00572   tri::RequirePerVertexAttribute(m,"sources");
00573   PerVertexPointerHandle sources = tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
00574 
00575   outMesh.Clear();
00576   outPoly.Clear();
00577   tri::UpdateTopology<MeshType>::FaceFace(m);
00578   tri::UpdateFlags<MeshType>::FaceBorderFromFF(m);
00579 
00580   std::map<VertexPointer, int> seedMap;  // It says if a given vertex of m is a seed (and what position it has in the seed vector)
00581   for(size_t i=0;i<m.vert.size();++i)
00582     seedMap[&(m.vert[i])]=-1;
00583   for(size_t i=0;i<seedVec.size();++i)
00584     seedMap[seedVec[i]]=i;
00585 
00586   // Consistency Checks
00587   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
00588   {
00589     assert(sources[vi] != 0);  // all vertices mush have a source must be seeds.
00590     int ind=tri::Index(m,sources[vi]);
00591     assert((ind>=0) && (ind<m.vn)); // the source must be a vertex of the mesh
00592     assert(seedMap[sources[vi]]!=-1); // the source must be one of the seedVec
00593   }
00594 
00595   std::vector<FacePointer> innerCornerVec,   // Faces adjacent to three different regions
00596                            borderCornerVec;  // Faces that are on the border and adjacent to at least two regions.
00597   GetFaceCornerVec(m, sources, innerCornerVec, borderCornerVec);
00598 
00599   std::map<FacePointer,int> vertexIndCornerMap; // Given a cornerFace (border or inner) what is the corresponding vertex?
00600   for(size_t i=0;i<m.face.size();++i)
00601     vertexIndCornerMap[&(m.face[i])]=-1;
00602 
00603   // First add all the needed vertices: seeds and corners
00604   for(size_t i=0;i<seedVec.size();++i)
00605     tri::Allocator<MeshType>::AddVertex(outMesh, seedVec[i]->P(),Color4b::White);
00606 
00607   for(size_t i=0;i<innerCornerVec.size();++i){
00608     tri::Allocator<MeshType>::AddVertex(outMesh, vcg::Barycenter(*(innerCornerVec[i])),Color4b::Gray);
00609     vertexIndCornerMap[innerCornerVec[i]] = outMesh.vn-1;
00610   }
00611   for(size_t i=0;i<borderCornerVec.size();++i){
00612     Point3f edgeCenter;
00613     for(int j=0;j<3;++j) if(face::IsBorder(*(borderCornerVec[i]),j))
00614       edgeCenter=(borderCornerVec[i]->P0(j)+borderCornerVec[i]->P1(j))/2.0f;
00615     tri::Allocator<MeshType>::AddVertex(outMesh, edgeCenter,Color4b::Gray);
00616     vertexIndCornerMap[borderCornerVec[i]] = outMesh.vn-1;
00617   }
00618   tri::Append<MeshType,MeshType>::MeshCopy(outPoly,outMesh);
00619 
00620   // There is a voronoi edge if there are two corner face that share two sources.
00621   // In such a case we add a pair of triangles with an edge connecting these two corner faces
00622   // and with the two involved sources
00623   // For each pair of adjacent seed we store the first of the two corner that we encounter.
00624   std::map<std::pair<VertexPointer,VertexPointer>, FacePointer > VoronoiEdge;
00625 
00626   // 1) Build internal triangles
00627   // Loop build all the triangles connecting seeds with internal corners
00628   // we loop over the all the voronoi corner (triangles with three different sources)
00629   // we build
00630   for(size_t i=0;i<innerCornerVec.size();++i)
00631   {
00632     for(int j=0;j<3;++j)
00633     {
00634       VertexPointer v0 = sources[innerCornerVec[i]->V0(j)];
00635       VertexPointer v1 = sources[innerCornerVec[i]->V1(j)];
00636       assert(seedMap[v0]>=0);assert(seedMap[v1]>=0);
00637 
00638       if(v1<v0) std::swap(v0,v1); assert(v1!=v0);
00639 
00640       if(VoronoiEdge[std::make_pair(v0,v1)] == 0)
00641         VoronoiEdge[std::make_pair(v0,v1)] = innerCornerVec[i];
00642       else
00643       {
00644         FacePointer otherCorner = VoronoiEdge[std::make_pair(v0,v1)];
00645         VertexPointer corner0 = &(outMesh.vert[vertexIndCornerMap[innerCornerVec[i]]]);
00646         VertexPointer corner1 = &(outMesh.vert[vertexIndCornerMap[otherCorner]]);
00647         tri::Allocator<MeshType>::AddFace(outMesh,&(outMesh.vert[seedMap[v0]]), corner0, corner1);
00648         tri::Allocator<MeshType>::AddFace(outMesh,&(outMesh.vert[seedMap[v1]]), corner1, corner0);
00649       }
00650     }
00651   }
00652 
00653   // 2) build the boundary facets:
00654   // We loop over border corners and build triangles with seed vertex
00655   // we do **only** triangles with a  bordercorner and a internal 'corner'
00656   for(size_t i=0;i<borderCornerVec.size();++i)
00657   {
00658     VertexPointer s0 = sources[borderCornerVec[i]->V(0)]; // All bordercorner faces have only two different regions
00659     VertexPointer s1 = sources[borderCornerVec[i]->V(1)];
00660     if(s1==s0)    s1 = sources[borderCornerVec[i]->V(2)];
00661     if(s1<s0) std::swap(s0,s1); assert(s1!=s0);
00662 
00663     FacePointer innerCorner = VoronoiEdge[std::make_pair(s0,s1)] ;
00664     if(innerCorner)
00665     {
00666       VertexPointer corner0 = &(outMesh.vert[vertexIndCornerMap[innerCorner]]);
00667       VertexPointer corner1 = &(outMesh.vert[vertexIndCornerMap[borderCornerVec[i]]]);
00668       tri::Allocator<MeshType>::AddFace(outMesh,&(outMesh.vert[seedMap[s0]]), corner0, corner1);
00669       tri::Allocator<MeshType>::AddFace(outMesh,&(outMesh.vert[seedMap[s1]]), corner0, corner1);
00670     }
00671   }
00672 
00673   // Final pass
00674   tri::UpdateFlags<MeshType>::FaceClearV(m);
00675   bool AllFaceVisited = false;
00676   while(!AllFaceVisited)
00677   {
00678     // search for a unvisited boundary face
00679     face::Pos<FaceType> pos,startPos;
00680     AllFaceVisited=true;
00681     for(size_t i=0; (AllFaceVisited) && (i<borderCornerVec.size()); ++i)
00682       if(!borderCornerVec[i]->IsV())
00683       {
00684         for(int j=0;j<3;++j)
00685           if(face::IsBorder(*(borderCornerVec[i]),j))
00686           {
00687             pos.Set(borderCornerVec[i],j,borderCornerVec[i]->V(j));
00688             AllFaceVisited =false;
00689           }
00690       }
00691     if(AllFaceVisited) break;
00692     assert(pos.IsBorder());
00693     startPos=pos;
00694     bool foundBorderSeed=false;
00695     FacePointer curBorderCorner = pos.F();
00696     do
00697     {
00698       pos.F()->SetV();
00699       pos.NextB();
00700       if(sources[pos.V()]==pos.V())
00701         foundBorderSeed=true;
00702       assert(isBorderCorner(curBorderCorner,sources));
00703       if(isBorderCorner(pos.F(),sources))
00704         if(pos.F() != curBorderCorner)
00705         {
00706           VertexPointer curReg = CommonSourceBetweenBorderCorner(curBorderCorner, pos.F(),sources);
00707           VertexPointer curSeed = &(outMesh.vert[seedMap[curReg]]);
00708           int otherCorner0 = vertexIndCornerMap[pos.F() ];
00709           int otherCorner1 = vertexIndCornerMap[curBorderCorner];
00710           VertexPointer corner0 = &(outMesh.vert[otherCorner0]);
00711           VertexPointer corner1 = &(outMesh.vert[otherCorner1]);
00712           if(!foundBorderSeed)
00713             tri::Allocator<MeshType>::AddFace(outMesh,curSeed,corner0,corner1);
00714           foundBorderSeed=false;
00715           curBorderCorner=pos.F();
00716         }
00717     }
00718     while(pos!=startPos);
00719   }
00720 
00721   //**************** CLEANING ***************
00722   // 1) reorient
00723   bool oriented,orientable;
00724   tri::UpdateTopology<MeshType>::FaceFace(outMesh);
00725   tri::Clean<MeshType>::OrientCoherentlyMesh(outMesh,oriented,orientable);
00726 //  assert(orientable);
00727   // check that the normal of the input mesh are consistent with the result
00728   tri::UpdateNormal<MeshType>::PerVertexNormalizedPerFaceNormalized(outMesh);
00729   tri::UpdateNormal<MeshType>::PerVertexNormalizedPerFaceNormalized(m);
00730   if(seedVec[0]->N() * outMesh.vert[0].N() < 0 )
00731     tri::Clean<MeshType>::FlipMesh(outMesh);
00732 
00733   tri::UpdateTopology<MeshType>::FaceFace(outMesh);
00734   tri::UpdateFlags<MeshType>::FaceBorderFromFF(outMesh);
00735 
00736   // 2) Remove Flips
00737   tri::UpdateNormal<MeshType>::PerFaceNormalized(outMesh);
00738   tri::UpdateFlags<MeshType>::FaceClearV(outMesh);
00739   for(FaceIterator fi=outMesh.face.begin();fi!=outMesh.face.end();++fi)
00740   {
00741     int badDiedralCnt=0;
00742     for(int i=0;i<3;++i)
00743       if(fi->N() * fi->FFp(i)->N() <0 ) badDiedralCnt++;
00744 
00745     if(badDiedralCnt == 2) fi->SetV();
00746   }
00747   for(FaceIterator fi=outMesh.face.begin();fi!=outMesh.face.end();++fi)
00748     if(fi->IsV())  Allocator<MeshType>::DeleteFace(outMesh,*fi);
00749   tri::Allocator<MeshType>::CompactEveryVector(outMesh);
00750   tri::UpdateTopology<MeshType>::FaceFace(outMesh);
00751   tri::UpdateFlags<MeshType>::FaceBorderFromFF(outMesh);
00752   tri::UpdateFlags<MeshType>::VertexBorderFromFaceBorder(outMesh);
00753 
00754   // 3) set up faux bits
00755   for(FaceIterator fi=outMesh.face.begin();fi!=outMesh.face.end();++fi)
00756     for(int i=0;i<3;++i)
00757     {
00758       size_t v0 = tri::Index(outMesh,fi->V0(i) );
00759       size_t v1 = tri::Index(outMesh,fi->V1(i) );
00760       if (v0 < seedVec.size() && !(seedVec[v0]->IsB() && fi->IsB(i))) fi->SetF(i);
00761       if (v1 < seedVec.size() && !(seedVec[v1]->IsB() && fi->IsB(i))) fi->SetF(i);
00762     }
00763 
00764   if(vpp.collapseShortEdge)
00765   {
00766     float distThr = m.bbox.Diag() * vpp.collapseShortEdgePerc;
00767     for(FaceIterator fi=outMesh.face.begin();fi!=outMesh.face.end();++fi) if(!fi->IsD())
00768     {
00769       for(int i=0;i<3;++i)
00770         if((Distance(fi->P0(i),fi->P1(i))<distThr) && !fi->IsF(i))
00771         {
00772 //          printf("Collapsing face %i:%i e%i \n",tri::Index(outMesh,*fi),tri::Index(outMesh,fi->FFp(i)),i);
00773           if ((!fi->V(i)->IsB())&&(face::FFLinkCondition(*fi, i)))
00774             face::FFEdgeCollapse(outMesh, *fi,i);
00775           break;
00776         }
00777     }
00778   }
00779 
00780   //******************** END OF CLEANING ****************
00781 
00782 
00783   // ******************* star to tri conversion *********
00784   // If requested the voronoi regions are converted from a star arragned polygon
00785   // with vertex on the seed to a simple triangulated polygon by mean of a simple edge collapse
00786   if(vpp.triangulateRegion)
00787   {
00788     for(FaceIterator fi=outMesh.face.begin();fi!=outMesh.face.end();++fi) if(!fi->IsD())
00789     {
00790       for(int i=0;i<3;++i)
00791       {
00792         bool b0 = fi->V0(i)->IsB();
00793         bool b1 = fi->V1(i)->IsB();
00794         if( ((b0  && b1) || (fi->IsF(i) && !b0 && !b1) ) &&
00795             tri::Index(outMesh,fi->V(i))<seedVec.size())
00796         {
00797           if(!seedVec[tri::Index(outMesh,fi->V(i))]->IsS())
00798             if(face::FFLinkCondition(*fi, i))
00799             {
00800               face::FFEdgeCollapse(outMesh, *fi,i);
00801               break;
00802             }
00803         }
00804       }
00805     }
00806   }
00807 
00808   // Now a plain conversion of the non faux edges into a polygonal mesh
00809   std::vector< typename tri::UpdateTopology<MeshType>::PEdge> EdgeVec;
00810   tri::UpdateTopology<MeshType>::FillUniqueEdgeVector(outMesh,EdgeVec,false);
00811   tri::UpdateTopology<MeshType>::AllocateEdge(outMesh);
00812 
00813   for(size_t i=0;i<EdgeVec.size();++i)
00814   {
00815     size_t e0 = tri::Index(outMesh,EdgeVec[i].v[0]);
00816     size_t e1 = tri::Index(outMesh,EdgeVec[i].v[1]);
00817     assert(e0<outPoly.vert.size());
00818     tri::Allocator<MeshType>::AddEdge(outPoly,&(outPoly.vert[e0]),&(outPoly.vert[e1]));
00819   }
00820 }
00821 
00822 class VoronoiEdge
00823 {
00824 public:
00825   VertexPointer r0,r1;
00826   FacePointer f0,f1;
00827   bool operator == (const VoronoiEdge &ve) const {return ve.r0==r0 && ve.r1==r1; }
00828   bool operator < (const VoronoiEdge &ve) const { return (ve.r0==r0)?ve.r1<r1:ve.r0<r0; }
00829   float Len() const { return Distance(vcg::Barycenter(*f0), vcg::Barycenter(*f1)); }
00830 };
00831 
00832 static void BuildVoronoiEdgeVec(MeshType &m, std::vector<VoronoiEdge> &edgeVec)
00833 {
00834   PerVertexPointerHandle sources =  tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
00835 
00836   edgeVec.clear();
00837   std::vector<FacePointer> cornerVec;
00838   std::vector<FacePointer> borderCornerVec;
00839   GetFaceCornerVec(m,sources,cornerVec,borderCornerVec);
00840   // Now find all the voronoi edges: each edge (a *face pair) is identified by two voronoi regions
00841   typedef std::map< std::pair<VertexPointer,VertexPointer>, std::pair<FacePointer,FacePointer> > EdgeMapType;
00842   EdgeMapType EdgeMap;
00843   printf("cornerVec.size() %i\n",(int)cornerVec.size());
00844 
00845   for(size_t i=0;i<cornerVec.size();++i)
00846   {
00847     for(int j=0;j<3;++j)
00848     {
00849       VertexPointer v0 = sources[cornerVec[i]->V0(j)];
00850       VertexPointer v1 = sources[cornerVec[i]->V1(j)];
00851       assert(v0!=v1);
00852       if(v0>v1) std::swap(v1,v0);
00853       std::pair<VertexPointer,VertexPointer> adjRegion = std::make_pair(v0,v1);
00854       if(EdgeMap[adjRegion].first==0)
00855         EdgeMap[adjRegion].first = cornerVec[i];
00856       else
00857         EdgeMap[adjRegion].second = cornerVec[i];
00858     }
00859   }
00860   for(size_t i=0;i<borderCornerVec.size();++i)
00861   {
00862     VertexPointer v0 = sources[borderCornerVec[i]->V(0)];
00863     VertexPointer v1 = sources[borderCornerVec[i]->V(1)];
00864     if(v0==v1) v1 = sources[borderCornerVec[i]->V(2)];
00865     assert(v0!=v1);
00866     if(v0>v1) std::swap(v1,v0);
00867     std::pair<VertexPointer,VertexPointer> adjRegion = std::make_pair(v0,v1);
00868     if(EdgeMap[adjRegion].first==0)
00869       EdgeMap[adjRegion].first = borderCornerVec[i];
00870     else
00871       EdgeMap[adjRegion].second = borderCornerVec[i];
00872 
00873   }
00874   typename EdgeMapType::iterator mi;
00875   for(mi=EdgeMap.begin();mi!=EdgeMap.end();++mi)
00876   {
00877     if((*mi).second.first && (*mi).second.second)
00878     {
00879       assert((*mi).first.first && (*mi).first.second);
00880     edgeVec.push_back(VoronoiEdge());
00881     edgeVec.back().r0 = (*mi).first.first;
00882     edgeVec.back().r1 = (*mi).first.second;
00883     edgeVec.back().f0 = (*mi).second.first;
00884     edgeVec.back().f1 = (*mi).second.second;
00885     }
00886   }
00887 }
00888 
00889 static void BuildBiasedSeedVec(MeshType &m,
00890                                DistanceFunctor &df,
00891                                std::vector<VertexPointer> &seedVec,
00892                                std::vector<VertexPointer> &frontierVec,
00893                                std::vector<VertDist> &biasedFrontierVec,
00894                                VoronoiProcessingParameter &vpp)
00895 {
00896     (void)df;
00897   biasedFrontierVec.clear();
00898   if(vpp.unbiasedSeedFlag)
00899   {
00900     for(size_t i=0;i<frontierVec.size();++i)
00901       biasedFrontierVec.push_back(VertDist(frontierVec[i],0));
00902     assert(biasedFrontierVec.size() == frontierVec.size());
00903     return;
00904   }
00905 
00906   std::vector<VoronoiEdge> edgeVec;
00907   BuildVoronoiEdgeVec(m,edgeVec);
00908   printf("Found %i edges on a diagram of %i seeds\n",int(edgeVec.size()),int(seedVec.size()));
00909 
00910   std::map<VertexPointer,std::vector<VoronoiEdge *> > SeedToEdgeVecMap;
00911   std::map< std::pair<VertexPointer,VertexPointer>, VoronoiEdge *> SeedPairToEdgeMap;
00912   float totalLen=0;
00913   for(size_t i=0;i<edgeVec.size();++i)
00914   {
00915     SeedToEdgeVecMap[edgeVec[i].r0].push_back(&(edgeVec[i]));
00916     SeedToEdgeVecMap[edgeVec[i].r1].push_back(&(edgeVec[i]));
00917     SeedPairToEdgeMap[std::make_pair(edgeVec[i].r0, edgeVec[i].r1)]=&(edgeVec[i]);
00918     assert (edgeVec[i].r0 < edgeVec[i].r1);
00919     totalLen +=edgeVec[i].Len();
00920   }
00921 
00922   // compute the perimeter of each region
00923   std::map <VertexPointer, float> regionPerymeter;
00924   for(size_t i=0;i<seedVec.size();++i)
00925   {
00926     for(size_t j=0;j<SeedToEdgeVecMap[seedVec[i]].size();++j)
00927     {
00928       VoronoiEdge *vep = SeedToEdgeVecMap[seedVec[i]][j];
00929       regionPerymeter[seedVec[i]]+=vep->Len();
00930     }
00931     printf("perimeter of region %i is %f\n",(int)i,regionPerymeter[seedVec[i]]);
00932   }
00933 
00934 
00935   PerVertexPointerHandle sources =  tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
00936   // The real bias for each edge is (perim)/(edge)
00937   // each source can belong to two edges max. so the weight is
00938   std::map<VertexPointer,float> weight;
00939   std::map<VertexPointer,int> cnt;
00940   float biasSum = totalLen/5.0f;
00941   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00942   {
00943     for(int i=0;i<3;++i)
00944     {
00945       VertexPointer s0 = sources[(*fi).V0(i)];
00946       VertexPointer s1 = sources[(*fi).V1(i)];
00947       if(s0!=s1)
00948       {
00949         if(s0>s1) std::swap(s0,s1);
00950         VoronoiEdge *ve = SeedPairToEdgeMap[std::make_pair(s0,s1)];
00951         if(!ve) printf("v %i %i \n",(int)tri::Index(m,s0),(int)tri::Index(m,s1));
00952         assert(ve);
00953         float el = ve->Len();
00954         weight[(*fi).V0(i)] += (regionPerymeter[s0]+biasSum)/(el+biasSum) ;
00955         weight[(*fi).V1(i)] += (regionPerymeter[s1]+biasSum)/(el+biasSum) ;
00956         cnt[(*fi).V0(i)]++;
00957         cnt[(*fi).V1(i)]++;
00958       }
00959     }
00960   }
00961   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
00962   {
00963     if(cnt[&*vi]>0)
00964     {
00965 //      float bias = weight[&*vi]/float(cnt[&*vi]);
00966       float bias = weight[&*vi]/float(cnt[&*vi]) + totalLen;
00967       biasedFrontierVec.push_back(VertDist(&*vi, bias));
00968     }
00969   }
00970   printf("Collected %i frontier vertexes\n",(int)biasedFrontierVec.size());
00971 }
00972 
00973 
00974 static void DeleteUnreachedRegions(MeshType &m, PerVertexPointerHandle &sources)
00975 {
00976   tri::UpdateFlags<MeshType>::VertexClearV(m);
00977   for(size_t i=0;i<m.vert.size();++i)
00978     if(sources[i]==0) m.vert[i].SetV();
00979 
00980   for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi)
00981     if(fi->V(0)->IsV() || fi->V(1)->IsV() || fi->V(2)->IsV() )
00982     {
00983       face::VFDetach(*fi);
00984       tri::Allocator<MeshType>::DeleteFace(m,*fi);
00985     }
00986   //            qDebug("Deleted faces not reached: %i -> %i",int(m.face.size()),m.fn);
00987   tri::Clean<MeshType>::RemoveUnreferencedVertex(m);
00988   tri::Allocator<MeshType>::CompactEveryVector(m);
00989 }
00990 
00995 
00996 struct QuadricSumDistance
00997 {
00998   ScalarType a;
00999   ScalarType c;
01000   CoordType b;
01001   QuadricSumDistance() {a=0; c=0; b[0]=0; b[1]=0; b[2]=0;}
01002   void AddPoint(CoordType p)
01003   {
01004     a+=1;
01005     assert(c>=0);
01006     c+=p*p;
01007     b[0]+= -2.0f*p[0];
01008     b[1]+= -2.0f*p[1];
01009     b[2]+= -2.0f*p[2];
01010   }
01011 
01012   ScalarType Eval(CoordType p) const
01013   {
01014     ScalarType d = a*(p*p) + b*p + c;
01015     assert(d>=0);
01016     return d;
01017   }
01018 
01019   CoordType Min() const
01020   {
01021     return b * -0.5f;
01022   }
01023 };
01024 
01036 static bool QuadricRelax(MeshType &m, std::vector<VertexType *> &seedVec,
01037                          std::vector<VertexPointer> &frontierVec,
01038                          std::vector<VertexType *> &newSeeds,
01039                          DistanceFunctor &df,
01040                          VoronoiProcessingParameter &vpp)
01041 {
01042     (void)seedVec;
01043     (void)frontierVec;
01044     (void)df;
01045   newSeeds.clear();
01046   PerVertexPointerHandle sources = tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
01047   PerVertexBoolHandle fixed = tri::Allocator<MeshType>:: template GetPerVertexAttribute<bool> (m,"fixed");
01048 
01049   QuadricSumDistance dz;
01050   std::vector<QuadricSumDistance> dVec(m.vert.size(),dz);
01051   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
01052   {
01053     assert(sources[vi]!=0);
01054     int seedIndex = tri::Index(m,sources[vi]);
01055     // When constraining seeds movement we move selected seeds only onto other selected vertices
01056     if(vpp.constrainSelectedSeed)
01057     { // So we sum only the contribs of the selected vertices
01058       if( (sources[vi]->IsS() && vi->IsS()) || (!sources[vi]->IsS()))
01059         dVec[seedIndex].AddPoint(vi->P());
01060     }
01061     else
01062       dVec[seedIndex].AddPoint(vi->P());
01063   }
01064 
01065   // Search the local maxima for each region and use them as new seeds
01066   std::pair<float,VertexPointer> zz(std::numeric_limits<ScalarType>::max(), static_cast<VertexPointer>(0));
01067   std::vector< std::pair<float,VertexPointer> > seedMaximaVec(m.vert.size(),zz);
01068   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
01069   {
01070     assert(sources[vi]!=0);
01071     int seedIndex = tri::Index(m,sources[vi]);
01072     ScalarType val = dVec[seedIndex].Eval(vi->P());
01073     vi->Q()=val;
01074     // if constrainSelectedSeed we search only among selected vertices
01075     if(!vpp.constrainSelectedSeed || !sources[vi]->IsS() || vi->IsS())
01076     {
01077       if(seedMaximaVec[seedIndex].first > val)
01078       {
01079         seedMaximaVec[seedIndex].first = val;
01080         seedMaximaVec[seedIndex].second = &*vi;
01081       }
01082     }
01083   }
01084 
01085   if(vpp.colorStrategy==VoronoiProcessingParameter::DistanceFromBorder)
01086     tri::UpdateColor<MeshType>::PerVertexQualityRamp(m);
01087 
01088 //  tri::io::ExporterPLY<MeshType>::Save(m,"last.ply",tri::io::Mask::IOM_VERTCOLOR + tri::io::Mask::IOM_VERTQUALITY );
01089   bool seedChanged=false;
01090   // update the seedvector with the new maxima (For the vertex not fixed)
01091   for(size_t i=0;i<m.vert.size();++i)
01092     if(seedMaximaVec[i].second) // Most of the seedMaximaVec is unused: only the updated entries have a non zero pointer
01093     {
01094       VertexPointer curSrc = sources[seedMaximaVec[i].second];
01095       if(vpp.preserveFixedSeed && fixed[curSrc])
01096         newSeeds.push_back(curSrc);
01097       else
01098       {
01099         newSeeds.push_back(seedMaximaVec[i].second);
01100         if(curSrc != seedMaximaVec[i].second)
01101           seedChanged=true;
01102       }
01103     }
01104 
01105   return seedChanged;
01106 }
01107 
01115 
01116 static bool GeodesicRelax(MeshType &m, std::vector<VertexType *> &seedVec, std::vector<VertexPointer> &frontierVec,
01117                           std::vector<VertexType *> &newSeeds,
01118                           DistanceFunctor &df, VoronoiProcessingParameter &vpp)
01119 {
01120   newSeeds.clear();
01121   typename MeshType::template PerVertexAttributeHandle<VertexPointer> sources;
01122   sources = tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
01123   typename MeshType::template PerVertexAttributeHandle<bool> fixed;
01124   fixed = tri::Allocator<MeshType>:: template GetPerVertexAttribute<bool> (m,"fixed");
01125 
01126   std::vector<typename tri::Geodesic<MeshType>::VertDist> biasedFrontierVec;
01127   BuildBiasedSeedVec(m,df,seedVec,frontierVec,biasedFrontierVec,vpp);
01128   tri::Geodesic<MeshType>::Visit(m,biasedFrontierVec,df);
01129   if(vpp.colorStrategy == VoronoiProcessingParameter::DistanceFromSeed)
01130     tri::UpdateColor<MeshType>::PerVertexQualityRamp(m);
01131   //    tri::io::ExporterPLY<MeshType>::Save(m,"last.ply",tri::io::Mask::IOM_VERTCOLOR + tri::io::Mask::IOM_VERTQUALITY );
01132 
01133   if(vpp.colorStrategy == VoronoiProcessingParameter::DistanceFromBorder)
01134     tri::UpdateColor<MeshType>::PerVertexQualityRamp(m);
01135 
01136   // Search the local maxima for each region and use them as new seeds
01137   std::pair<float,VertexPointer> zz(0.0f,static_cast<VertexPointer>(NULL));
01138   std::vector< std::pair<float,VertexPointer> > seedMaximaVec(m.vert.size(),zz);
01139   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
01140   {
01141     assert(sources[vi]!=0);
01142     int seedIndex = tri::Index(m,sources[vi]);
01143 
01144     if(!vpp.constrainSelectedSeed || !sources[vi]->IsS() || vi->IsS())
01145     {
01146       if(seedMaximaVec[seedIndex].first < (*vi).Q())
01147       {
01148         seedMaximaVec[seedIndex].first=(*vi).Q();
01149         seedMaximaVec[seedIndex].second=&*vi;
01150       }
01151     }
01152   }
01153 
01154   bool seedChanged=false;
01155 
01156   // update the seedvector with the new maxima (For the vertex not selected)
01157   for(size_t i=0;i<seedMaximaVec.size();++i)
01158     if(seedMaximaVec[i].second)// only updated entries have a non zero pointer
01159     {
01160       VertexPointer curSrc = sources[seedMaximaVec[i].second];
01161       if(vpp.preserveFixedSeed && fixed[curSrc])
01162         newSeeds.push_back(curSrc);
01163       else
01164       {
01165         newSeeds.push_back(seedMaximaVec[i].second);
01166         if(curSrc != seedMaximaVec[i].second) seedChanged=true;
01167       }
01168     }
01169   return seedChanged;
01170 }
01171 
01172 static void PruneSeedByRegionArea(std::vector<VertexType *> &seedVec,
01173                                   std::vector< std::pair<float,VertexPointer> > &regionArea,
01174                                   VoronoiProcessingParameter &vpp)
01175 {
01176   // Smaller area region are discarded
01177   Distribution<float> H;
01178   for(size_t i=0;i<regionArea.size();++i)
01179     if(regionArea[i].second) H.Add(regionArea[i].first);
01180   float areaThreshold=0;
01181   if(vpp.areaThresholdPerc != 0) areaThreshold = H.Percentile(vpp.areaThresholdPerc);
01182   std::vector<VertexType *> newSeedVec;
01183 
01184   // update the seedvector with the new maxima (For the vertex not selected)
01185   for(size_t i=0;i<seedVec.size();++i)
01186   {
01187     if(regionArea[i].first >= areaThreshold)
01188       newSeedVec.push_back(seedVec[i]);
01189   }
01190   swap(seedVec,newSeedVec);
01191 }
01192 
01198 static void FixVertexVector(MeshType &m, std::vector<VertexType *> &vertToFixVec)
01199 {
01200   typename MeshType::template PerVertexAttributeHandle<bool> fixed;
01201   fixed = tri::Allocator<MeshType>:: template GetPerVertexAttribute<bool> (m,"fixed");
01202   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
01203     fixed[vi]=false;
01204   for(size_t i=0;i<vertToFixVec.size();++i)
01205     fixed[vertToFixVec[i]]=true;
01206 }
01207 
01208 
01209 static int RestrictedVoronoiRelaxing(MeshType &m, std::vector<CoordType> &seedPosVec,
01210                                      std::vector<bool> &fixedVec,
01211                                      int relaxStep,
01212                                      VoronoiProcessingParameter &vpp,
01213                                      vcg::CallBackPos *cb=0)
01214 {
01215   PerVertexFloatHandle area = tri::Allocator<MeshType>:: template GetPerVertexAttribute<float> (m,"area");
01216 
01217   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
01218     area[vi]=0;
01219 
01220   for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
01221   {
01222     ScalarType a3 = DoubleArea(*fi)/6.0;
01223     for(int i=0;i<3;++i)
01224       area[fi->V(i)]+=a3;
01225   }
01226 
01227   assert(m.vn > seedPosVec.size()*20);
01228   int i;
01229   ScalarType perturb = m.bbox.Diag()*vpp.seedPerturbationAmount;
01230   for(i=0;i<relaxStep;++i)
01231   {
01232     if(cb) cb(i*100/relaxStep,"RestrictedVoronoiRelaxing ");    
01233     // Kdtree for the seeds must be rebuilt at each step;
01234     VectorConstDataWrapper<std::vector<CoordType> > vdw(seedPosVec);
01235     KdTree<ScalarType> seedTree(vdw);
01236 
01237     std::vector<std::pair<ScalarType,CoordType> > sumVec(seedPosVec.size(),std::make_pair(0,CoordType(0,0,0)));
01238     for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
01239     {
01240       unsigned int seedInd;
01241       ScalarType sqdist;
01242       seedTree.doQueryClosest(vi->P(),seedInd,sqdist);
01243       vi->Q()=sqrt(sqdist);
01244       sumVec[seedInd].first+=area[vi];
01245       sumVec[seedInd].second+=vi->cP()*area[vi];
01246     }
01247 
01248     vector<CoordType> newseedVec;
01249     vector<bool> newfixedVec;
01250 
01251     for(size_t i=0;i<seedPosVec.size();++i)
01252     {
01253       if(fixedVec[i])
01254       {
01255         newseedVec.push_back(seedPosVec[i]);
01256         newfixedVec.push_back(true);
01257       }
01258       else
01259       {
01260         if(sumVec[i].first != 0)
01261         {
01262           newseedVec.push_back(sumVec[i].second /ScalarType(sumVec[i].first));
01263           if(vpp.seedPerturbationProbability > RandomGenerator().generate01())
01264             newseedVec.back()+=math::GeneratePointInUnitBallUniform<ScalarType,math::MarsenneTwisterRNG>( RandomGenerator())*perturb;
01265           newfixedVec.push_back(false);
01266         }
01267       }
01268     }
01269     std::swap(seedPosVec,newseedVec);
01270     std::swap(fixedVec,newfixedVec);
01271     tri::UpdateColor<MeshType>::PerVertexQualityRamp(m);
01272   }
01273   return relaxStep;
01274 }
01275 
01281 
01282 static int VoronoiRelaxing(MeshType &m, std::vector<VertexType *> &seedVec,
01283                             int relaxIter, DistanceFunctor &df,
01284                             VoronoiProcessingParameter &vpp,
01285                             vcg::CallBackPos *cb=0)
01286 {
01287   tri::RequireVFAdjacency(m);
01288   tri::RequireCompactness(m);
01289   for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
01290     assert(vi->VFp() && "Require mesh without unreferenced vertexes\n");
01291   std::vector<VertexType *> selectedVec;
01292   if(vpp.relaxOnlyConstrainedFlag)
01293   {
01294     for(size_t i=0;i<seedVec.size();++i)
01295       if(seedVec[i]->IsS())
01296         selectedVec.push_back(seedVec[i]);
01297     std::swap(seedVec,selectedVec);
01298   }
01299 
01300   tri::UpdateFlags<MeshType>::FaceBorderFromVF(m);
01301   tri::UpdateFlags<MeshType>::VertexBorderFromFaceBorder(m);
01302   PerVertexPointerHandle sources = tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
01303   PerVertexBoolHandle fixed = tri::Allocator<MeshType>:: template GetPerVertexAttribute<bool> (m,"fixed");
01304   int iter;
01305   for(iter=0;iter<relaxIter;++iter)
01306   {
01307     if(cb) cb(iter*100/relaxIter,"Voronoi Lloyd Relaxation: First Partitioning");
01308 
01309     // first run: find for each point what is the closest to one of the seeds.
01310     tri::Geodesic<MeshType>::Compute(m, seedVec, df,std::numeric_limits<ScalarType>::max(),0,&sources);
01311 
01312     if(vpp.colorStrategy == VoronoiProcessingParameter::DistanceFromSeed)
01313       tri::UpdateColor<MeshType>::PerVertexQualityRamp(m);
01314     // Delete all the (hopefully) small regions that have not been reached by the seeds;
01315 
01316     if(vpp.deleteUnreachedRegionFlag)  DeleteUnreachedRegions(m,sources);
01317     std::pair<float,VertexPointer> zz(0.0f,static_cast<VertexPointer>(NULL));
01318     std::vector< std::pair<float,VertexPointer> > regionArea(m.vert.size(),zz);
01319     std::vector<VertexPointer> frontierVec;
01320 
01321     GetAreaAndFrontier(m, sources,  regionArea, frontierVec);
01322     assert(frontierVec.size()>0);
01323 
01324     if(vpp.colorStrategy == VoronoiProcessingParameter::RegionArea) VoronoiAreaColoring(m, seedVec, regionArea);
01325 
01326     //    qDebug("We have found %i regions range (%f %f), avg area is %f, Variance is %f 10perc is %f",(int)seedVec.size(),H.Min(),H.Max(),H.Avg(),H.StandardDeviation(),areaThreshold);
01327 
01328     if(cb) cb(iter*100/relaxIter,"Voronoi Lloyd Relaxation: Searching New Seeds");
01329     std::vector<VertexPointer> newSeedVec;
01330 
01331     bool changed;
01332     if(vpp.geodesicRelaxFlag)
01333       changed = GeodesicRelax(m,seedVec, frontierVec, newSeedVec, df,vpp);
01334     else
01335       changed = QuadricRelax(m,seedVec,frontierVec, newSeedVec, df,vpp);
01336 
01337     //assert(newSeedVec.size() == seedVec.size());
01338     PruneSeedByRegionArea(newSeedVec,regionArea,vpp);
01339 
01340     for(size_t i=0;i<frontierVec.size();++i)
01341       frontierVec[i]->C() = Color4b::Gray;
01342     for(size_t i=0;i<seedVec.size();++i)
01343       seedVec[i]->C() = Color4b::Black;
01344     for(size_t i=0;i<newSeedVec.size();++i)
01345       newSeedVec[i]->C() = Color4b::White;
01346 
01347     swap(newSeedVec,seedVec);
01348     if(!changed) break;
01349   }
01350 
01351   // Last run: Needed if we have changed the seed set to leave the sources handle correct.
01352   if(iter==relaxIter)
01353     tri::Geodesic<MeshType>::Compute(m, seedVec, df,std::numeric_limits<ScalarType>::max(),0,&sources);
01354 
01355   if(vpp.relaxOnlyConstrainedFlag)
01356   {
01357     std::swap(seedVec,selectedVec);
01358     size_t i,j;
01359     for(i=0,j=0;i<seedVec.size();++i){
01360       if(seedVec[i]->IsS())
01361       {
01362         seedVec[i]=selectedVec[j];
01363         fixed[seedVec[i]]=true;
01364         ++j;
01365       }
01366     }
01367   }
01368   return iter;
01369 }
01370 
01371 
01372 // Base vertex voronoi coloring algorithm.
01373 // It assumes VF adjacency. 
01374 // No attempt of computing real geodesic distnace is done. Just a BFS visit starting from the seeds
01375 // It leaves in each vertex quality the index of the seed.
01376 
01377 static void TopologicalVertexColoring(MeshType &m, std::vector<VertexType *> &seedVec)
01378 {
01379   std::queue<VertexPointer> VQ;
01380 
01381   tri::UpdateQuality<MeshType>::VertexConstant(m,0);
01382 
01383   for(size_t i=0;i<seedVec.size();++i)
01384   {
01385     VQ.push(seedVec[i]);
01386     seedVec[i]->Q()=i+1;
01387   }
01388 
01389   while(!VQ.empty())
01390   {
01391     VertexPointer vp = VQ.front();
01392     VQ.pop();
01393 
01394     std::vector<VertexPointer> vertStar;
01395     vcg::face::VVStarVF<FaceType>(vp,vertStar);
01396     for(typename std::vector<VertexPointer>::iterator vv = vertStar.begin();vv!=vertStar.end();++vv)
01397     {
01398       if((*vv)->Q()==0)
01399       {
01400         (*vv)->Q()=vp->Q();
01401         VQ.push(*vv);
01402       }
01403     }
01404   } // end while(!VQ.empty())
01405 
01406 }
01407 
01408 
01409 template <class genericType>
01410 static std::pair<genericType, genericType> ordered_pair(const genericType &a, const genericType &b)
01411 {
01412   if(a<b) return std::make_pair(a,b);
01413   return std::make_pair(b,a);
01414 }
01415 
01423 static void GenerateMidPointMap(MeshType &m,
01424                                 map<std::pair<VertexPointer,VertexPointer>, VertexPointer > &midMap)
01425 {
01426   PerVertexPointerHandle sources = tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
01427 
01428   for(FaceIterator fi = m.face.begin(); fi!=m.face.end(); ++fi)
01429   {
01430     VertexPointer vp[3],sp[3];
01431     vp[0] =    (*fi).V(0);  vp[1] =    (*fi).V(1);  vp[2] =    (*fi).V(2);
01432     sp[0] = sources[vp[0]]; sp[1] = sources[vp[1]]; sp[2] = sources[vp[2]];
01433     if((sp[0] == sp[1]) && (sp[0] == sp[2])) continue; // skip internal faces
01434 //    if((sp[0] != sp[1]) && (sp[0] != sp[2]) && (sp[1] != sp[2])) continue; // skip corner faces
01435 
01436     for(int i=0;i<3;++i) // for each edge of a frontier face
01437     {
01438       int i0 = i;
01439       int i1 = (i+1)%3;
01440 //      if((sp[i0]->IsS() && sp[i1]->IsS()) && !( vp[i0]->IsS() || vp[i1]->IsS() ) ) continue;
01441 
01442       VertexPointer closestVert = vp[i0];
01443       if( vp[i1]->Q() <  closestVert->Q()) closestVert =  vp[i1];
01444 
01445       if(sp[i0]->IsS() && sp[i1]->IsS())
01446       {
01447          if ( (vp[i0]->IsS()) && !(vp[i1]->IsS()) ) closestVert =  vp[i0];
01448          if (!(vp[i0]->IsS()) &&  (vp[i1]->IsS()) ) closestVert =  vp[i1];
01449          if ( (vp[i0]->IsS()) &&  (vp[i1]->IsS()) ) closestVert =  (vp[i0]->Q() < vp[i1]->Q()) ? vp[i0]:vp[i1];
01450       }
01451 
01452       if(midMap[ordered_pair(sp[i0],sp[i1])] == 0 ) {
01453         midMap[ordered_pair(sp[i0],sp[i1])] = closestVert;
01454       }
01455       else {
01456         if(sp[i0]->IsS() && sp[i1]->IsS()) // constrained edge
01457         {
01458           if(!(midMap[ordered_pair(sp[i0],sp[i1])]->IsS()) && closestVert->IsS())
01459              midMap[ordered_pair(sp[i0],sp[i1])] = closestVert;
01460           if( midMap[ordered_pair(sp[i0],sp[i1])]->IsS() && closestVert->IsS() &&
01461             closestVert->Q() < midMap[ordered_pair(sp[i0],sp[i1])]->Q())
01462           {
01463             midMap[ordered_pair(sp[i0],sp[i1])] = closestVert;
01464           }
01465         }
01466         else // UNCOSTRAINED EDGE
01467         {
01468         if(closestVert->Q() < midMap[ordered_pair(sp[i0],sp[i1])]->Q())
01469           midMap[ordered_pair(sp[i0],sp[i1])] = closestVert;
01470         }
01471       }
01472     }
01473   }
01474 }
01475 
01484 
01485 static bool CheckVoronoiTopology(MeshType& m,std::vector<VertexType *> &seedVec)
01486 {
01487   tri::RequirePerVertexAttribute(m,"sources");
01488   tri::RequireCompactness(m);
01489 
01490   typename MeshType::template PerVertexAttributeHandle<VertexPointer> sources;
01491   sources = tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
01492 
01493   std::map<VertexPointer, int> seedMap;  // It says if a given vertex of m is a seed (and its index in seedVec)
01494   BuildSeedMap(m,seedVec,seedMap);
01495 
01496   // Very basic check: each vertex must have a source that is a seed.
01497   for(int i=0;i<m.vn;++i)
01498   {
01499     VertexPointer vp = sources[i];
01500     int seedInd = seedMap[vp];
01501     if(seedInd <0)
01502       return false;
01503   }
01504 
01505   std::vector<MeshType *> regionVec(seedVec.size(),0);
01506   for(size_t i=0; i< seedVec.size();i++) regionVec[i] = new MeshType;
01507 
01508   for(int i=0;i<m.fn;++i)
01509   {
01510     int vi0 = seedMap[sources[m.face[i].V(0)]];
01511     int vi1 = seedMap[sources[m.face[i].V(1)]];
01512     int vi2 = seedMap[sources[m.face[i].V(2)]];
01513     assert(vi0>=0 && vi1>=0 && vi2>=0);
01514     tri::Allocator<MeshType>::AddFace(*regionVec[vi0], m.face[i].cP(0),m.face[i].cP(1),m.face[i].cP(2));
01515 
01516     if(vi1 != vi0)
01517       tri::Allocator<MeshType>::AddFace(*regionVec[vi1], m.face[i].cP(0),m.face[i].cP(1),m.face[i].cP(2));
01518 
01519     if((vi2 != vi0) && (vi2 != vi1) )
01520       tri::Allocator<MeshType>::AddFace(*regionVec[vi2], m.face[i].cP(0),m.face[i].cP(1),m.face[i].cP(2));
01521   }
01522 
01523   bool AllDiskRegion=true;
01524   for(size_t i=0; i< seedVec.size();i++)
01525   {
01526     MeshType &rm = *(regionVec[i]);
01527     tri::Clean<MeshType>::RemoveDuplicateVertex(rm);
01528     tri::Allocator<MeshType>::CompactEveryVector(rm);
01529     tri::UpdateTopology<MeshType>::FaceFace(rm);
01530     //    char buf[100]; sprintf(buf,"disk%04i.ply",i); tri::io::ExporterPLY<MeshType>::Save(rm,buf,tri::io::Mask::IOM_VERTCOLOR + tri::io::Mask::IOM_VERTQUALITY );
01531 
01532     int NNmanifoldE=tri::Clean<MeshType>::CountNonManifoldEdgeFF(rm);
01533     if (NNmanifoldE!=0)
01534       AllDiskRegion= false;
01535     int G=tri::Clean<MeshType>::MeshGenus(rm);
01536     int numholes=tri::Clean<MeshType>::CountHoles(rm);
01537     if (numholes!=1)
01538       AllDiskRegion= false;
01539     if(G!=0) AllDiskRegion= false;
01540     delete regionVec[i];
01541   }
01542 
01543   if(!AllDiskRegion) return false;
01544 
01545   // **** Final step build a rough delaunay tri and check that it is manifold
01546   MeshType delaMesh;
01547   std::vector<FacePointer> innerCornerVec,   // Faces adjacent to three different regions
01548       borderCornerVec;  // Faces that are on the border and adjacent to at least two regions.
01549   GetFaceCornerVec(m, sources, innerCornerVec, borderCornerVec);
01550 
01551   // First add all the needed vertices: seeds and corners
01552   for(size_t i=0;i<seedVec.size();++i)
01553     tri::Allocator<MeshType>::AddVertex(delaMesh, seedVec[i]->P());
01554 
01555   // Now just add one face for each inner corner
01556   for(size_t i=0;i<innerCornerVec.size();++i)
01557   {
01558     VertexPointer v0 = & delaMesh.vert[seedMap[sources[innerCornerVec[i]->V(0)]]];
01559     VertexPointer v1 = & delaMesh.vert[seedMap[sources[innerCornerVec[i]->V(1)]]];
01560     VertexPointer v2 = & delaMesh.vert[seedMap[sources[innerCornerVec[i]->V(2)]]];
01561     tri::Allocator<MeshType>::AddFace(delaMesh,v0,v1,v2);
01562   }
01563   Clean<MeshType>::RemoveUnreferencedVertex(delaMesh);
01564   tri::Allocator<MeshType>::CompactVertexVector(delaMesh);
01565   tri::UpdateTopology<MeshType>::FaceFace(delaMesh);
01566 
01567   int nonManif = tri::Clean<MeshType>::CountNonManifoldEdgeFF(delaMesh);
01568   if(nonManif>0) return false;
01569 
01570   return true;
01571 }
01572 
01573 static void BuildSeedMap(MeshType &m, std::vector<VertexType *> &seedVec,  std::map<VertexPointer, int> &seedMap)
01574 {
01575   seedMap.clear();
01576   for(size_t i=0;i<m.vert.size();++i)
01577     seedMap[&(m.vert[i])]=-1;
01578   for(size_t i=0;i<seedVec.size();++i)
01579     seedMap[seedVec[i]]=i;
01580   for(size_t i=0;i<seedVec.size();++i)
01581     assert(tri::Index(m,seedVec[i])>=0 && tri::Index(m,seedVec[i])<size_t(m.vn));
01582 }
01583 
01594 static void ConvertDelaunayTriangulationToMesh(MeshType &m,
01595                                                MeshType &outMesh,
01596                                                std::vector<VertexType *> &seedVec, bool refineFlag=true)
01597 {
01598   tri::RequirePerVertexAttribute(m,"sources");
01599   tri::RequireCompactness(m);
01600   tri::RequireVFAdjacency(m);
01601 
01602   PerVertexPointerHandle sources = tri::Allocator<MeshType>:: template GetPerVertexAttribute<VertexPointer> (m,"sources");
01603 
01604   outMesh.Clear();
01605   tri::UpdateTopology<MeshType>::FaceFace(m);
01606   tri::UpdateFlags<MeshType>::FaceBorderFromFF(m);
01607 
01608   std::map<VertexPointer, int> seedMap;  // It says if a given vertex of m is a seed (and its index in seedVec)
01609   BuildSeedMap(m,seedVec,seedMap);
01610 
01611   std::vector<FacePointer> innerCornerVec,   // Faces adjacent to three different regions
01612       borderCornerVec;  // Faces that are on the border and adjacent to at least two regions.
01613   GetFaceCornerVec(m, sources, innerCornerVec, borderCornerVec);
01614 
01615   // First add all the needed vertices: seeds and corners
01616   for(size_t i=0;i<seedVec.size();++i)
01617     tri::Allocator<MeshType>::AddVertex(outMesh, seedVec[i]->P(),Color4b::White);
01618 
01619   map<std::pair<VertexPointer,VertexPointer>, int > midMapInd;
01620 
01621   // Given a pair of sources gives the index of the mid vertex
01622   map<std::pair<VertexPointer,VertexPointer>, VertexPointer > midMapPt;
01623   if(refineFlag)
01624   {
01625     GenerateMidPointMap(m, midMapPt);
01626     typename std::map<std::pair<VertexPointer,VertexPointer>, VertexPointer >::iterator mi;
01627     for(mi=midMapPt.begin(); mi!=midMapPt.end(); ++mi)
01628     {
01629       midMapInd[ordered_pair(mi->first.first, mi->first.second)]=outMesh.vert.size();
01630       tri::Allocator<MeshType>::AddVertex(outMesh, mi->second->cP(), Color4b::LightBlue);
01631     }
01632   }
01633 
01634   // Now just add one (or four) face for each inner corner
01635   for(size_t i=0;i<innerCornerVec.size();++i)
01636   {
01637     VertexPointer s0 = sources[innerCornerVec[i]->V(0)];
01638     VertexPointer s1 = sources[innerCornerVec[i]->V(1)];
01639     VertexPointer s2 = sources[innerCornerVec[i]->V(2)];
01640     assert ( (s0!=s1) && (s0!=s2) && (s1!=s2) );
01641     VertexPointer v0 = & outMesh.vert[seedMap[s0]];
01642     VertexPointer v1 = & outMesh.vert[seedMap[s1]];
01643     VertexPointer v2 = & outMesh.vert[seedMap[s2]];
01644     if(refineFlag)
01645     {
01646       VertexPointer mp01 =  & outMesh.vert[ midMapInd[ordered_pair(s0,s1)]];
01647       VertexPointer mp02 =  & outMesh.vert[ midMapInd[ordered_pair(s0,s2)]];
01648       VertexPointer mp12 =  & outMesh.vert[ midMapInd[ordered_pair(s1,s2)]];
01649       assert ( (mp01!=mp02) && (mp01!=mp12) && (mp02!=mp12) );
01650       tri::Allocator<MeshType>::AddFace(outMesh,v0,mp01,mp02);
01651       tri::Allocator<MeshType>::AddFace(outMesh,v1,mp12,mp01);
01652       tri::Allocator<MeshType>::AddFace(outMesh,v2,mp02,mp12);
01653       tri::Allocator<MeshType>::AddFace(outMesh,mp01,mp12,mp02);
01654     }
01655      else
01656       tri::Allocator<MeshType>::AddFace(outMesh,v0,v1,v2);
01657   }
01658   Clean<MeshType>::RemoveUnreferencedVertex(outMesh);
01659   tri::Allocator<MeshType>::CompactVertexVector(outMesh);
01660 }
01661 
01662 template <class MidPointType >
01663 static void PreprocessForVoronoi(MeshType &m, ScalarType radius,
01664                                  MidPointType mid,
01665                                  VoronoiProcessingParameter &vpp)
01666 {
01667   const int maxSubDiv = 10;
01668   tri::RequireFFAdjacency(m);
01669   tri::UpdateTopology<MeshType>::FaceFace(m);
01670   tri::Clean<MeshType>::RemoveUnreferencedVertex(m);
01671   ScalarType edgeLen = tri::Stat<MeshType>::ComputeFaceEdgeLengthAverage(m);
01672 
01673   for(int i=0;i<maxSubDiv;++i)
01674   {
01675     bool ret = tri::Refine<MeshType, MidPointType >(m,mid,min(edgeLen*2.0f,radius/vpp.refinementRatio));
01676     if(!ret) break;
01677   }
01678   tri::Allocator<MeshType>::CompactEveryVector(m);
01679   tri::UpdateTopology<MeshType>::VertexFace(m);
01680 }
01681 
01682 static void PreprocessForVoronoi(MeshType &m, float radius, VoronoiProcessingParameter &vpp)
01683 {
01684   tri::MidPoint<MeshType> mid(&m);
01685   PreprocessForVoronoi<tri::MidPoint<MeshType> >(m, radius,mid,vpp);
01686 }
01687 
01688 static void RelaxRefineTriangulationSpring(MeshType &m, MeshType &delaMesh, int relaxStep=10, int refineStep=3 )
01689 {
01690   tri::RequireCompactness(m);
01691   tri::RequireCompactness(delaMesh);
01692   tri::RequireVFAdjacency(delaMesh);
01693   tri::RequireFFAdjacency(delaMesh);
01694   tri::RequirePerFaceMark(delaMesh);
01695 
01696   const float convergenceThr = 0.001f;
01697   const float eulerStep = 0.1f;
01698 
01699   tri::UpdateNormal<MeshType>::PerVertexNormalizedPerFaceNormalized(m);
01700 
01701   typedef GridStaticPtr<FaceType, ScalarType> TriMeshGrid;
01702   TriMeshGrid ug;
01703   ug.Set(m.face.begin(),m.face.end());
01704 
01705   typedef typename vcg::SpatialHashTable<VertexType, ScalarType> HashVertexGrid;
01706   HashVertexGrid HG;
01707   HG.Set(m.vert.begin(),m.vert.end());
01708 
01709   PerVertexBoolHandle fixed = tri::Allocator<MeshType>:: template GetPerVertexAttribute<bool> (m,"fixed");
01710 
01711   const ScalarType maxDist = m.bbox.Diag()/4.f;
01712   for(int kk=0;kk<refineStep+1;kk++)
01713   {
01714     tri::UpdateTopology<MeshType>::FaceFace(delaMesh);
01715 
01716     if(kk!=0) // first step do not refine;
01717     {
01718       int nonManif = tri::Clean<MeshType>::CountNonManifoldEdgeFF(delaMesh);
01719       if(nonManif) return;
01720       tri::Refine<MeshType, tri::MidPoint<MeshType> >(delaMesh,tri::MidPoint<MeshType>(&delaMesh));
01721     }
01722     tri::UpdateTopology<MeshType>::VertexFace(delaMesh);
01723     const float dist_upper_bound=m.bbox.Diag()/10.0;
01724     float dist;
01725 
01726     for(int k=0;k<relaxStep;k++) 
01727     {
01728       std::vector<Point3f> avgForce(delaMesh.vn);
01729       std::vector<float> avgLenVec(delaMesh.vn,0);
01730       for(int i=0;i<delaMesh.vn;++i)
01731       {
01732         vector<VertexPointer> starVec;
01733         face::VVStarVF<FaceType>(&delaMesh.vert[i],starVec);
01734 
01735         for(size_t j=0;j<starVec.size();++j)
01736           avgLenVec[i] +=Distance(delaMesh.vert[i].cP(),starVec[j]->cP());
01737         avgLenVec[i] /= float(starVec.size());
01738 
01739         avgForce[i] =Point3f(0,0,0);
01740         for(size_t j=0;j<starVec.size();++j)
01741         {
01742           Point3f force = delaMesh.vert[i].cP()-starVec[j]->cP();
01743           float len = force.Norm();
01744           force.Normalize();
01745           avgForce[i] += force * (avgLenVec[i]-len);
01746         }
01747       }
01748       bool changed=false;
01749       for(int i=0;i<delaMesh.vn;++i)
01750       {
01751         VertexPointer vp = tri::GetClosestVertex<MeshType,HashVertexGrid>(m, HG, delaMesh.vert[i].P(), dist_upper_bound, dist);
01752         if(!fixed[vp] && !(vp->IsS())) // update only non fixed vertices
01753         {
01754           delaMesh.vert[i].P() += (avgForce[i]*eulerStep);
01755           CoordType closest;
01756           float dist;
01757           tri::GetClosestFaceBase(m,ug,delaMesh.vert[i].cP(), maxDist,dist,closest);
01758           assert(dist!=maxDist);
01759           if(Distance(closest,delaMesh.vert[i].P()) > avgLenVec[i]*convergenceThr) changed = true;
01760           delaMesh.vert[i].P()=closest;
01761         }
01762       }
01763 
01764       if(!changed) k=relaxStep;
01765     } // end for k
01766   }
01767 }
01768 
01769 static void RelaxRefineTriangulationLaplacian(MeshType &m, MeshType &delaMesh, int refineStep=3, int relaxStep=10 )
01770 {
01771   tri::RequireCompactness(m);
01772   tri::RequireCompactness(delaMesh);
01773   tri::RequireFFAdjacency(delaMesh);
01774   tri::RequirePerFaceMark(delaMesh);
01775   tri::UpdateTopology<MeshType>::FaceFace(delaMesh);
01776 
01777   typedef GridStaticPtr<FaceType, ScalarType> TriMeshGrid;
01778   TriMeshGrid ug;
01779   ug.Set(m.face.begin(),m.face.end());
01780   const ScalarType maxDist = m.bbox.Diag()/4.f;
01781 
01782   int origVertNum = delaMesh.vn;
01783 
01784   for(int k=0;k<refineStep;++k)
01785   {
01786     tri::UpdateSelection<MeshType>::VertexClear(delaMesh);
01787 
01788     tri::Refine<MeshType, tri::MidPoint<MeshType> >(delaMesh,tri::MidPoint<MeshType>(&delaMesh));
01789 
01790     for(int j=0;j<relaxStep;++j)
01791     {
01792 //      tri::Smooth<MeshType>::VertexCoordLaplacian(delaMesh,1,true);
01793       for(int i=origVertNum;i<delaMesh.vn;++i)
01794       {
01795         float dist;
01796         delaMesh.vert[i].SetS();
01797         CoordType closest;
01798         tri::GetClosestFaceBase(m,ug,delaMesh.vert[i].cP(), maxDist,dist,closest);
01799         assert(dist!=maxDist);
01800         delaMesh.vert[i].P()= (delaMesh.vert[i].P()+closest)/2.0f;
01801       }
01802       tri::Smooth<MeshType>::VertexCoordLaplacianBlend(delaMesh,1,0.2f,true);
01803     }
01804   }
01805   for(int i=origVertNum;i<delaMesh.vn;++i) delaMesh.vert[i].C()=Color4b::LightBlue;
01806 }
01807 }; // end class VoronoiProcessing
01808 
01809 } // end namespace tri
01810 } // end namespace vcg
01811 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:38:44