*** empty log message ***

This commit is contained in:
Federico Ponchio 2007-06-01 09:07:23 +00:00
parent 7823c5dba1
commit 511f4053c9
2 changed files with 97 additions and 54 deletions

View File

@ -50,9 +50,10 @@ template <class MESH> class AdvancingFront {
MESH &mesh; //this structure will be filled by the algorithm MESH &mesh; //this structure will be filled by the algorithm
AdvancingFront(MESH &_mesh): mesh(_mesh) { AdvancingFront(MESH &_mesh): mesh(_mesh) {
// UpdateFlags<MESH>::VertexClear(mesh);
UpdateFlags<MESH>::Clear(mesh);
// UpdateTopology<MESH>::VertexFace(mesh); // UpdateTopology<MESH>::VertexFace(mesh);
//UpdateTopology<MESH>::TestVertexFace(mesh); //odd i would like to return a false not an assert... //UpdateTopology<MESH>::TestVertexFace(mesh); //odd i would like to return a false not an assert...
UpdateFlags<MESH>::VertexClear(mesh);
// UpdateFlags<MESH>::FaceBorderFromVF(mesh); // UpdateFlags<MESH>::FaceBorderFromVF(mesh);
UpdateFlags<MESH>::FaceBorderFromNone(mesh); UpdateFlags<MESH>::FaceBorderFromNone(mesh);
UpdateFlags<MESH>::VertexBorderFromFace(mesh); UpdateFlags<MESH>::VertexBorderFromFace(mesh);
@ -63,6 +64,7 @@ template <class MESH> class AdvancingFront {
CreateLoops(); CreateLoops();
} }
virtual ~AdvancingFront() {} virtual ~AdvancingFront() {}
virtual ScalarType radi() { return 0; }
void BuildMesh(CallBackPos call = NULL, int interval = 512) { void BuildMesh(CallBackPos call = NULL, int interval = 512) {
while(1) { while(1) {
@ -111,7 +113,6 @@ protected:
NewEdge(FrontEdge(f.V0(k) - start, f.V1(k) - start, f.V2(k) - start, i)); NewEdge(FrontEdge(f.V0(k) - start, f.V1(k) - start, f.V2(k) - start, i));
nb[f.V0(k)-start]++; nb[f.V0(k)-start]++;
} }
} }
} }
@ -127,9 +128,13 @@ protected:
if((*j).previous != front.end()) continue; if((*j).previous != front.end()) continue;
(*s).next = j; (*s).next = j;
(*j).previous = s; (*j).previous = s;
break;
} }
} }
for(std::list<FrontEdge>::iterator s = front.begin(); s != front.end(); s++) {
assert((*s).next != front.end());
assert((*s).previous != front.end());
}
} }
bool SeedFace() { bool SeedFace() {
@ -171,7 +176,6 @@ protected:
public: public:
bool AddFace() { bool AddFace() {
if(!front.size()) { if(!front.size()) {
return SeedFace(); return SeedFace();
} }
@ -185,7 +189,6 @@ public:
assert(nb[v0] < 10 && nb[v1] < 10); assert(nb[v0] < 10 && nb[v1] < 10);
std::list<FrontEdge>::iterator touch = front.end(); std::list<FrontEdge>::iterator touch = front.end();
int v2 = Place(current, touch); int v2 = Place(current, touch);
if(v2 == -1) { if(v2 == -1) {
KillEdge(ei); KillEdge(ei);
@ -195,15 +198,15 @@ public:
assert(v2 != v0 && v2 != v1); assert(v2 != v0 && v2 != v1);
if(touch != front.end()) { if(touch != front.end()) {
//check for orientation and manifoldness //check for orientation and manifoldness
if(!CheckEdge(v0, v2) || !CheckEdge(v2, v1)) { //if(!CheckEdge(v0, v2) || !CheckEdge(v2, v1)) {
//touch == current.previous?
if(v2 == previous.v0) {
if(!CheckEdge(v2, v1)) {
KillEdge(ei); KillEdge(ei);
return 0; return 0;
} }
//touch == current.previous?
if(v2 == previous.v0) {
/*touching previous FrontEdge (we reuse previous) /*touching previous FrontEdge (we reuse previous)
next next
------->v2 -----> v1------> ------->v2 -----> v1------>
@ -227,8 +230,10 @@ public:
//touch == (*current.next).next //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) /*touching next FrontEdge (we reuse next)
previous previous
------->v0 -----> v2------> ------->v0 -----> v2------>
@ -248,9 +253,11 @@ public:
Erase(current.next); Erase(current.next);
Erase(ei); Erase(ei);
Glue(up); Glue(up);
} else { } else {
if(!CheckEdge(v0, v2) || !CheckEdge(v2, v1)) {
KillEdge(ei);
return 0;
}
//touching some loop: split (or merge it is local does not matter. //touching some loop: split (or merge it is local does not matter.
//like this //like this
/* /*
@ -293,7 +300,8 @@ public:
} else { } else {
assert(CheckEdge(v0, v2));
assert(CheckEdge(v2, v1));
/* adding a new vertex /* adding a new vertex
v2 v2
@ -304,23 +312,18 @@ public:
/ V / V
----v0 - - - > v1--------- */ ----v0 - - - > v1--------- */
assert(!mesh.vert[v2].IsB()); //fatal error! a new point is already a border? assert(!mesh.vert[v2].IsB()); //fatal error! a new point is already a border?
nb[v2]++; nb[v2]++;
mesh.vert[v2].SetB(); mesh.vert[v2].SetB();
std::list<FrontEdge>::iterator down = NewEdge(FrontEdge(v2, v1, v0, mesh.face.size())); std::list<FrontEdge>::iterator down = NewEdge(FrontEdge(v2, v1, v0, mesh.face.size()));
std::list<FrontEdge>::iterator up = NewEdge(FrontEdge(v0, v2, v1, mesh.face.size())); std::list<FrontEdge>::iterator up = NewEdge(FrontEdge(v0, v2, v1, mesh.face.size()));
(*down).previous = up; (*down).previous = up;
(*up).next = down; (*up).next = down;
(*down).next = current.next; (*down).next = current.next;
next.previous = down; next.previous = down;
(*up).previous = current.previous; (*up).previous = current.previous;
previous.next = up; previous.next = up;
Erase(ei); Erase(ei);
} }
@ -360,17 +363,18 @@ protected:
bool CheckEdge(int v0, int v1) { bool CheckEdge(int v0, int v1) {
int tot = 0; int tot = 0;
//HACK to speed up things until i can use a seach structure //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; if(front.size() < 100) i = mesh.face.size() - 100;
// i = 0; if(i < 0) i = 0;*/
if(i < 0) i = 0; VertexType *vv0 = &(mesh.vert[v0]);
for(; i < (int)mesh.face.size(); i++) { VertexType *vv1 = &(mesh.vert[v1]);
for(int i = 0; i < (int)mesh.face.size(); i++) {
FaceType &f = mesh.face[i]; FaceType &f = mesh.face[i];
for(int k = 0; k < 3; k++) { for(int k = 0; k < 3; k++) {
if(v1== (int)f.V(k) && v0 == (int)f.V((k+1)%3)) ++tot; if(vv0 == f.V0(k) && vv1 == f.V1(k)) //orientation non constistent
else if(v0 == (int)f.V(k) && v1 == (int)f.V((k+1)%3)) { //orientation non constistent
return false; return false;
} else if(vv1 == f.V0(k) && vv0 == f.V1(k)) ++tot;
} }
if(tot >= 2) { //non manifold if(tot >= 2) { //non manifold
return false; return false;

View File

@ -29,6 +29,7 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
float max_angle; //max angle between 2 faces (cos(angle) actually) float max_angle; //max angle between 2 faces (cos(angle) actually)
public: public:
ScalarType radi() { return radius; }
BallPivoting(MESH &_mesh, float _radius = 0, BallPivoting(MESH &_mesh, float _radius = 0,
float minr = 0.2, float angle = M_PI/2): float minr = 0.2, float angle = M_PI/2):
@ -37,8 +38,15 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
last_seed(-1) { last_seed(-1) {
//compute bbox //compute bbox
for(int i = 0; i < (int)this->mesh.vert.size(); i++) baricenter = Point3x(0, 0, 0);
this->mesh.bbox.Add(this->mesh.vert[i].P()); int count = 0;
this->mesh.bbox = Box3<ScalarType>();
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); assert(this->mesh.vn > 3);
if(radius == 0) if(radius == 0)
@ -133,11 +141,12 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
if(d0 < min_edge || d0 > max_edge) continue; if(d0 < min_edge || d0 > max_edge) continue;
Point3x normal = (p1 - p0)^(p2 - p0); 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 * vv0->N() < 0) continue;
if(normal * vv1->N() < 0) continue; if(normal * vv1->N() < 0) continue;
if(normal * vv2->N() < 0) continue; if(normal * vv2->N() < 0) continue;
} }*/
if(!FindSphere(p0, p1, p2, center)) { if(!FindSphere(p0, p1, p2, center)) {
continue; continue;
@ -199,13 +208,18 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
Point3x middle = (v0 + v1)/2; Point3x middle = (v0 + v1)/2;
Point3x center; Point3x center;
if(!FindSphere(v0, v1, v2, center)) return -1; if(!FindSphere(v0, v1, v2, center)) {
// assert(0);
return -1;
}
Point3x start_pivot = center - middle; Point3x start_pivot = center - middle;
Point3x axis = (v1 - v0); Point3x axis = (v1 - v0);
ScalarType axis_len = axis.SquaredNorm(); ScalarType axis_len = axis.SquaredNorm();
if(axis_len > 4*radius*radius) return false; if(axis_len > 4*radius*radius) {
return -1;
}
axis.Normalize(); axis.Normalize();
// r is the radius of the thorus of all possible spheres passing throug v0 and v1 // r is the radius of the thorus of all possible spheres passing throug v0 and v1
@ -218,7 +232,7 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
int n = trimesh::GetInSphereVertex(this->mesh, grid, middle, r + radius, targets, dists, points); int n = trimesh::GetInSphereVertex(this->mesh, grid, middle, r + radius, targets, dists, points);
if(targets.size() == 0) { 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; VertexType *candidate = NULL;
@ -268,13 +282,17 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
min_angle = alpha; min_angle = alpha;
} }
} }
if(min_angle >= M_PI - 0.1) return -1; if(min_angle >= M_PI - 0.1) {
return -1;
}
if(candidate == NULL) { if(candidate == NULL) {
return -1; return -1;
} }
if(!candidate->IsB()) {
assert((candidate->P() - v0).Norm() > min_edge); assert((candidate->P() - v0).Norm() > min_edge);
assert((candidate->P() - v1).Norm() > min_edge); assert((candidate->P() - v1).Norm() > min_edge);
}
int id = candidate - &*this->mesh.vert.begin(); int id = candidate - &*this->mesh.vert.begin();
assert(id != edge.v0 && id != edge.v1); assert(id != edge.v0 && id != edge.v1);
@ -297,6 +315,7 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
private: private:
int last_seed; //used for new seeds when front is empty int last_seed; //used for new seeds when front is empty
int usedBit; //use to detect if a vertex has been already processed. 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 StaticGrid grid; //lookup grid for points
@ -305,14 +324,32 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
the normal of the face points toward the center of the sphere */ the normal of the face points toward the center of the sphere */
bool FindSphere(Point3x &p0, Point3x &p1, Point3x &p2, Point3x &center) { bool FindSphere(Point3x &p0, Point3x &p1, Point3x &p2, Point3x &center) {
Point3x q1 = p1 - p0; //we want p0 to be always the smallest one.
Point3x q2 = p2 - p0; 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; Point3x up = q1^q2;
ScalarType uplen = up.Norm(); ScalarType uplen = up.Norm();
//the three points are aligned //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; up /= uplen;
@ -326,10 +363,12 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
center = q1*l1 + q2*l2; center = q1*l1 + q2*l2;
ScalarType circle_r = center.Norm(); 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); ScalarType height = sqrt(radius*radius - circle_r*circle_r);
center += p0 + up*height; center += p[0] + up*height;
return true; return true;
} }