Fix undefined behavior and other issues in the MeshFix library

!ADD call to TMesh::init function to initialize prediacates, fixes problems
turn off result check - sometimes it is too restrictive
This commit is contained in:
PavelMikus 2022-06-06 11:42:10 +02:00 committed by Lukas Matena
parent 91eb0b8153
commit 24dc0317a2
18 changed files with 900 additions and 751 deletions

View file

@ -31,6 +31,4 @@ target_include_directories(meshfix PUBLIC
include/Kernel include/Kernel
) )
target_compile_options(meshfix PRIVATE -fpermissive)
################################################################################ ################################################################################

View file

@ -116,12 +116,6 @@ typedef unsigned short UINT16;
typedef signed short INT16; typedef signed short INT16;
#endif #endif
#ifdef IS64BITPLATFORM
typedef long int j_voidint;
#else
typedef int j_voidint;
#endif
#define UBYTE_MAX 255 #define UBYTE_MAX 255
#ifndef UINT16_MAX #ifndef UINT16_MAX
@ -138,18 +132,169 @@ typedef int j_voidint;
#define MAX(a,b)(((a)>(b))?(a):(b)) #define MAX(a,b)(((a)>(b))?(a):(b))
#endif #endif
//////// Swaps two pointers. /////////////////////////////// //////// Swaps two pointers. ///////////////////////////////
inline void p_swap(void **a, void **b) {void *t = *a; *a = *b; *b = t;} inline void p_swap(void **a, void **b) {void *t = *a; *a = *b; *b = t;}
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
template<typename T, typename Child>
class Primitive {
protected:
T value;
public:
// we must type cast to child to so
// a += 3 += 5 ... and etc.. work the same way
// as on primitives
Child &childRef(){
return *((Child*)this);
}
// you can overload to give a default value if you want
Primitive(){}
explicit Primitive(T v):value(v){}
T get(){
return value;
}
#define OP(op) Child &operator op(Child const &v){\
value op v.value; \
return childRef(); \
}\
Child &operator op(T const &v){\
value op v; \
return childRef(); \
}
// all with equals
OP(+=)
OP(-=)
OP(*=)
OP(/=)
OP(<<=)
OP(>>=)
OP(|=)
OP(^=)
OP(&=)
OP(%=)
#undef OP
#define OP(p) Child operator p(Child const &v){\
Child other = childRef();\
other p ## = v;\
return other;\
}\
Child operator p(T const &v){\
Child other = childRef();\
other p ## = v;\
return other;\
}
OP(+)
OP(-)
OP(*)
OP(/)
OP(<<)
OP(>>)
OP(|)
OP(^)
OP(&)
OP(%)
#undef OP
#define OP(p) bool operator p(Child const &v){\
return value p v.value;\
}\
bool operator p(T const &v){\
return value p v;\
}
OP(&&)
OP(||)
OP(<)
OP(<=)
OP(>)
OP(>=)
OP(==)
OP(!=)
#undef OP
Child operator +(){return Child(value);}
Child operator -(){return Child(-value);}
Child &operator ++(){++value; return childRef();}
Child operator ++(int){
Child ret(value);
++value;
return childRef();
}
Child operator --(int){
Child ret(value);
--value;
return childRef();
}
bool operator!(){return !value;}
Child operator~(){return Child(~value);}
};
class Data { class Data {
public: public:
virtual ~Data() = default; virtual ~Data() = default;
}; };
class intWrapper: public Data {
private:
int val;
public:
intWrapper(int val = 0) :
val(val) {
}
operator int &() {
return val;
}
int* operator &() {
return &val;
}
operator int() const {
return val;
}
operator int*() {
return &val;
}
};
class doubleWrapper: public Data, public Primitive<double, doubleWrapper> {
public:
doubleWrapper(double val = 0) {
this->value = val;
}
operator double &() {
return value;
}
double* operator &() {
return &value;
}
operator double() const {
return value;
}
operator double*() {
return &value;
}
};
inline int to_int(Data *d) {
return static_cast<intWrapper*>(d)->operator int();
}
} //namespace T_MESH } //namespace T_MESH

View file

@ -54,7 +54,7 @@ namespace T_MESH
class abstractHeap class abstractHeap
{ {
protected: protected:
void **heap; //!< Heap data is stored here Data **heap; //!< Heap data is stored here
int numels; //!< Current number of elements int numels; //!< Current number of elements
int maxels; //!< Maximum number of elements int maxels; //!< Maximum number of elements
int *positions; //!< Optional pointer to an array of positions int *positions; //!< Optional pointer to an array of positions
@ -67,7 +67,7 @@ class abstractHeap
//! This function must be implemented in the extended class. //! This function must be implemented in the extended class.
//! The return value must be <0 if a<b, >0 if a>b or 0 if a=b. //! The return value must be <0 if a<b, >0 if a>b or 0 if a=b.
virtual int compare(const void *a, const void *b) = 0; virtual int compare(const Data *a, const Data *b) = 0;
public : public :
@ -81,11 +81,11 @@ class abstractHeap
//! returned, otherwise the index position of the newly inserted element is //! returned, otherwise the index position of the newly inserted element is
//! returned. //! returned.
int insert(void *e); int insert(Data *e);
int isEmpty() const {return (numels == 0);} //!< Returns TRUE if the heap is empty int isEmpty() const {return (numels == 0);} //!< Returns TRUE if the heap is empty
void *getHead() const {return heap[1];} //!< Returns the first element of the heap Data *getHead() const {return heap[1];} //!< Returns the first element of the heap
void *removeHead(); //!< Removes and returns the first element after rearranging the heap Data *removeHead(); //!< Removes and returns the first element after rearranging the heap
void flush() {numels=0;} //!< Removes all the elements void flush() {numels=0;} //!< Removes all the elements
}; };

View file

@ -72,7 +72,7 @@ class Point : public Data
{ {
public : public :
coord x,y,z; //!< Coordinates coord x,y,z; //!< Coordinates
void *info; //!< Further information Data *info; //!< Further information
//! Creates a new point with coordinates (0,0,0). //! Creates a new point with coordinates (0,0,0).
Point() {x = y = z = 0; info = NULL;} Point() {x = y = z = 0; info = NULL;}

View file

@ -55,7 +55,7 @@ class Edge : public Data
Vertex *v1,*v2; //!< End-points Vertex *v1,*v2; //!< End-points
class Triangle *t1,*t2; //!< Incident triangles class Triangle *t1,*t2; //!< Incident triangles
unsigned char mask; //!< bit-mask for marking purposes unsigned char mask; //!< bit-mask for marking purposes
void *info; //!< Further information Data *info; //!< Further information
Edge(); //!< AMF_ADD 1.1-2 > Edge(); //!< AMF_ADD 1.1-2 >

View file

@ -77,7 +77,7 @@ class mc_cell : public Data
} }
void polygonize(Basic_TMesh *tin); void polygonize(Basic_TMesh *tin);
static int compare(const void *e1, const void *e2); static int compare(const Data *e1, const Data *e2);
void merge(mc_cell *m); void merge(mc_cell *m);

View file

@ -51,7 +51,7 @@ class Triangle : public Data
public : public :
Edge *e1, *e2, *e3; //!< Edges of the triangle Edge *e1, *e2, *e3; //!< Edges of the triangle
void *info; //!< Further information Data* info; //!< Further information
unsigned char mask; //!< bit-mask for marking purposes unsigned char mask; //!< bit-mask for marking purposes
Triangle(); Triangle();

View file

@ -282,7 +282,7 @@ int Basic_TMesh::mergeCoincidentEdges()
if (e->v2->info != e->v2) e->v2 = (Vertex *)e->v2->info; if (e->v2->info != e->v2) e->v2 = (Vertex *)e->v2->info;
e->v1->e0 = e->v2->e0 = e; e->v1->e0 = e->v2->e0 = e;
} }
int rv = removeVertices(); removeVertices();
// At this point the mesh should no longer have duplicated vertices, but may have duplicated edges // At this point the mesh should no longer have duplicated vertices, but may have duplicated edges
E.sort(&vtxEdgeCompare); E.sort(&vtxEdgeCompare);
@ -296,7 +296,6 @@ int Basic_TMesh::mergeCoincidentEdges()
{ {
Triangle *t1 = e->getBoundaryTriangle(); Triangle *t1 = e->getBoundaryTriangle();
Edge *f = ((Edge *)e->info); Edge *f = ((Edge *)e->info);
Triangle *t2 = f->getBoundaryTriangle();
t1->replaceEdge(e, f); t1->replaceEdge(e, f);
((f->t1 == NULL) ? (f->t1) : (f->t2)) = t1; ((f->t1 == NULL) ? (f->t1) : (f->t2)) = t1;
e->v1 = e->v2 = NULL; e->v1 = e->v2 = NULL;
@ -355,14 +354,14 @@ bool Basic_TMesh::rebuildConnectivity(bool fixconnectivity) //!< AMF_CHANGE 1.1>
Triangle *t; Triangle *t;
ExtVertex **var = new ExtVertex *[V.numels()]; ExtVertex **var = new ExtVertex *[V.numels()];
int i=0; int i=0;
FOREACHVERTEX(v, n) { v->e0 = NULL; var[i] = new ExtVertex(v); v->info = (void *)(intptr_t)i; i++; } FOREACHVERTEX(v, n) { v->e0 = NULL; var[i] = new ExtVertex(v); v->info = new intWrapper(i); i++; }
int nt = T.numels(); int nt = T.numels();
int *triangles = new int[nt*3]; int *triangles = new int[nt*3];
i = 0; FOREACHTRIANGLE(t, n) i = 0; FOREACHTRIANGLE(t, n)
{ {
triangles[i * 3] = (j_voidint)t->v1()->info; triangles[i * 3] = ((intWrapper*)t->v1()->info)->operator int();
triangles[i*3+1] = (j_voidint)t->v2()->info; triangles[i*3+1] = ((intWrapper*)t->v2()->info)->operator int();
triangles[i*3+2] = (j_voidint)t->v3()->info; triangles[i*3+2] = ((intWrapper*)t->v3()->info)->operator int();
i++; i++;
} }
T.freeNodes(); T.freeNodes();
@ -450,7 +449,7 @@ int multiSplitEdge(Basic_TMesh *tin, Edge *e)
while (splitVertices.numels()) while (splitVertices.numels())
{ {
coord ad, mind = DBL_MAX; coord ad, mind = DBL_MAX;
Vertex *gv; Vertex *gv = nullptr;
FOREACHVVVERTEX((&splitVertices), v, n) if ((ad = v->squaredDistance(e->v2)) < mind) { gv = v; mind = ad; } FOREACHVVVERTEX((&splitVertices), v, n) if ((ad = v->squaredDistance(e->v2)) < mind) { gv = v; mind = ad; }
splitVertices.removeNode(gv); splitVertices.removeNode(gv);
tin->splitEdge(e, gv); tin->splitEdge(e, gv);

View file

@ -580,7 +580,7 @@ int Basic_TMesh::refineSelectedHolePatches(Triangle *t0)
Edge *e, *f; Edge *e, *f;
Vertex *v; Vertex *v;
List *ve, toswap, reg, all_edges, interior_edges, boundary_edges, boundary_vertices, interior_vertices; List *ve, toswap, reg, all_edges, interior_edges, boundary_edges, boundary_vertices, interior_vertices;
coord sigma, l, sv1, sv2, sv3, dv1, dv2, dv3; doubleWrapper sigma, l, sv1, sv2, sv3, dv1, dv2, dv3;
int swaps, totits, nee, ntb, nnt=-1, pnnt, gits=0; int swaps, totits, nee, ntb, nnt=-1, pnnt, gits=0;
const double alpha = sqrt(2.0); const double alpha = sqrt(2.0);
Point vc; Point vc;
@ -630,7 +630,7 @@ int Basic_TMesh::refineSelectedHolePatches(Triangle *t0)
{ {
ve = v->VE(); ve = v->VE();
sigma=0; nee=0; FOREACHVEEDGE(ve, e, m) if (!IS_BIT(e, 5)) {nee++; sigma += e->length();} sigma=0; nee=0; FOREACHVEEDGE(ve, e, m) if (!IS_BIT(e, 5)) {nee++; sigma += e->length();}
sigma /= nee; v->info = new coord(sigma); sigma /= double(nee); v->info = new doubleWrapper(sigma);
delete(ve); delete(ve);
} }
@ -644,9 +644,9 @@ int Basic_TMesh::refineSelectedHolePatches(Triangle *t0)
FOREACHVTTRIANGLE((&reg), t, n) FOREACHVTTRIANGLE((&reg), t, n)
{ {
vc = t->getCenter(); vc = t->getCenter();
sv1 = (*(coord *)t->v1()->info); sv1 = (*(doubleWrapper *)t->v1()->info);
sv2 = (*(coord *)t->v2()->info); sv2 = (*(doubleWrapper *)t->v2()->info);
sv3 = (*(coord *)t->v3()->info); sv3 = (*(doubleWrapper *)t->v3()->info);
sigma = (sv1+sv2+sv3)/3.0; sigma = (sv1+sv2+sv3)/3.0;
dv1 = alpha*(t->v1()->distance(&vc)); dv1 = alpha*(t->v1()->distance(&vc));
dv2 = alpha*(t->v2()->distance(&vc)); dv2 = alpha*(t->v2()->distance(&vc));
@ -658,7 +658,7 @@ int Basic_TMesh::refineSelectedHolePatches(Triangle *t0)
nnt += (T.numels()-ntb); nnt += (T.numels()-ntb);
if (T.numels() == ntb+2) if (T.numels() == ntb+2)
{ {
v->info = new coord(sigma); v->info = new doubleWrapper(sigma);
interior_vertices.appendHead(v); interior_vertices.appendHead(v);
interior_edges.appendHead(v->e0); interior_edges.appendHead(v->e0);
interior_edges.appendHead(v->e0->leftTriangle(v)->prevEdge(v->e0)); interior_edges.appendHead(v->e0->leftTriangle(v)->prevEdge(v->e0));
@ -700,8 +700,8 @@ int Basic_TMesh::refineSelectedHolePatches(Triangle *t0)
} while (nnt && gits<10); } while (nnt && gits<10);
//FOREACHVEEDGE((&boundary_edges), e, n) UNMARK_BIT(e, 6); //FOREACHVEEDGE((&boundary_edges), e, n) UNMARK_BIT(e, 6);
FOREACHVVVERTEX((&boundary_vertices), v, n) { delete((coord *)v->info); v->info = NULL; MARK_BIT(v, 5);} FOREACHVVVERTEX((&boundary_vertices), v, n) { delete((Data *)v->info); v->info = NULL; MARK_BIT(v, 5);}
FOREACHVVVERTEX((&interior_vertices), v, n) { delete((coord *)v->info); v->info = NULL; MARK_BIT(v, 6);} FOREACHVVVERTEX((&interior_vertices), v, n) { delete((Data *)v->info); v->info = NULL; MARK_BIT(v, 6);}
if (gits>=10) {TMesh::warning("Fill holes: Refinement stage failed to converge. Breaking.\n"); return 1;} if (gits>=10) {TMesh::warning("Fill holes: Refinement stage failed to converge. Breaking.\n"); return 1;}

View file

@ -134,7 +134,7 @@ UBYTE mc_cell::lookdown()
return i; return i;
} }
int mc_cell::compare(const void *e1, const void *e2) int mc_cell::compare(const Data *e1, const Data *e2)
{ {
mc_cell *a = (mc_cell *)e1; mc_cell *a = (mc_cell *)e1;
mc_cell *b = (mc_cell *)e2; mc_cell *b = (mc_cell *)e2;
@ -680,7 +680,7 @@ void mc_cell::merge(mc_cell *m)
List *mc_grid::createCells() List *mc_grid::createCells()
{ {
int i,j,k,numcells=numrays+1; int i,j,k=numrays+1;
mc_ints *m; mc_ints *m;
Node *n; Node *n;
List *ac = new List; List *ac = new List;

View file

@ -37,7 +37,7 @@ namespace T_MESH
abstractHeap::abstractHeap(int size) abstractHeap::abstractHeap(int size)
{ {
heap = new void *[size+1]; heap = new Data *[size+1];
numels = 0; numels = 0;
maxels = size; maxels = size;
positions = NULL; positions = NULL;
@ -52,9 +52,9 @@ int abstractHeap::upheap(int k)
{ {
if (k < 2) return k; if (k < 2) return k;
void *t = heap[k]; Data *t = heap[k];
int fk = (k%2)?((k-1)/2):(k/2); int fk = (k%2)?((k-1)/2):(k/2);
void *f = heap[fk]; Data *f = heap[fk];
if (compare(t, f) <= 0) if (compare(t, f) <= 0)
{ {
@ -62,8 +62,8 @@ int abstractHeap::upheap(int k)
heap[fk] = t; heap[fk] = t;
if (positions != NULL) if (positions != NULL)
{ {
positions[(j_voidint)f] = k; positions[to_int(f)] = k;
positions[(j_voidint)t] = fk; positions[to_int(t)] = fk;
} }
return upheap(fk); return upheap(fk);
} }
@ -74,21 +74,21 @@ int abstractHeap::downheap(int k)
{ {
int j; int j;
void *t = heap[k]; Data *t = heap[k];
int fk = (numels%2)?((numels-1)/2):(numels/2); int fk = (numels%2)?((numels-1)/2):(numels/2);
if (k > fk) return k; if (k > fk) return k;
j = k+k; j = k+k;
if (j < numels && compare(heap[j], heap[j+1]) >= 0) j++; if (j < numels && compare(heap[j], heap[j+1]) >= 0) j++;
void *f = heap[j]; Data *f = heap[j];
if (compare(t, f) >= 0) if (compare(t, f) >= 0)
{ {
heap[k] = f; heap[k] = f;
heap[j] = t; heap[j] = t;
if (positions != NULL) if (positions != NULL)
{ {
positions[(j_voidint)f] = k; positions[to_int(f)] = k;
positions[(j_voidint)t] = j; positions[to_int(t)] = j;
} }
return downheap(j); return downheap(j);
} }
@ -96,23 +96,23 @@ int abstractHeap::downheap(int k)
return k; return k;
} }
int abstractHeap::insert(void *t) int abstractHeap::insert(Data *t)
{ {
if (numels == maxels) return -1; if (numels == maxels) return -1;
heap[++numels] = t; heap[++numels] = t;
if (positions != NULL) positions[(j_voidint)t] = numels; if (positions != NULL) positions[to_int(t)] = numels;
return upheap(numels); return upheap(numels);
} }
void *abstractHeap::removeHead() Data *abstractHeap::removeHead()
{ {
void *t = heap[1]; Data *t = heap[1];
if (positions != NULL) positions[(j_voidint)t] = 0; if (positions != NULL) positions[to_int(t)] = 0;
heap[1] = heap[numels--]; heap[1] = heap[numels--];
if (numels) if (numels)
{ {
if (positions != NULL) positions[(j_voidint)heap[1]] = 1; if (positions != NULL) positions[to_int(heap[1])] = 1;
downheap(1); downheap(1);
} }

View file

@ -31,7 +31,7 @@
// This code is inspired on ideas first published in the following paper: // This code is inspired on ideas first published in the following paper:
// Jonathan Richard Shewchuk. Adaptive Precision Floating-Point Arithmetic // Jonathan Richard Shewchuk. Adaptive Precision Floating-Point Arithmetic
// and Fast Robust Geometric Predicates, Discrete & Computational Geometry // and Fast Robust Geometric Predicates, Discrete & Computational Geometry
// 18(3):305363, October 1997. // 18(3):305–363, October 1997.
// //
#include <math.h> #include <math.h>
@ -171,8 +171,8 @@ double _estm(int elen, double *e)
double _adaptive2dorientation(double *pa, double *pb, double *pc, double detsum) double _adaptive2dorientation(double *pa, double *pb, double *pc, double detsum)
{ {
double acx, acy, bcx, bcy,acxtail, acytail, bcxtail, bcytail, detleft, detright; double acx, acy, bcx, bcy,acxtail, acytail, bcxtail, bcytail, detleft, detright;
double detlefttail, detrighttail, det, errbound, B[4], C1[8], C2[12], D[16]; double detlefttail, detrighttail, det, errbound, B[5], C1[8], C2[12], D[16];
double B3, u[4], u3, s1, t1, s0, t0, _bvr, _avr, _brn, _arn, c; double B3, u[5], u3, s1, t1, s0, t0, _bvr, _avr, _brn, _arn, c;
double abig, ahi, alo, bhi, blo, err1, err2, err3, _i, _j, _0; double abig, ahi, alo, bhi, blo, err1, err2, err3, _i, _j, _0;
int C1length, C2length, Dlength; int C1length, C2length, Dlength;

View file

@ -253,7 +253,7 @@ void TMesh::printElapsedTime(bool reset)
{ {
static clock_t beginning_time; static clock_t beginning_time;
if (reset) beginning_time = clock(); if (reset) beginning_time = clock();
else printf("\n\n********** PARTIAL ELAPSED: %d msecs\n\n", (clock() - beginning_time)); else printf("\n\n********** PARTIAL ELAPSED: %d msecs\n\n", int((clock() - beginning_time)));
} }
} //namespace T_MESH } //namespace T_MESH

View file

@ -39,14 +39,14 @@ bool joinClosestComponents(Basic_TMesh *tin)
{ {
i++; i++;
triList.appendHead(t); triList.appendHead(t);
t->info = (void *)(intptr_t)i; t->info = new intWrapper(i);
while (triList.numels()) while (triList.numels())
{ {
t = (Triangle *)triList.popHead(); t = (Triangle *)triList.popHead();
if ((s = t->t1()) != NULL && s->info == NULL) { triList.appendHead(s); s->info = (void *)(intptr_t)i; } if ((s = t->t1()) != NULL && s->info == NULL) { triList.appendHead(s); s->info = new intWrapper(i); }
if ((s = t->t2()) != NULL && s->info == NULL) { triList.appendHead(s); s->info = (void *)(intptr_t)i; } if ((s = t->t2()) != NULL && s->info == NULL) { triList.appendHead(s); s->info = new intWrapper(i); }
if ((s = t->t3()) != NULL && s->info == NULL) { triList.appendHead(s); s->info = (void *)(intptr_t)i; } if ((s = t->t3()) != NULL && s->info == NULL) { triList.appendHead(s); s->info = new intWrapper(i); }
} }
} }

View file

@ -722,7 +722,7 @@ int Basic_TMesh::saveVRML1(const char *fname, const int mode)
fprintf(fp,"Material {\n diffuseColor [\n"); fprintf(fp,"Material {\n diffuseColor [\n");
FOREACHTRIANGLE(t, n) FOREACHTRIANGLE(t, n)
{ {
pkc = (unsigned int)((j_voidint)t->info); pkc = ((intWrapper*)(t->info))->operator int();
fprintf(fp," %f %f %f,\n",((pkc>>24)&0x000000ff)/255.0,((pkc>>16)&0x000000ff)/255.0,((pkc>>8)&0x000000ff)/255.0); fprintf(fp," %f %f %f,\n",((pkc>>24)&0x000000ff)/255.0,((pkc>>16)&0x000000ff)/255.0,((pkc>>8)&0x000000ff)/255.0);
} }
fprintf(fp," ]\n}\nMaterialBinding {\n value PER_FACE_INDEXED\n}\n"); fprintf(fp," ]\n}\nMaterialBinding {\n value PER_FACE_INDEXED\n}\n");
@ -731,7 +731,7 @@ int Basic_TMesh::saveVRML1(const char *fname, const int mode)
fprintf(fp,"Material {\n diffuseColor [\n"); fprintf(fp,"Material {\n diffuseColor [\n");
FOREACHVERTEX(v, n) FOREACHVERTEX(v, n)
{ {
pkc = (unsigned int)((j_voidint)v->info); pkc = ((intWrapper*)(v->info))->operator int();
fprintf(fp," %f %f %f,\n",((pkc>>24)&0x000000ff)/255.0,((pkc>>16)&0x000000ff)/255.0,((pkc>>8)&0x000000ff)/255.0); fprintf(fp," %f %f %f,\n",((pkc>>24)&0x000000ff)/255.0,((pkc>>16)&0x000000ff)/255.0,((pkc>>8)&0x000000ff)/255.0);
} }
fprintf(fp," ]\n}\nMaterialBinding {\n value PER_VERTEX_INDEXED\n}\n"); fprintf(fp," ]\n}\nMaterialBinding {\n value PER_VERTEX_INDEXED\n}\n");
@ -893,7 +893,7 @@ int Basic_TMesh::saveVerTri(const char *fname)
ocds = new coord[V.numels()]; ocds = new coord[V.numels()];
i=0; FOREACHVERTEX(v, n) ocds[i++] = v->x; i=0; FOREACHVERTEX(v, n) ocds[i++] = v->x;
i=0; FOREACHVERTEX(v, n) v->x = ++i; i=0; FOREACHVERTEX(v, n) v->x = ++i;
i=0; FOREACHTRIANGLE(t, n) {i++; t->info = (void *)(intptr_t)i;} i=0; FOREACHTRIANGLE(t, n) {i++; t->info = new intWrapper(i);}
fprintf(fpt,"%d\n",T.numels()); fprintf(fpt,"%d\n",T.numels());
FOREACHTRIANGLE(t, n) FOREACHTRIANGLE(t, n)
@ -1460,7 +1460,7 @@ int Basic_TMesh::loadSTL(const char *fname)
{ {
FILE *fp; FILE *fp;
int nt=0, i=0; int nt=0, i=0;
char kw[64]="", kw2[64]="", *line, facet[50]; char kw[65]="", kw2[65]="", *line, facet[50];
float x,y,z; float x,y,z;
bool binary=0; bool binary=0;
Vertex *v, *v1=NULL, *v2=NULL, *v3=NULL; Vertex *v, *v1=NULL, *v2=NULL, *v3=NULL;

View file

@ -187,11 +187,11 @@ void Basic_TMesh::init(const Basic_TMesh *tin, const bool clone_info)
Triangle *t, *nt; Triangle *t, *nt;
int i; int i;
void **t_info = new void *[tin->T.numels()]; Data **t_info = new Data *[tin->T.numels()];
i=0; FOREACHVTTRIANGLE((&(tin->T)), t, n) t_info[i++]=t->info; i=0; FOREACHVTTRIANGLE((&(tin->T)), t, n) t_info[i++]=t->info;
void **e_info = new void *[tin->E.numels()]; Data **e_info = new Data *[tin->E.numels()];
i=0; FOREACHVEEDGE((&(tin->E)), e, n) e_info[i++]=e->info; i=0; FOREACHVEEDGE((&(tin->E)), e, n) e_info[i++]=e->info;
void **v_info = new void *[tin->V.numels()]; Data **v_info = new Data *[tin->V.numels()];
i=0; FOREACHVVVERTEX((&(tin->V)), v, n) v_info[i++]=v->info; i=0; FOREACHVVVERTEX((&(tin->V)), v, n) v_info[i++]=v->info;
FOREACHVVVERTEX((&(tin->V)), v, n) FOREACHVVVERTEX((&(tin->V)), v, n)
@ -838,14 +838,14 @@ Basic_TMesh *Basic_TMesh::createSubMeshFromSelection(Triangle *t0, bool keep_ref
FOREACHVEEDGE((&sE), e, n) e->v1->e0 = e->v2->e0 = e; FOREACHVEEDGE((&sE), e, n) e->v1->e0 = e->v2->e0 = e;
int i; int i;
void **v_info = NULL, **e_info = NULL, **t_info = NULL; Data **v_info = NULL, **e_info = NULL, **t_info = NULL;
if (!keep_ref) if (!keep_ref)
{ {
v_info = new void *[sV.numels()]; v_info = new Data *[sV.numels()];
i=0; FOREACHVVVERTEX((&sV), v, n) v_info[i++] = v->info; i=0; FOREACHVVVERTEX((&sV), v, n) v_info[i++] = v->info;
e_info = new void *[sE.numels()]; e_info = new Data *[sE.numels()];
i=0; FOREACHVEEDGE((&sE), e, n) e_info[i++] = e->info; i=0; FOREACHVEEDGE((&sE), e, n) e_info[i++] = e->info;
t_info = new void *[sT.numels()]; t_info = new Data *[sT.numels()];
i=0; FOREACHVTTRIANGLE((&sT), t, n) t_info[i++] = t->info; i=0; FOREACHVTTRIANGLE((&sT), t, n) t_info[i++] = t->info;
} }

View file

@ -50,6 +50,8 @@ namespace detail {
using namespace T_MESH; using namespace T_MESH;
static int ensure_tmesh_initialization = (TMesh::init(), 0);
double closestPair(List *bl1, List *bl2, Vertex **closest_on_bl1, Vertex **closest_on_bl2) double closestPair(List *bl1, List *bl2, Vertex **closest_on_bl1, Vertex **closest_on_bl2)
{ {
Node *n, *m; Node *n, *m;
@ -84,14 +86,14 @@ bool joinClosestComponents(Basic_TMesh *tin)
{ {
i++; i++;
triList.appendHead(t); triList.appendHead(t);
t->info = (void *)(intptr_t)i; t->info = new intWrapper(i);
while (triList.numels()) while (triList.numels())
{ {
t = (Triangle *)triList.popHead(); t = (Triangle *)triList.popHead();
if ((s = t->t1()) != NULL && s->info == NULL) {triList.appendHead(s); s->info = (void *)(intptr_t)i;} if ((s = t->t1()) != NULL && s->info == NULL) {triList.appendHead(s); s->info = new intWrapper(i);}
if ((s = t->t2()) != NULL && s->info == NULL) {triList.appendHead(s); s->info = (void *)(intptr_t)i;} if ((s = t->t2()) != NULL && s->info == NULL) {triList.appendHead(s); s->info = new intWrapper(i);}
if ((s = t->t3()) != NULL && s->info == NULL) {triList.appendHead(s); s->info = (void *)(intptr_t)i;} if ((s = t->t3()) != NULL && s->info == NULL) {triList.appendHead(s); s->info = new intWrapper(i);}
} }
} }
@ -298,7 +300,8 @@ bool fix_model_by_meshfix(ModelObject &model_object, int volume_idx, wxProgressD
tin.deselectTriangles(); tin.deselectTriangles();
tin.boundaries(); tin.boundaries();
// Keep only the largest component (i.e. with most triangles) // Keep only the largest component (i.e. with most triangles)
on_progress(L("Remove smallest components"), unsigned(progress_part_base + 0.2 * percent_per_part)); on_progress(L("Remove smallest components"),
unsigned(progress_part_base + 0.2 * percent_per_part));
if (canceled) if (canceled)
throw RepairCanceledException(); throw RepairCanceledException();
tin.removeSmallestComponents(); tin.removeSmallestComponents();
@ -308,7 +311,8 @@ bool fix_model_by_meshfix(ModelObject &model_object, int volume_idx, wxProgressD
if (canceled) if (canceled)
throw RepairCanceledException(); throw RepairCanceledException();
if (tin.boundaries()) { if (tin.boundaries()) {
on_progress(L("Patch small holes"), unsigned(progress_part_base + 0.4 * percent_per_part)); on_progress(L("Patch small holes"),
unsigned(progress_part_base + 0.4 * percent_per_part));
if (canceled) if (canceled)
throw RepairCanceledException(); throw RepairCanceledException();
tin.fillSmallBoundaries(0, true); tin.fillSmallBoundaries(0, true);
@ -320,22 +324,25 @@ bool fix_model_by_meshfix(ModelObject &model_object, int volume_idx, wxProgressD
// Run geometry correction // Run geometry correction
if (!tin.boundaries()) { if (!tin.boundaries()) {
int iteration = 0; int iteration = 0;
on_progress(L("Start iterative correction"), unsigned(progress_part_base + 0.55 * percent_per_part)); on_progress(L("Start iterative correction"),
unsigned(progress_part_base + 0.55 * percent_per_part));
tin.deselectTriangles(); tin.deselectTriangles();
tin.invertSelection(); tin.invertSelection();
bool fixed = false; bool fixed = false;
while (iteration < 10 && !fixed) { //default constants taken from TMesh library while (iteration < 10 && !fixed) { //default constants taken from TMesh library
fixed = tin.meshclean_single_iteration(3, canceled); fixed = tin.meshclean_single_iteration(3, canceled);
on_progress(L("Fixing geometry"), progress_part_base + percent_per_part * std::min(0.9, 0.6 + iteration*0.08)); // majority of objects should finish in 4 iterations on_progress(L("Fixing geometry"),
progress_part_base
+ percent_per_part * std::min(0.9, 0.6 + iteration * 0.08)); // majority of objects will finish in 4 iterations
if (canceled) if (canceled)
throw RepairCanceledException(); throw RepairCanceledException();
iteration++; iteration++;
} }
} }
if (tin.boundaries() || tin.T.numels() == 0) { // if (tin.boundaries() || tin.T.numels() == 0) {
throw RepairFailedException(); // throw RepairFailedException();
} // }
parts[part_idx] = tin.to_indexed_triangle_set(); parts[part_idx] = tin.to_indexed_triangle_set();
} }