Forked from
gmsh / gmsh
18370 commits behind the upstream repository.
-
Jean-François Remacle authoredJean-François Remacle authored
BDS.h 6.37 KiB
// This is a 2D version of the Bidirectional Data Structure (BDS)
// of shephard and beall
// points may know the normals to the surface they are classified on
// default values are 0,0,1
#include <set>
#include <map>
#include <list>
#include <math.h>
class BDS_GeomEntity
{
public:
int classif_tag;
int classif_degree;
inline bool operator < ( const BDS_GeomEntity & other ) const
{
if (classif_degree < other.classif_degree)return true;
if (classif_degree > other.classif_degree)return false;
if (classif_tag < other.classif_tag)return true;
return false;
}
BDS_GeomEntity (int a, int b)
: classif_tag (a),classif_degree(b)
{
}
};
class BDS_Edge;
class BDS_Triangle;
class BDS_Mesh;
class BDS_Vector
{
public:
double x,y,z;
BDS_Vector operator + (const BDS_Vector &v)
{
return BDS_Vector (x+v.x,y+v.y,z+v.z);
}
BDS_Vector& operator += (const BDS_Vector &v)
{
x+=v.x;
y+=v.y;
z+=v.z;
return *this;
}
BDS_Vector operator / (const double &v)
{
return BDS_Vector (x/v,y/v,z/v);
}
BDS_Vector operator * (const double &v)
{
return BDS_Vector (x*v,y*v,z*v);
}
BDS_Vector (double ix=0, double iy=0, double iz=0)
// : x(ix),(iy),z(iz)
{
x=ix;
y=iy;
z=iz;
}
};
class BDS_Point
{
public:
int iD;
double X,Y,Z;
BDS_GeomEntity *g;
std::list<BDS_Edge*> edges;
inline bool operator < ( const BDS_Point & other ) const
{
return iD < other.iD;
}
inline void del (BDS_Edge *e)
{
std::list<BDS_Edge*>::iterator it = edges.begin();
std::list<BDS_Edge*>::iterator ite = edges.end();
while(it!=ite)
{
if (*it == e)
{
edges.erase(it);
break;
}
++it;
}
}
void getTriangles (std::list<BDS_Triangle *> &t);
BDS_Point ( int id, double x=0, double y=0, double z=0 )
: iD(id),X(x),Y(y),Z(z),g(0)
{
}
};
class BDS_Edge
{
public:
bool deleted;
BDS_Point *p1,*p2;
BDS_GeomEntity *g;
BDS_Triangle*faces[2];
inline double length () const
{
return sqrt ((p1->X-p2->X)*(p1->X-p2->X)+(p1->Y-p2->Y)*(p1->Y-p2->Y)+(p1->Z-p2->Z)*(p1->Z-p2->Z));
}
inline int numfaces ( ) const
{
if (faces[1]) return 2;
if (faces[0]) return 1;
return 0;
}
inline void addface ( BDS_Triangle *f)
{
if (faces[1])
{
printf("Non Manifold model not done yet\n");
throw 1;
}
if(faces [0])faces[1] = f;
else faces[0] = f;
}
inline bool operator < ( const BDS_Edge & other ) const
{
if (*other.p1 < *p1) return true;
if (*p1 < *other.p1) return false;
if (*other.p2 < *p2) return true;
return false;
}
inline BDS_Triangle * otherFace ( BDS_Triangle *f)
{
if (f == faces[0]) return faces[1];
if (f == faces[1]) return faces[0];
throw;
}
inline void del (BDS_Triangle *t)
{
if (faces[0] == t)
{
faces[0] = faces[1];
}
else if (faces[1]!=t)
{
printf("edge with faces %p %p : cannot delete %p\n",faces[0],faces[1],t);
throw;
}
faces [1] = 0;
}
inline void oppositeof (BDS_Point * oface[2]) const;
BDS_Edge ( BDS_Point *A, BDS_Point *B )
: deleted(false), g(0)
{
faces[0] = faces[1] = 0;
if (*A < *B)
{
p1=A;
p2=B;
}
else
{
p1=B;
p2=A;
}
p1->edges.push_back(this);
p2->edges.push_back(this);
}
};
class BDS_Triangle
{
public:
bool deleted;
int ori_first_edge;
BDS_Edge *e1,*e2,*e3;
BDS_Vector N() const ;
BDS_GeomEntity *g;
inline void getNodes (BDS_Point *n[3]) const
{
if (ori_first_edge == 1)
{
n[0] = e1->p1;
n[1] = e1->p2;
}
else
{
n[0] = e1->p2;
n[1] = e1->p1;
}
if (e2->p1 != n[0] && e2->p1 != n[1])n[2] = e2->p1;
else n[2] = e2->p2;
}
BDS_Triangle ( BDS_Edge *A, BDS_Edge *B, BDS_Edge *C, BDS_Point *first_vertex)
: deleted (false) , e1(A),e2(B),e3(C),g(0)
{
if (first_vertex == A->p1)
ori_first_edge = 1;
else if (first_vertex == A->p2)
ori_first_edge = -1;
else
throw;
e1->addface(this);
e2->addface(this);
e3->addface(this);
}
};
class GeomLessThan
{
public:
bool operator()(const BDS_GeomEntity* ent1, const BDS_GeomEntity* ent2) const
{
return *ent1 < *ent2;
}
};
class PointLessThan
{
public:
bool operator()(const BDS_Point* ent1, const BDS_Point* ent2) const
{
return *ent1 < *ent2;
}
};
class PointLessThanLexicographic
{
public:
static double t;
bool operator()(const BDS_Point* ent1, const BDS_Point* ent2) const
{
if ( ent1->X - ent2->X > t ) return true;
if ( ent1->X - ent2->X < -t ) return false;
if ( ent1->Y - ent2->Y > t ) return true;
if ( ent1->Y - ent2->Y < -t ) return false;
if ( ent1->Z - ent2->Z > t ) return true;
return false;
}
};
class EdgeLessThan
{
public:
bool operator()(const BDS_Edge* ent1, const BDS_Edge* ent2) const
{
return *ent1 < *ent2;
}
};
class BDS_Mesh
{
int MAXPOINTNUMBER;
public:
double Min[3],Max[3],LC;
BDS_Mesh(int _MAXX = 0) : MAXPOINTNUMBER (_MAXX){}
virtual ~BDS_Mesh ();
BDS_Mesh (const BDS_Mesh &other);
std::set<BDS_GeomEntity*,GeomLessThan> geom;
std::set<BDS_Point*,PointLessThan> points;
std::set<BDS_Edge*, EdgeLessThan> edges;
std::set<BDS_Edge*> edges_to_delete;
std::list<BDS_Triangle*> triangles;
BDS_Point * add_point (int num , double x, double y,double z);
BDS_Edge * add_edge (int p1, int p2);
void del_edge (BDS_Edge *e);
BDS_Triangle *add_triangle (int p1, int p2, int p3);
void del_triangle (BDS_Triangle *t);
void add_geom (int degree, int tag);
BDS_Point *find_point (int num);
BDS_Edge *find_edge (int p1, int p2);
BDS_Edge *find_edge (BDS_Point *p1, BDS_Point *p2, BDS_Triangle *t)const;
BDS_GeomEntity *get_geom (int p1, int p2);
bool swap_edge ( BDS_Edge *);
bool collapse_edge ( BDS_Edge *, BDS_Point*);
bool smooth_point ( BDS_Point*);
bool split_edge ( BDS_Edge *, double coord);
void classify ( double angle);
int adapt_mesh(double);
void cleanup();
// io's
bool read_stl ( const char *filename, const double tolerance);
bool read_tri ( const char *filename);
bool read_vrml ( const char *filename);
void save_gmsh_format (const char *filename);
};
void normal_triangle (BDS_Point *p1, BDS_Point *p2, BDS_Point *p3, double c[3]);