Skip to content
Snippets Groups Projects
BDS.h 15.3 KiB
Newer Older
// 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

#ifdef HAVE_ANN_
#include "ANN/ANN.h"
#endif
#include <string>
#include <set>
#include <map>
#include <vector>
#include <list>
#include <math.h>
//#include <algorithm>
class BDS_Edge;
class BDS_Triangle;
class BDS_Mesh;
class BDS_Point;


void vector_triangle (BDS_Point *p1, BDS_Point *p2, BDS_Point *p3, double c[3]); 
void normal_triangle (BDS_Point *p1, BDS_Point *p2, BDS_Point *p3, double c[3]); 
double surface_triangle (BDS_Point *p1, BDS_Point *p2, BDS_Point *p3); 
double quality_triangle  (BDS_Point *p1, BDS_Point *p2, BDS_Point *p3);

class BDS_Metric
{
 public:
  const double target,_min,_max,treshold;
  const double nb_elements_per_radius_of_curvature;
  BDS_Metric ( double _target , double _mmin, double _mmax, double cc, double _tres = 0.7) 
    : target(_target),_min(_mmin),_max(_mmax), treshold(_tres),nb_elements_per_radius_of_curvature(cc)
    {}
  inline double update_target_length( double _target, double old_target_length  ) const
    {
      if (_target <= _min) return _min;
      if (_target >= _max) return _max;
      if (old_target_length > _target)return _target ;
      return old_target_length;

    }
  inline double target_length( double x, double y, double z ) const
    {
      return target;
    }
};


class BDS_Surface
{
public :
    virtual double signedDistanceTo ( double x, double y, double z ) const = 0;
    virtual void projection ( double xa, double ya, double za,
			      double &x, double &y, double &z) const =0;
    virtual std::string nameOf () const = 0;
//    virtual BDS_Vector Gradient ( double x, double y, double z ) const = 0;
    virtual double normalCurv ( double x, double y, double z ) const = 0;
class BDS_GeomEntity
{
public:
  int nbK;
  int classif_tag;
  int classif_degree;
#ifdef HAVE_ANN_
    ANNpointArray           dataPts;                                // data points
    ANNpoint                queryPt;                                // query point
    ANNidxArray             nnIdx;                                  // near neighbor indices
    ANNdistArray            dists;                                  // near neighbor distances
    ANNkd_tree*             kdTree;                                 // search structure
    std::vector<BDS_Edge *> sE;
    std::vector<double> sR;
    std::list<BDS_Triangle *> t;
    std::list<BDS_Edge *>     e;
    BDS_Point   *p;
    BDS_Surface *surf;
    void getClosestTriangles ( double x, double y, double z, 
			  std::list<BDS_Triangle*> &l , double &radius);
    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),p(0),surf(0)
      {
#ifdef HAVE_ANN_
	kdTree = 0;
#endif
      }
    ~BDS_GeomEntity ()  
      {
#ifdef HAVE_ANN_
	if (kdTree)
	  {
	    delete [] nnIdx;                                                    // clean things up
	    delete [] dists;
	    delete kdTree;
	  }
#endif
      }

void print_face (BDS_Triangle *t);
class BDS_Vector
{
public:
  double x,y,z;
  bool operator<(const BDS_Vector &o) const
      {
	  if ( x - o.x  > t  ) return true;
	  if ( x - o.x  < -t ) return false;
	  if ( y - o.y  > t  ) return true;
	  if ( y - o.y  < -t ) return false;
	  if ( z - o.z  > t  ) return true;
	  return false;
      }
  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)
  {
    return BDS_Vector (x-v.x,y-v.y,z-v.z);
  }
  inline BDS_Vector operator % (const BDS_Vector &other) const
      {
	  return BDS_Vector(y*other.z-z*other.y,
			    z*other.x-x*other.z,
			    x*other.y-y*other.x);
      }
  BDS_Vector& operator += (const  BDS_Vector &v)
  {
    x+=v.x;
    y+=v.y;
    z+=v.z;
    return *this;
  }
  BDS_Vector& operator *= (const  double &v)
  {
    x*=v;
    y*=v;
    z*=v;
    return *this;
  }
  BDS_Vector& operator /= (const  double &v)
  {
    x/=v;
    y/=v;
    z/=v;
    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);
  }
  double angle (const  BDS_Vector &v) const
  {
    double a[3] = { x ,  y ,  z };
    double b[3] = { v.x ,  v.y ,  v.z };
    double c[3];
    c[2] = a[0] * b[1] - a[1] * b[0];
    c[1] = -a[0] * b[2] + a[2] * b[0];
    c[0] = a[1] * b[2] - a[2] * b[1];
    double cosa = a[0]*b[0] +a[1]*b[1] +a[2]*b[2];
    double sina = sqrt (c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
    double ag = atan2(sina,cosa);
    return ag;
  }
  double operator * (const  BDS_Vector &v) const
  {
    return (x*v.x+y*v.y+z*v.z);
  }
  BDS_Vector (const BDS_Point &p2,const BDS_Point &p1);

  BDS_Vector (const double X=0., const double Y=0., const double Z=0.)
        : x(X),y(Y),z(Z)
  static double t;
class BDS_Pos
{
 public:
    double X,Y,Z;    
    BDS_Pos(const double &x,const double &y, const double & z)
	: X(x),Y(y),Z(z)
	{
	}
};

class BDS_Point : public BDS_Pos
    double radius_of_curvature;
    BDS_GeomEntity *g;
    std::list<BDS_Edge*> edges;

    BDS_Vector N() const;

    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) const; 	

    void compute_curvature ( );

    BDS_Point ( int id, double x=0, double y=0, double z=0 )
	: BDS_Pos(x,y,z),iD(id),radius_of_curvature(1.e22),g(0)
