working backup

This commit is contained in:
Federico Ponchio 2006-10-18 10:08:15 +00:00
parent 6eb4a5b293
commit 36db742b83
1 changed files with 128 additions and 34 deletions

View File

@ -26,6 +26,7 @@ class Pivot {
ScalarType radius; //default 1 (not meaningful
ScalarType mindist; //minimum distance between points in the mesh (% of radius)
ScalarType crease; // -0.5
bool normals; //default false
Box3<ScalarType> box;
MESH &mesh;
@ -37,7 +38,11 @@ class Pivot {
//this edge belongs to
int face; //corresponding face
Coord center; //center of the sphere touching the face
int count; //test delay touch edges.
int count; //test delay touch edges.
float angle;
int candidate;
Coord newcenter;
//the loops in the front are mantained as a double linked list
typename std::list<Edge>::iterator next;
@ -46,7 +51,7 @@ class Pivot {
Edge() {}
Edge(int _v0, int _v1, int _v2, int _face, Point3f &_center):
v0(_v0), v1(_v1), v2(_v2),
face(_face), center(_center), count(0) {
face(_face), center(_center), count(-1) {
assert(v0 != v1 && v1 != v2 && v0 != v2);
}
};
@ -66,8 +71,8 @@ class Pivot {
int last_seed;
Pivot(MESH &_mesh, ScalarType _radius, ScalarType _mindist = 0.05, ScalarType _crease = -0.5):
mesh(_mesh), radius(_radius), mindist(_mindist), crease(_crease), last_seed(0) {
Pivot(MESH &_mesh, ScalarType _radius, ScalarType _mindist = 0.1, ScalarType _crease = -0.5):
mesh(_mesh), radius(_radius), mindist(_mindist), crease(_crease), normals(false), last_seed(0) {
//Compute bounding box. (this may be passed as a parameter?
for(int i = 0; i < mesh.vert.size(); i++)
@ -83,10 +88,54 @@ Pivot(MESH &_mesh, ScalarType _radius, ScalarType _mindist = 0.05, ScalarType _c
grid.Set(mesh.vert.begin(), mesh.vert.end(), box);
nb.clear();
nb.resize(mesh.vert.size(), 0);
for(int i = 0; i < mesh.vert.size(); i++)
mesh.vert[i].ClearFlags();
if(mesh.face.size()) {
//init border from mesh
Point3x center;
CVertex *start = &*mesh.vert.begin();
for(int i = 0; i < mesh.face.size(); i++) {
CFace &face = mesh.face[i];
for(int k = 0; k < 3; k++) {
if(!face.V(k)->IsB()) face.V(k)->SetV();
if(face.IsB(k)) {
//compute center:
findSphere(face.P(k), face.P((k+1)%3), face.P((k+2)%3), center);
newEdge(Edgex(face.V((k)%3) -start, face.V((k+1)%3) - start, face.V((k+2)%3) - start,
i, center));
}
}
}
for(typename std::list<Edgex>::iterator s = front.begin(); s != front.end(); s++) {
(*s).previous = front.end();
(*s).next = front.end();
printf("%d %d\n", (*s).v0, (*s).v1);
}
//now create loops:
for(typename std::list<Edgex>::iterator s = front.begin(); s != front.end(); s++) {
for(typename std::list<Edgex>::iterator j = front.begin(); j != front.end(); j++) {
if(s == j) continue;
if((*s).v1 != (*j).v0) continue;
if((*j).previous != front.end()) continue;
(*s).next = j;
(*j).previous = s;
}
}
/* for(typename std::list<Edgex>::iterator s = front.begin(); s != front.end(); s++) {
assert((*s).next != front.end());
assert((*s).previous != front.end());
} */
for(int i = 0; i < mesh.face.size(); i++) {
CFace &face = mesh.face[i];
for(int k = 0; k < 3; k++)
face.V(k) = (CVertex *)(face.V(k) - start);
}
} else {
for(int i = 0; i < mesh.vert.size(); i++)
mesh.vert[i].ClearFlags();
}
srand(time(NULL));
}
/* return false if you want to stop.\n */
void buildMesh(CallBackPos *call = NULL, int interval = 512) {
@ -122,13 +171,14 @@ void buildMesh(CallBackPos *call = NULL, int interval = 512) {
bool seed(bool outside = true, int start = -1) {
//pick a random point (well...)
if(start == -1) start = rand()%mesh.vert.size();
if(start == -1) start = 0;//rand()%mesh.vert.size();
//get a sphere of neighbours
std::vector<int> targets;
std::vector<ScalarType> dists;
int n = getInSphere(mesh.vert[start].P(), 2*radius, targets, dists);
if(n < 3) {
mesh.vert[start].SetD();
//bad luck. we should call seed again (assuming random pick) up to
//some maximum tries. im lazy.
return false;
@ -160,8 +210,14 @@ bool seed(bool outside = true, int start = -1) {
if((p2 - p0).Norm() < mindist*radius) continue;
if((p2 - p1).Norm() < mindist*radius) continue;
Point3x normal = (p1 - p0)^(p2 - p0);
//check normal pointing inside
if(normal * out < 0) continue;
if(!normals) {
//check normal pointing inside
if(normal * out < 0) continue;
} else {
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;
bool failed = false;
@ -241,7 +297,6 @@ int addFace() {
}
if(!front.size()) {
return -1;
//maybe there are unconnected parts of the mesh:
//find a non D, V, B point and try to seed if failed D it.
for(; last_seed < mesh.vert.size(); ++last_seed) {
@ -260,21 +315,40 @@ int addFace() {
Edgex &e = *ei;
Edgex &previous = *e.previous;
Edgex &next = *e.next;
/* if(e.count == -1) {
printf("angle %f\n", e.angle);
if(e.angle < 1) e.count = 0;
else if(e.angle < 1.5) e.count = 2;
else if(e.angle < 2) e.count = 4;
else e.count = 6;
}
if(e.count > 0) {
printf("delay\n");
e.count--;
moveBack(ei);
return 0;
} */
int v0 = e.v0, v1 = e.v1;
assert(nb[v0] < 10 && nb[v1] < 10);
int v2;
Point3x center;
std::vector<int> targets;
bool success = pivot(e, v2, center, targets);
bool success = pivot(e);
v2 = e.candidate;
center = e.newcenter;
//if no pivoting or we are trying to connect to the inside of the mesh.
if(!success || mesh.vert[v2].IsV()) {
printf("no success\n");
killEdge(ei);
return 0;
}
//does v2 belongs to a front? (and which?)
typename std::list<Edgex>::iterator touch = touches(v2, ei);
typename std::list<Edgex>::iterator touch = touches(ei);
assert(v2 != v0 && v2 != v1);
@ -307,6 +381,7 @@ int addFace() {
previous.next = e.next;
next.previous = e.previous;
pivot(previous);
moveBack(e.previous);
//this checks if we can glue something to e.previous
@ -315,6 +390,7 @@ int addFace() {
} else if(v2 == next.v1) {
/*touching next edge (we reuse next)
previous
@ -333,6 +409,7 @@ int addFace() {
next.center = center;
next.previous = e.previous;
previous.next = e.next;
pivot(next);
// moveBack(e.next);
//this checks if we can glue something to e.previous
@ -340,7 +417,12 @@ int addFace() {
front.erase(ei);
} else {
/* if(e.count == -1) {
e.count = 4;
moveBack(ei);
return 0;
}*/
/* this code would delay the joining edge to avoid bad situations not used but..
if(e.count < 2) {
e.count++;
@ -387,7 +469,9 @@ int addFace() {
(*up).v1 = v2;
(*up).face = fn;
(*up).center = center;
moveBack(ei);
pivot(*up);
pivot(*down);
moveBack(ei);
}
@ -420,6 +504,8 @@ int addFace() {
e.face = fn;
e.center = center;
e.next = down;
pivot(*ei);
pivot(*down);
moveBack(ei);
}
addFace(v0, v2, v1);
@ -430,7 +516,7 @@ int addFace() {
/* return new vertex and the center of the new sphere pivoting from edge
if the vertex belongs to another edge, touch points to it. */
bool pivot(Edgex &edge, int &candidate, Point3x &end_pivot, std::vector<int> &targets) {
bool pivot(Edgex &edge) {
Point3x v0 = mesh.vert[edge.v0].P();
Point3x v1 = mesh.vert[edge.v1].P();
Point3x v2 = mesh.vert[edge.v2].P();
@ -440,8 +526,7 @@ int addFace() {
Point3x &normal = mesh.face[edge.face].N();
*/
Point3x normal = ((v1 - v0)^(v2 - v0)).Normalize();
Point3x normal = ((v1 - v0)^(v2 - v0)).Normalize();
Point3x middle = (v0 + v1)/2;
Point3x start_pivot = edge.center - middle;
Point3x axis = (v1 - v0);
@ -453,13 +538,13 @@ int addFace() {
// 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<int> targets;
std::vector<ScalarType> dists;
getInSphere(middle, r + radius, targets, dists);
if(targets.size() == 0) return false; //this really would be strange but one never knows.
candidate = -1;
edge.candidate = -1;
ScalarType minangle = 0;
Point3x center; //to be computed for each sample
for(int i = 0; i < targets.size(); i++) {
@ -472,9 +557,12 @@ int addFace() {
Point3x p = mesh.vert[id].P();
if(normals && normal * mesh.vert[id].N() < 0) {
continue;
}
/* Prevent 360 edges, also often reject ~ 50% points */
Point3x n = ((p - v0)^(v1 - v0)).Normalize();
if(n * normal < -0.5) {
if(n * normal < crease) {
continue;
}
@ -489,7 +577,7 @@ int addFace() {
/* adding a small bias to already chosen vertices.
doesn't solve numerical problems, but helps. */
if(mesh.vert[id].IsB()) alpha -= 0.001;
// if(mesh.vert[id].IsB()) alpha -= 0.001;
/* Sometimes alpha might be little less then M_PI while it should be 0,
by numerical errors: happens for example pivoting
@ -503,18 +591,23 @@ int addFace() {
if(alpha > beta) alpha -= 2*M_PI;
}
if(candidate == -1 || alpha < minangle) {
candidate = id;
minangle = alpha;
end_pivot = center;
//if alphs < 0.1
//scale alpha by distance:
if(edge.candidate == -1 ||
(alpha < 0.1 && id < edge.candidate) ||
(alpha >= 0.1 && alpha < edge.angle)) {
edge.candidate = id;
edge.angle = alpha;
edge.newcenter = center;
}
}
//found no point suitable.
if(candidate == -1) {
if(edge.candidate == -1 || normal * mesh.vert[edge.candidate].N() < 0) {
return false;
}
assert(candidate != edge.v0 && candidate != edge.v1);
assert(edge.candidate != edge.v0 && edge.candidate != edge.v1);
return true;
}
@ -540,7 +633,7 @@ int addFace() {
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() - 2*(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;
@ -697,10 +790,11 @@ int addFace() {
return true;
}
typename std::list<Edgex>::iterator touches(int v, typename std::list<Edgex>::iterator e) {
typename std::list<Edgex>::iterator touches(typename std::list<Edgex>::iterator e) {
//TODO what happens when it touches more than one front?
//might still work.
int v = (*e).candidate;
typename std::list<Edgex>::iterator touch = front.end();
if(mesh.vert[v].IsB()) {
//test nearby Edges: it is faster