diff --git a/vcg/complex/algorithms/create/advancing_front.h b/vcg/complex/algorithms/create/advancing_front.h index e5d1fb3f..070b97f9 100644 --- a/vcg/complex/algorithms/create/advancing_front.h +++ b/vcg/complex/algorithms/create/advancing_front.h @@ -6,7 +6,6 @@ #include #include #include -#include namespace vcg { namespace tri { diff --git a/vcg/complex/algorithms/create/ball_pivoting.h b/vcg/complex/algorithms/create/ball_pivoting.h index b7e36d35..c6584b1f 100644 --- a/vcg/complex/algorithms/create/ball_pivoting.h +++ b/vcg/complex/algorithms/create/ball_pivoting.h @@ -2,7 +2,8 @@ #define BALL_PIVOTING_H #include "advancing_front.h" -#include +#include + #include /* Ball pivoting algorithm: @@ -22,15 +23,13 @@ template class BallPivoting: public AdvancingFront { typedef typename MESH::ScalarType ScalarType; typedef typename MESH::VertexIterator VertexIterator; typedef typename MESH::VertexType::CoordType Point3x; - typedef GridStaticPtr StaticGrid; - + float radius; //radius of the ball float min_edge; //min length of an edge float max_edge; //min length of an edge float max_angle; //max angle between 2 faces (cos(angle) actually) public: - ScalarType radi() { return radius; } // if radius ==0 an autoguess for the ball pivoting radius is attempted // otherwise the passed value (in absolute mesh units) is used. @@ -58,57 +57,49 @@ template class BallPivoting: public AdvancingFront { min_edge *= radius; max_edge *= radius; - //enlarging the bbox for out-of-box queries - Box3 BPbbox=this->mesh.bbox; - BPbbox.Offset(4*radius); - grid.Set(this->mesh.vert.begin(), this->mesh.vert.end(), BPbbox); - - //mark visited points - std::vector targets; - std::vector points; - std::vector dists; + VertexConstDataWrapper ww(this->mesh); + tree = new KdTree(ww); + tree->setMaxNofNeighbors(16); usedBit = VertexType::NewBitFlag(); - for(int i = 0; i < (int)this->mesh.vert.size(); i++) - this->mesh.vert[i].ClearUserBit(usedBit); - + UpdateFlags::VertexClear(this->mesh,usedBit); UpdateFlags::VertexClearV(this->mesh); for(int i = 0; i < (int)this->mesh.face.size(); i++) { FaceType &f = this->mesh.face[i]; if(f.IsD()) continue; for(int k = 0; k < 3; k++) { - f.V(k)->SetV(); - int n = tri::GetInSphereVertex(this->mesh, grid, f.V(k)->P(), min_edge, targets, dists, points); - for(int t = 0; t < n; t++) { - targets[t]->SetUserBit(usedBit); - assert(targets[t]->IsUserBit(usedBit)); - } - assert(f.V(k)->IsUserBit(usedBit)); + Mark(f.V(k)); } } } ~BallPivoting() { VertexType::DeleteBitFlag(usedBit); + delete tree; } bool Seed(int &v0, int &v1, int &v2) { //get a sphere of neighbours std::vector targets; - std::vector points; - std::vector dists; while(++last_seed < (int)(this->mesh.vert.size())) { VertexType &seed = this->mesh.vert[last_seed]; if(seed.IsD() || seed.IsUserBit(usedBit)) continue; seed.SetUserBit(usedBit); - int n = tri::GetInSphereVertex(this->mesh, grid, seed.P(), 2*radius, targets, dists, points); - if(n < 3) { - continue; - } - + tree->doQueryK(seed.P()); + int nn = tree->getNofFoundNeighbors(); + for(int i=0;imesh.vert[tree->getNeighborId(i)]; + if(Distance(seed.P(),vp->cP()) > 2*radius) continue; + targets.push_back(vp); + } + + int n = targets.size(); + if(n<3) continue; + bool success = true; //find the closest visited or boundary for(int i = 0; i < n; i++) { @@ -229,26 +220,22 @@ template class BallPivoting: public AdvancingFront { // r is the radius of the thorus of all possible spheres passing throug v0 and v1 ScalarType r = sqrt(radius*radius - axis_len/4); + - std::vector targets; // The vector of - std::vector dists; // never used. - std::vector points; // never used. - - tri::GetInSphereVertex(this->mesh, grid, middle, r + radius, targets, dists, points); - - if(targets.size() == 0) { - return -1; //this really would be strange but one never knows. - } + tree->doQueryK(middle); + int nn = tree->getNofFoundNeighbors(); + if(nn==0) return -1; VertexType *candidate = NULL; ScalarType min_angle = M_PI; // // Loop over all the nearest vertexes and choose the best one according the ball pivoting strategy. // - for(size_t i = 0; i < targets.size(); i++) { - VertexType *v = targets[i]; - if(v->IsD()) continue; - int vInd = tri::Index(this->mesh,v); + for (int i = 0; i < nn; i++) { + int vInd = tree->getNeighborId(i); + VertexType *v = &this->mesh.vert[vInd]; + if(Distance(middle,v->cP()) > r + radius) continue; + // this should always be true IsB => IsV , IsV => IsU if(v->IsB()) assert(v->IsV()); if(v->IsV()) assert(v->IsUserBit(usedBit)); @@ -334,10 +321,9 @@ template class BallPivoting: public AdvancingFront { private: int last_seed; //used for new seeds when front is empty int usedBit; //use to detect if a vertex has been already processed. - Point3x baricenter;//used for the first seed. - - StaticGrid grid; //lookup grid for points - + Point3x baricenter;//used for the first seed. + KdTree *tree; + /* returns the sphere touching p0, p1, p2 of radius r such that the normal of the face points toward the center of the sphere */ @@ -404,12 +390,13 @@ template class BallPivoting: public AdvancingFront { } void Mark(VertexType *v) { - std::vector targets; - std::vector points; - std::vector dists; - int n = tri::GetInSphereVertex(this->mesh, grid, v->P(), min_edge, targets, dists, points); - for(int t = 0; t < n; t++) - targets[t]->SetUserBit(usedBit); + tree->doQueryK(v->cP()); + int n = tree->getNofFoundNeighbors(); + for (int i = 0; i < n; i++) { + VertexType *vp = &this->mesh.vert[tree->getNeighborId(i)]; + if(Distance(v->cP(),vp->cP())SetUserBit(usedBit); + } v->SetV(); } };