class BDS_Edge
{
    std::vector <BDS_Triangle *> _faces;
    bool deleted;
    int status;
    int partition;
    double target_length;
    BDS_Point *p1,*p2;
    BDS_GeomEntity *g;
    inline BDS_Triangle* faces(int i) const
	{
	    return _faces [i];
	}

    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 
	{
	    return _faces.size();
    inline BDS_Point * commonvertex ( const BDS_Edge *other ) const
      {
	if (p1 == other->p1 || p1 == other->p2) return p1;
	if (p2 == other->p1 || p2 == other->p2) return p2;
	return 0;
      }

    inline BDS_Point * othervertex ( const BDS_Point *p ) const
      {
	if (p1 == p) return p2;
	if (p2 == p) return p1;
	return 0;
      }

    inline void addface ( BDS_Triangle *f)
	{
	    _faces.push_back(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 ( const BDS_Triangle *f) const
	  if (numfaces()!=2) throw;
	  if (f == _faces[0]) return _faces[1];
	  if (f == _faces[1]) return _faces[0];
	  throw;
    inline void del (BDS_Triangle *t)
	{
	    _faces.erase ( std::remove_if (_faces.begin(),_faces.end() , std::bind2nd(std::equal_to<BDS_Triangle*> (), t)) , 
			   _faces.end () );
	}

    inline void oppositeof (BDS_Point * oface[2]) const; 

    BDS_Edge ( BDS_Point *A, BDS_Point *B )
      : deleted(false), status(0),partition(0),target_length(1.0),g(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 status;
    int partition;
    BDS_Edge *e1,*e2,*e3;
    BDS_Vector NORMAL;
    double surface;
    inline BDS_Vector N() const {return NORMAL;}
    inline double S() const {return surface;}
    BDS_GeomEntity *g;
    inline BDS_Tet * opposite_tet (BDS_Tet *t)
      {
	if (t == t1)return t2;
	if (t == t2)return t1;
	throw;
      }

    inline int numtets ( ) const 
	{
	  return ( (t1!=0) + (t2 !=0) );
	}

    inline BDS_Vector cog() const
	{
	    BDS_Point *n[3];
	    getNodes (n);
	    return BDS_Vector ((n[0]->X+n[1]->X+n[2]->X)/3.,
			       (n[0]->Y+n[1]->Y+n[2]->Y)/3.,
			       (n[0]->Z+n[1]->Z+n[2]->Z)/3.);
	}

    inline void _update ()
      { 
	BDS_Point *pts[3];
	getNodes (pts);
	double c[3];
	vector_triangle (pts[0],pts[1],pts[2],c);
	surface = 0.5 * sqrt(c[0]*c[0]+c[1]*c[1]+c[2]*c[2]);
	NORMAL.x = 2*c[0]/surface;
	NORMAL.y = 2*c[1]/surface;
	NORMAL.z = 2*c[2]/surface;
      }

    inline void getNodes (BDS_Point *n[3]) const
	  n[0] = e1->commonvertex (e3);
	  n[1] = e1->commonvertex (e2);
	  n[2] = e2->commonvertex (e3);

    inline void addtet ( BDS_Tet *t)
	{
	  if (!t1) t1 = t;
	  else if (!t2) t2 = t;
	  else throw;
	}

    inline void del (BDS_Tet *t)
	{
	  if (t == t1) 
	    {
	      t1 = t2;
	      t2 = 0;
	    }
	  else if (t == t2)
	    {
	      t2 = 0;
	    }
	  else
	    throw;
	}

    BDS_Triangle ( BDS_Edge *A, BDS_Edge *B, BDS_Edge *C)
	: deleted (false) , status(0), partition(0),t1(0),t2(0),e1(A),e2(B),e3(C),g(0)
	    e1->addface(this);
	    e2->addface(this);
	    e3->addface(this);
	    _update();
class BDS_Tet
{
public:
    bool deleted;
    int status;
    int partition;
    BDS_Triangle  *f1,*f2,*f3,*f4;
    double volume;
    inline double V() const {return volume;}
    BDS_GeomEntity *g;

    inline BDS_Vector cog() const
	{
	  BDS_Point *n[4];
	  getNodes (n);
	  return BDS_Vector ((n[0]->X+n[1]->X+n[2]->X+n[3]->X)/4.,
			     (n[0]->Y+n[1]->Y+n[2]->Y+n[3]->Y)/4.,
			     (n[0]->Z+n[1]->Z+n[2]->Z+n[3]->Z)/4.);
	}

    inline void _update ()
      { 
      }

    inline void getNodes (BDS_Point *n[4]) const
	{
	  BDS_Point *o[3];
	  f1->getNodes (n);
	  f2->getNodes (o);	  
	  if(o[0] != n[0] && o[0] != n[1] &&o[0] != n[2])n[3] = o[0];
	  if(o[1] != n[0] && o[1] != n[1] &&o[1] != n[2])n[3] = o[1];
	  if(o[2] != n[0] && o[2] != n[1] &&o[2] != n[2])n[3] = o[2];
	}

    BDS_Tet ( BDS_Triangle *A, BDS_Triangle *B, BDS_Triangle *C, BDS_Triangle *D)
	: deleted (false) , status(0), partition(0),f1(A),f2(B),f3(C),f4(D),g(0)
	{	
	    f1->addtet(this);
	    f2->addtet(this);
	    f3->addtet(this);
	    f4->addtet(this);
	    _update();
	}
};


class BDS_Plane : public  BDS_Surface
{
    double a,b,c,d;
    BDS_Plane (const double &A, const double &B, const double &C)
	: a(A),b(B),c(C)
	{
	}
    virtual double signedDistanceTo (  double x, double y, double z ) const {return a*x + b*y + c*z + 1;}
    virtual void projection ( double xa, double ya, double za,
			      double &x, double &y, double &z) const 
	{
	    double k = - ( a * xa +  b * ya +  c * za + 1 ) / ( a * a + b * b + c * c ); 
	    x = xa + k * a;
	    y = ya + k * b;
	    z = za + k * c;
	}
    virtual std::string nameOf () const {return std::string("Plane");}
    virtual BDS_Vector Gradient ( double x, double y, double z ) const
	{
	    return BDS_Vector ( a , b , c );
	} 
    virtual double normalCurv ( double x, double y, double z ) const
	{
class BDS_Quadric : public  BDS_Surface
    double a,b,c,d,e,f,g,h,i;
    BDS_Quadric (double A,double B,double C, double D, double E, double F, double G, double H, double I)
	: a(A),b(B),c(C),d(D),e(E),f(F),g(G),h(H),i(I)
	{
	}

    virtual BDS_Vector Gradient ( double x, double y, double z ) const 
	{
	    return BDS_Vector ( 2* ( a * x + d * y + e * z ) + g ,
				2* ( d * x + b * y + f * z ) + h ,
				2* ( e * x + f * y + c * z ) + i );
	}

    virtual double normalCurv ( double x, double y, double z ) const;

    virtual double signedDistanceTo (  double x, double y, double z ) const {
	const double q = 
	    a * x * x +  
	    b * y * y +  
	    c * z * z +  
	    2 * d * x * y + 
	    2 * e * x * z + 
	    2 * f * y * z +
	    g *  x +
	    h *  y +
	    i *  z - 1.0;
	return q;
    }
    virtual void projection ( double xa, double ya, double za,
			      double &x, double &y, double &z) const ;
    virtual std::string nameOf () const {return std::string("Quadric");}
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
    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
    bool operator()(const BDS_Edge* ent1, const BDS_Edge* ent2) const
	    return *ent1 < *ent2;
class BDS_Mesh 
    int MAXPOINTNUMBER,SNAP_SUCCESS,SNAP_FAILURE;
    
    double Min[3],Max[3],LC;

    void projection ( double &x, double &y, double &z );

    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::list<BDS_Edge*>      edges; 
    std::list<BDS_Triangle*>   triangles; 
    std::list<BDS_Tet*>        tets; 
    BDS_Point * add_point (int num , double x, double y,double z);
    BDS_Edge  * add_edge  (int p1, int p2);
    void del_point  (BDS_Point *p);
    void del_edge  (BDS_Edge *e);
    BDS_Triangle *add_triangle  (int p1, int p2, int p3); 
    BDS_Triangle *add_triangle  (BDS_Edge *e1,BDS_Edge *e2,BDS_Edge *e3);
    BDS_Tet *add_tet  (int p1, int p2, int p3,int p4);
    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_Triangle  *find_triangle (BDS_Edge *e1,BDS_Edge *e2,BDS_Edge *e3);
    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*, const double eps);
    void snap_point   ( BDS_Point* , BDS_Mesh *geom = 0);
    bool smooth_point   ( BDS_Point* , BDS_Mesh *geom = 0);
    bool smooth_point_b ( BDS_Point* );
    bool split_edge ( BDS_Edge *, double coord, BDS_Mesh *geom = 0);
    void classify ( double angle, int nb = -1); 
    void color_plane_surf ( double eps , int nb);
    void reverseEngineerCAD ( ) ;
    void createSearchStructures ( ) ;
    int adapt_mesh(double,bool smooth = false,BDS_Mesh *geom = 0); 
    void compute_metric_edge_lengths (const BDS_Metric & metric);
    void cleanup();
    bool read_stl  ( const char *filename, const double tolerance);
    // INRIA MESH
    bool read_mesh  ( const char *filename);
    bool read_vrml ( const char *filename);
    void save_gmsh_format (const char *filename);
bool project_point_on_a_list_of_triangles ( BDS_Point *p , const std::list<BDS_Triangle*> &t,
					    double &X, double &Y, double &Z);