*** empty log message ***
This commit is contained in:
parent
7823c5dba1
commit
511f4053c9
|
@ -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;
|
||||
|
|
|
@ -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 ¢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 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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue