From 511f4053c912bff31625088d98429aec75302d4d Mon Sep 17 00:00:00 2001 From: ponchio Date: Fri, 1 Jun 2007 09:07:23 +0000 Subject: [PATCH] *** empty log message *** --- vcg/complex/trimesh/create/advancing_front.h | 74 ++++++++++--------- vcg/complex/trimesh/create/ball_pivoting.h | 77 +++++++++++++++----- 2 files changed, 97 insertions(+), 54 deletions(-) diff --git a/vcg/complex/trimesh/create/advancing_front.h b/vcg/complex/trimesh/create/advancing_front.h index 9efa59f7..d19daf01 100644 --- a/vcg/complex/trimesh/create/advancing_front.h +++ b/vcg/complex/trimesh/create/advancing_front.h @@ -50,9 +50,10 @@ template class AdvancingFront { MESH &mesh; //this structure will be filled by the algorithm AdvancingFront(MESH &_mesh): mesh(_mesh) { +// UpdateFlags::VertexClear(mesh); + UpdateFlags::Clear(mesh); // UpdateTopology::VertexFace(mesh); //UpdateTopology::TestVertexFace(mesh); //odd i would like to return a false not an assert... - UpdateFlags::VertexClear(mesh); // UpdateFlags::FaceBorderFromVF(mesh); UpdateFlags::FaceBorderFromNone(mesh); UpdateFlags::VertexBorderFromFace(mesh); @@ -63,6 +64,7 @@ template class AdvancingFront { CreateLoops(); } virtual ~AdvancingFront() {} + virtual ScalarType radi() { return 0; } void BuildMesh(CallBackPos call = NULL, int interval = 512) { while(1) { @@ -110,8 +112,7 @@ protected: if(f.IsB(k)) { NewEdge(FrontEdge(f.V0(k) - start, f.V1(k) - start, f.V2(k) - start, i)); nb[f.V0(k)-start]++; - } - + } } } @@ -126,10 +127,14 @@ protected: if((*s).v1 != (*j).v0) continue; if((*j).previous != front.end()) continue; (*s).next = j; - (*j).previous = s; - + (*j).previous = s; + break; } } + for(std::list::iterator s = front.begin(); s != front.end(); s++) { + assert((*s).next != front.end()); + assert((*s).previous != front.end()); + } } bool SeedFace() { @@ -171,7 +176,6 @@ protected: public: bool AddFace() { - if(!front.size()) { return SeedFace(); } @@ -185,7 +189,6 @@ public: assert(nb[v0] < 10 && nb[v1] < 10); std::list::iterator touch = front.end(); - int v2 = Place(current, touch); if(v2 == -1) { KillEdge(ei); @@ -195,15 +198,15 @@ public: assert(v2 != v0 && v2 != v1); if(touch != front.end()) { - //check for orientation and manifoldness - if(!CheckEdge(v0, v2) || !CheckEdge(v2, v1)) { - KillEdge(ei); - return 0; - } + //if(!CheckEdge(v0, v2) || !CheckEdge(v2, v1)) { + //touch == current.previous? if(v2 == previous.v0) { - + if(!CheckEdge(v2, v1)) { + KillEdge(ei); + return 0; + } /*touching previous FrontEdge (we reuse previous) next ------->v2 -----> v1------> @@ -224,11 +227,13 @@ public: Erase(current.previous); Erase(ei); Glue(up); - + //touch == (*current.next).next - } else if(v2 == next.v1) { - - + } else if(v2 == next.v1) { + if(!CheckEdge(v0, v2)) { + KillEdge(ei); + return 0; + } /*touching next FrontEdge (we reuse next) previous ------->v0 -----> v2------> @@ -248,9 +253,11 @@ public: Erase(current.next); Erase(ei); Glue(up); - } else { - + if(!CheckEdge(v0, v2) || !CheckEdge(v2, v1)) { + KillEdge(ei); + return 0; + } //touching some loop: split (or merge it is local does not matter. //like this /* @@ -293,7 +300,8 @@ public: } else { - + assert(CheckEdge(v0, v2)); + assert(CheckEdge(v2, v1)); /* adding a new vertex v2 @@ -304,26 +312,21 @@ public: / V ----v0 - - - > v1--------- */ assert(!mesh.vert[v2].IsB()); //fatal error! a new point is already a border? - nb[v2]++; mesh.vert[v2].SetB(); - + std::list::iterator down = NewEdge(FrontEdge(v2, v1, v0, mesh.face.size())); std::list::iterator up = NewEdge(FrontEdge(v0, v2, v1, mesh.face.size())); - (*down).previous = up; (*up).next = down; - (*down).next = current.next; next.previous = down; - (*up).previous = current.previous; previous.next = up; - Erase(ei); } - + AddFace(v0, v2, v1); return 1; } @@ -360,17 +363,18 @@ protected: bool CheckEdge(int v0, int v1) { int tot = 0; //HACK to speed up things until i can use a seach structure - int i = mesh.face.size() - 4*(front.size()); +/* int i = mesh.face.size() - 4*(front.size()); if(front.size() < 100) i = mesh.face.size() - 100; - // i = 0; - if(i < 0) i = 0; - for(; i < (int)mesh.face.size(); i++) { + if(i < 0) i = 0;*/ + VertexType *vv0 = &(mesh.vert[v0]); + VertexType *vv1 = &(mesh.vert[v1]); + + for(int i = 0; i < (int)mesh.face.size(); i++) { FaceType &f = mesh.face[i]; for(int k = 0; k < 3; k++) { - if(v1== (int)f.V(k) && v0 == (int)f.V((k+1)%3)) ++tot; - else if(v0 == (int)f.V(k) && v1 == (int)f.V((k+1)%3)) { //orientation non constistent - return false; - } + if(vv0 == f.V0(k) && vv1 == f.V1(k)) //orientation non constistent + return false; + else if(vv1 == f.V0(k) && vv0 == f.V1(k)) ++tot; } if(tot >= 2) { //non manifold return false; diff --git a/vcg/complex/trimesh/create/ball_pivoting.h b/vcg/complex/trimesh/create/ball_pivoting.h index fdbf6d28..bd5cf442 100644 --- a/vcg/complex/trimesh/create/ball_pivoting.h +++ b/vcg/complex/trimesh/create/ball_pivoting.h @@ -29,6 +29,7 @@ template class BallPivoting: public AdvancingFront { float max_angle; //max angle between 2 faces (cos(angle) actually) public: + ScalarType radi() { return radius; } BallPivoting(MESH &_mesh, float _radius = 0, float minr = 0.2, float angle = M_PI/2): @@ -37,8 +38,15 @@ template class BallPivoting: public AdvancingFront { last_seed(-1) { //compute bbox - for(int i = 0; i < (int)this->mesh.vert.size(); i++) - this->mesh.bbox.Add(this->mesh.vert[i].P()); + baricenter = Point3x(0, 0, 0); + int count = 0; + this->mesh.bbox = Box3(); + for(int i = 0; i < (int)this->mesh.vert.size(); i++) { + VertexType &v = this->mesh.vert[i]; + if(v.IsD()) continue; + this->mesh.bbox.Add(v.P()); + baricenter += v.P(); + } assert(this->mesh.vn > 3); if(radius == 0) @@ -133,11 +141,12 @@ template class BallPivoting: public AdvancingFront { if(d0 < min_edge || d0 > max_edge) continue; Point3x normal = (p1 - p0)^(p2 - p0); - if(use_normals) { + if(normal * (p0 - baricenter) > 0) continue; +/* if(use_normals) { if(normal * vv0->N() < 0) continue; if(normal * vv1->N() < 0) continue; if(normal * vv2->N() < 0) continue; - } + }*/ if(!FindSphere(p0, p1, p2, center)) { continue; @@ -197,15 +206,20 @@ template class BallPivoting: public AdvancingFront { Point3x normal = ((v1 - v0)^(v2 - v0)).Normalize(); Point3x middle = (v0 + v1)/2; - Point3x center; - - if(!FindSphere(v0, v1, v2, center)) return -1; + Point3x center; + + if(!FindSphere(v0, v1, v2, center)) { +// assert(0); + return -1; + } Point3x start_pivot = center - middle; Point3x axis = (v1 - v0); ScalarType axis_len = axis.SquaredNorm(); - if(axis_len > 4*radius*radius) return false; + if(axis_len > 4*radius*radius) { + return -1; + } axis.Normalize(); // r is the radius of the thorus of all possible spheres passing throug v0 and v1 @@ -218,7 +232,7 @@ template class BallPivoting: public AdvancingFront { int n = trimesh::GetInSphereVertex(this->mesh, grid, middle, r + radius, targets, dists, points); if(targets.size() == 0) { - return false; //this really would be strange but one never knows. + return -1; //this really would be strange but one never knows. } VertexType *candidate = NULL; @@ -268,20 +282,24 @@ template class BallPivoting: public AdvancingFront { min_angle = alpha; } } - if(min_angle >= M_PI - 0.1) return -1; + if(min_angle >= M_PI - 0.1) { + return -1; + } if(candidate == NULL) { return -1; } - assert((candidate->P() - v0).Norm() > min_edge); - assert((candidate->P() - v1).Norm() > min_edge); + if(!candidate->IsB()) { + assert((candidate->P() - v0).Norm() > min_edge); + assert((candidate->P() - v1).Norm() > min_edge); + } int id = candidate - &*this->mesh.vert.begin(); assert(id != edge.v0 && id != edge.v1); Point3x newnormal = ((candidate->P() - v0)^(v1 - v0)).Normalize(); - if(normal * newnormal < max_angle || this->nb[id] >= 2) { - return -1; + if(normal * newnormal < max_angle || this->nb[id] >= 2) { + return -1; } //test if id is in some border (to return touch for(list::iterator k = this->front.begin(); k != this->front.end(); k++) @@ -297,6 +315,7 @@ 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 @@ -305,14 +324,32 @@ template class BallPivoting: public AdvancingFront { the normal of the face points toward the center of the sphere */ bool FindSphere(Point3x &p0, Point3x &p1, Point3x &p2, Point3x ¢er) { - Point3x q1 = p1 - p0; - Point3x q2 = p2 - p0; + //we want p0 to be always the smallest one. + Point3x p[3]; + + if(p0 < p1 && p0 < p2) { + p[0] = p0; + p[1] = p1; + p[2] = p2; + } else if(p1 < p0 && p1 < p2) { + p[0] = p1; + p[1] = p2; + p[2] = p0; + } else { + p[0] = p2; + p[1] = p0; + p[2] = p1; + } + Point3x q1 = p[1] - p[0]; + Point3x q2 = p[2] - p[0]; Point3x up = q1^q2; ScalarType uplen = up.Norm(); //the three points are aligned - if(uplen < 0.001*q1.Norm()*q2.Norm()) return false; + if(uplen < 0.001*q1.Norm()*q2.Norm()) { + return false; + } up /= uplen; @@ -326,10 +363,12 @@ template class BallPivoting: public AdvancingFront { center = q1*l1 + q2*l2; ScalarType circle_r = center.Norm(); - if(circle_r > radius) return false; //need too big a sphere + if(circle_r > radius) { + return false; //need too big a sphere + } ScalarType height = sqrt(radius*radius - circle_r*circle_r); - center += p0 + up*height; + center += p[0] + up*height; return true; }