*** 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
|
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;
|
||||||
|
|
|
@ -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 ¢er) {
|
bool FindSphere(Point3x &p0, Point3x &p1, Point3x &p2, Point3x ¢er) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue