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:
parent
91eb0b8153
commit
24dc0317a2
18 changed files with 900 additions and 751 deletions
|
@ -31,6 +31,4 @@ target_include_directories(meshfix PUBLIC
|
||||||
include/Kernel
|
include/Kernel
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_options(meshfix PRIVATE -fpermissive)
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -149,10 +149,10 @@ PM_Rational ceil(const PM_Rational& a);
|
||||||
PM_Rational floor(const PM_Rational& a);
|
PM_Rational floor(const PM_Rational& a);
|
||||||
PM_Rational round(const PM_Rational& a);
|
PM_Rational round(const PM_Rational& a);
|
||||||
|
|
||||||
/**************** I/O operators ****************/
|
/**************** I/O operators ****************/
|
||||||
|
|
||||||
inline std::ostream & operator<<(std::ostream &o, const PM_Rational& c) { return o << c.toRational(); }
|
inline std::ostream & operator<<(std::ostream &o, const PM_Rational& c) { return o << c.toRational(); }
|
||||||
inline std::istream & operator>>(std::istream &i, PM_Rational& c) { EXACT_NT a; i >> a; c.setFromRational(a); return i; }
|
inline std::istream & operator>>(std::istream &i, PM_Rational& c) { EXACT_NT a; i >> a; c.setFromRational(a); return i; }
|
||||||
|
|
||||||
#define TMESH_TO_DOUBLE(x) ((x).toDouble())
|
#define TMESH_TO_DOUBLE(x) ((x).toDouble())
|
||||||
#define TMESH_TO_FLOAT(x) ((x).toFloat())
|
#define TMESH_TO_FLOAT(x) ((x).toFloat())
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;}
|
||||||
|
|
|
@ -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 >
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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((®), t, n)
|
FOREACHVTTRIANGLE((®), 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;}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||||
|
|
|
@ -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); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue