From 4e1b6897b13bd428623a88e8643a6620ac2194f5 Mon Sep 17 00:00:00 2001 From: cnr-isti-vclab Date: Tue, 28 Jul 2009 23:07:26 +0000 Subject: [PATCH] class that provides an estimation of the overlap of two meshes. It works as follow: it samples N points in a normal equalized manner on the Mov mesh, then count how many points of the Fix mesh are in consensus with the sampled points. To be in consensus means: distance between points is <= param.consensusDistance AND the angle between points normals is <= param.normalAngle. This works for point clouds too. comments will be added in next commit. --- vcg/complex/trimesh/overlap_estimation.h | 264 +++++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 vcg/complex/trimesh/overlap_estimation.h diff --git a/vcg/complex/trimesh/overlap_estimation.h b/vcg/complex/trimesh/overlap_estimation.h new file mode 100644 index 00000000..7fd4b115 --- /dev/null +++ b/vcg/complex/trimesh/overlap_estimation.h @@ -0,0 +1,264 @@ +#ifndef OVERLAP_ESTIMATION_H +#define OVERLAP_ESTIMATION_H + +#include +#include +//#include +#include +#include +#include +//#include + +#include + +using namespace std; +using namespace vcg; + + +template class OverlapEstimation +{ + public: + + typedef MESH_TYPE MeshType; + typedef typename MeshType::ScalarType ScalarType; + typedef typename MeshType::CoordType CoordType; + typedef typename MeshType::VertexType VertexType; + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::VertexPointer VertexPointer; + typedef typename MeshType::VertexIterator VertexIterator; + typedef typename vector::iterator VertexPointerIterator; + typedef GridStaticPtr MeshGrid; + typedef tri::VertTmark MarkerVertex; + + private: + class VertexPointerSampler + { + public: + + MeshType* m; //this is needed for advanced sampling (i.e poisson sampling) + + VertexPointerSampler(){ m = new MeshType(); m->Tr.SetIdentity(); m->sfn=0; } + ~VertexPointerSampler(){ if(m) delete m; } + vector sampleVec; + + void AddVert(VertexType &p){ sampleVec.push_back(&p); } + + void AddFace(const FaceType &f, const CoordType &p){} + + void AddTextureSample(const FaceType &, const CoordType &, const Point2i &){} + }; + + public: + class Parameters + { + public: + int samples; //number of samples + int bestScore; //used to paint mMove: paint only if is a best score + float consensusDist; //consensus distance + float consensusNormalsAngle; //holds the the consensus angle for normals, in gradients. + float threshold; //consensus % to win consensus; + bool normalEqualization; //to use normal equalization in consensus + bool paint; //to paint mMov according to consensus + void (*log)(int level, const char * f, ... ); //pointer to log function + + Parameters() + { + samples = 2500; + bestScore = 0; + consensusDist = 2.0f; + consensusNormalsAngle = 0.965f; //15 degrees. + threshold = 0.0f; + normalEqualization = true; + paint = false; + log = NULL; + } + }; + + MeshType* mFix, *mMov; + vector >* normBuckets; //structure to hold normals bucketing. Needed for normal equalized sampling during consensus + MeshGrid* gridFix; //variable to manage uniform grid + MarkerVertex markerFunctorFix; //variable to manage uniform grid + + OverlapEstimation() : normBuckets(NULL), gridFix(NULL){} + ~OverlapEstimation(){ + if(normBuckets) delete normBuckets; + if(gridFix) delete gridFix; + } + + void SetFix(MeshType& m){ mFix = &m; } + + void SetMove(MeshType& m){ mMov = &m; } + + void Paint() + { + for(VertexIterator vi=mMov->vert.begin(); vi!=mMov->vert.end(); vi++){ + if(!(*vi).IsD()){ + if((*vi).Q()==0.0) (*vi).C() = Color4b::Red; + if((*vi).Q()==1.0) (*vi).C() = Color4b::Yellow; + if((*vi).Q()==2.0) (*vi).C() = Color4b::Blue; + } + } + } + + bool Init(Parameters& param){ + //builds the uniform grid with mFix vertices + gridFix = new MeshGrid(); + SetupGrid(); + + //if requested, group normals of mMov into 30 buckets. Buckets are used for Vertex Normal Equalization + //in consensus. Bucketing is done here once for all to speed up consensus. + if(normBuckets) {normBuckets->clear(); delete normBuckets; } + if(param.normalEqualization){ + normBuckets = BucketVertexNormal(mMov->vert, 30); + assert(normBuckets); + } + return true; + } + + float Compute(Parameters& param) + { + return Check(param)/float(param.samples); + } + + //compute the randomized consensus beetween m1 e m2 (without taking in account any additional transformation) + //IMPORTANT: per vertex normals of m1 and m2 MUST BE PROVIDED JET NORMALIZED!!! + int Check(Parameters& param) + { + //pointer to a function to compute distance beetween points + vertex::PointDistanceFunctor PDistFunct; + + //if no buckets are provided get a vector of vertex pointers sampled uniformly + //else, get a vector of vertex pointers sampled in a normal equalized manner; used as query points + vector queryVert; + if(param.normalEqualization){ + assert(normBuckets); + for(unsigned int i=0; ivert.size(); i++) queryVert.push_back(&(mMov->vert[i]));//do a copy of pointers to vertexes + SampleVertNormalEqualized(queryVert, param.samples); + } + else{ + SampleVertUniform(*mMov, queryVert, param.samples); + } + assert(queryVert.size()!=0); + + //init variables for consensus + float consDist = param.consensusDist*(mMov->bbox.Diag()/100.0f); //consensus distance + int cons_succ = int(param.threshold*(param.samples/100.0f)); //score needed to pass consensus + int consensus = 0; //counts vertices in consensus + float dist; //holds the distance of the closest vertex found + VertexType* closestVertex = NULL; //pointer to the closest vertex + Point3 queryNrm; //the query point normal for consensus + CoordType queryPnt; //the query point for consensus + CoordType closestPnt; //the closest point found in consensus + Matrix33 inv33_matMov(mMov->Tr,3); //3x3 matrix needed to transform normals + Matrix33 inv33_matFix(Inverse(mFix->Tr),3); //3x3 matrix needed to transform normals + + //consensus loop + VertexPointerIterator vi; int i; + for(i=0, vi=queryVert.begin(); vi!=queryVert.end(); vi++, i++) + { + dist = -1.0f; + //set query point; vertex coord is transformed properly in fix mesh coordinates space; the same for normals + queryPnt = Inverse(mFix->Tr) * (mMov->Tr * (*vi)->P()); + queryNrm = inv33_matFix * (inv33_matMov * (*vi)->N()); + //if query point is bbox, the look for a vertex in cDist from the query point + if(mFix->bbox.IsIn(queryPnt)) closestVertex = gridFix->GetClosest(PDistFunct,markerFunctorFix,queryPnt,consDist,dist,closestPnt); + else closestVertex=NULL; //out of bbox, we consider the point not in consensus... + + if(closestVertex!=NULL && dist < consDist){ + assert(closestVertex->P()==closestPnt); //coord and vertex pointer returned by getClosest must be the same + + //point is in consensus distance, now we check if normals are near + if(queryNrm.dot(closestVertex->N())>param.consensusNormalsAngle) //15 degrees + { + consensus++; //got consensus + if(param.paint) (*vi)->Q() = 0.0f; //store 0 as quality + } + else{ + if(param.paint) (*vi)->Q() = 1.0f; //store 1 as quality + } + } + else{ + if(param.paint) (*vi)->Q() = 2.0f; //store 2 as quality + } + } + + //apply colors if consensus is the best ever found. + //NOTE: we got to do this here becouse we need a handle to sampler. This is becouse vertex have been shuffled + //and so colors have been stored not in order in the buffer! + if(param.paint){ + if(consensus>=param.bestScore && consensus>=cons_succ) Paint(); + } + + return consensus; + } + + private: + + void SampleVertUniform(MESH_TYPE& m, vector& vert, int sampleNum) + { + VertexPointerSampler sampler; + tri::SurfaceSampling::VertexUniform(m, sampler, sampleNum); + for(unsigned int i=0; i >* BucketVertexNormal(typename MESH_TYPE::VertContainer& vert, int bucketDim = 30) + { + static vector NV; + if(NV.size()==0) GenNormal::Uniform(bucketDim,NV); + + // Bucket vector dove, per ogni normale metto gli indici + // dei vertici ad essa corrispondenti + vector >* BKT = new vector >(NV.size()); //NV size is greater then bucketDim, so don't change this! + + int ind; + for(int i=0;i::BestMatchingNormal(vert[i].N(),NV); + (*BKT)[ind].push_back(i); + } + + return BKT; + } + + bool SampleVertNormalEqualized(vector& vert, int SampleNum) + { + assert(normBuckets); + // vettore di contatori per sapere quanti punti ho gia' preso per ogni bucket + vector BKTpos(normBuckets->size(),0); + + if(SampleNum >= int(vert.size())) SampleNum= int(vert.size()-1); + + int ind; + for(int i=0;isize()); // Scelgo un Bucket + int &CURpos = BKTpos[ind]; + vector &CUR = (*normBuckets)[ind]; + + if(CURposSet(mFix->vert.begin(),mFix->vert.end()); + markerFunctorFix.SetMesh(mFix); + } +}; + +#endif // OVERLAP_ESTIMATION_H