*** 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
AdvancingFront(MESH &_mesh): mesh(_mesh) {
// UpdateFlags<MESH>::VertexClear(mesh);
UpdateFlags<MESH>::Clear(mesh);
// UpdateTopology<MESH>::VertexFace(mesh);
//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>::FaceBorderFromNone(mesh);
UpdateFlags<MESH>::VertexBorderFromFace(mesh);
@ -63,6 +64,7 @@ template <class MESH> 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<FrontEdge>::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<FrontEdge>::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<FrontEdge>::iterator down = NewEdge(FrontEdge(v2, v1, v0, mesh.face.size()));
std::list<FrontEdge>::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;

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)
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 MESH> class BallPivoting: public AdvancingFront<MESH> {
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<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);
if(radius == 0)
@ -133,11 +141,12 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
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 MESH> class BallPivoting: public AdvancingFront<MESH> {
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 MESH> class BallPivoting: public AdvancingFront<MESH> {
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 MESH> class BallPivoting: public AdvancingFront<MESH> {
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<FrontEdge>::iterator k = this->front.begin(); k != this->front.end(); k++)
@ -297,6 +315,7 @@ template <class MESH> class BallPivoting: public AdvancingFront<MESH> {
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 MESH> class BallPivoting: public AdvancingFront<MESH> {
the normal of the face points toward the center of the sphere */
bool FindSphere(Point3x &p0, Point3x &p1, Point3x &p2, Point3x &center) {
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 MESH> class BallPivoting: public AdvancingFront<MESH> {
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;
}