diff --git a/Common/GmshMatrix.h b/Common/GmshMatrix.h index 4c02c183eca95a8ffabc775e1abf6fff8cb4a164..67c9b0a4a2836ae9cfa017a04be8cb60012d7dce 100644 --- a/Common/GmshMatrix.h +++ b/Common/GmshMatrix.h @@ -109,7 +109,7 @@ public: class GSL_Vector { private: - int r,c; + int r; public: inline int size() const {return r;} gsl_vector *data; diff --git a/Mesh/BDS.cpp b/Mesh/BDS.cpp index 7df60c5e8762bb3b1c236710064796a96f7f3a72..713a30112844521a021ace087092d428c014b4ac 100644 --- a/Mesh/BDS.cpp +++ b/Mesh/BDS.cpp @@ -36,53 +36,6 @@ BDS_Vector BDS_Point::N() const return SumN; } -BDS_Sphere :: BDS_Sphere( BDS_Point *p1, BDS_Point *p2, BDS_Point *p3, BDS_Point *p4) -{ - double mat[3][3], b[3], dum,res[3]; - int i; - double X[4] = {p1->X,p2->X,p3->X,p4->X}; - double Y[4] = {p1->Y,p2->Y,p3->Y,p4->Y}; - double Z[4] = {p1->Z,p2->Z,p3->Z,p4->Z}; - - b[0] = X[1] * X[1] - X[0] * X[0] + - Y[1] * Y[1] - Y[0] * Y[0] + Z[1] * Z[1] - Z[0] * Z[0]; - b[1] = X[2] * X[2] - X[1] * X[1] + - Y[2] * Y[2] - Y[1] * Y[1] + Z[2] * Z[2] - Z[1] * Z[1]; - b[2] = X[3] * X[3] - X[2] * X[2] + - Y[3] * Y[3] - Y[2] * Y[2] + Z[3] * Z[3] - Z[2] * Z[2]; - - for(i = 0; i < 3; i++) - b[i] *= 0.5; - - mat[0][0] = X[1] - X[0]; - mat[0][1] = Y[1] - Y[0]; - mat[0][2] = Z[1] - Z[0]; - mat[1][0] = X[2] - X[1]; - mat[1][1] = Y[2] - Y[1]; - mat[1][2] = Z[2] - Z[1]; - mat[2][0] = X[3] - X[2]; - mat[2][1] = Y[3] - Y[2]; - mat[2][2] = Z[3] - Z[2]; - - -// printf("X = %g %g %g %g\n",X[0],X[1],X[2],X[3]); -// printf("Y = %g %g %g %g\n",Y[0],Y[1],Y[2],Y[3]); -// printf("Z = %g %g %g %g\n",Z[0],Z[1],Z[2],Z[3]); - - if(!sys3x3(mat, b, res, &dum)) { - R = 1.e22; - xc = yc = zc = 1.e33; -// printf("ahrgh\n"); - } - else - { - xc = res[0]; - yc = res[1]; - zc = res[2]; - R = sqrt ((p1->X-xc)*(p1->X-xc)+(p1->Y-yc)*(p1->Y-yc)+(p1->Z-zc)*(p1->Z-zc)); - } -} - double dist_droites_gauches(BDS_Point *p1, BDS_Point *p2, BDS_Point *p3 ,BDS_Point *p4) { @@ -191,21 +144,6 @@ double quality_triangle (BDS_Point *p1, BDS_Point *p2, BDS_Point *p3) return a / (e12+e22+e32); } -BDS_Plane::BDS_Plane (BDS_Point *p1, BDS_Point *p2, BDS_Point *p3) -{ - double mat[3][3]; - mat[0][0] = p1->X; mat[0][1] = p1->Y; mat[0][2] = p1->Z; - mat[1][0] = p2->X; mat[1][1] = p2->Y; mat[1][2] = p2->Z; - mat[2][0] = p3->X; mat[2][1] = p3->Y; mat[2][2] = p3->Z; - double rhs[3] = {-1,-1,-1}; - double pl[3] , det ; - sys3x3 (mat,rhs,pl,&det); - a = pl[0]; - b = pl[1]; - c = pl[2]; -} - - void BDS_Point::getTriangles (std::list<BDS_Triangle *> &t) const { t.clear (); @@ -399,85 +337,155 @@ void BDS_Mesh :: reverseEngineerCAD ( ) { if ((*it)->classif_degree == 2) { - std::set<BDS_Point*,PointLessThan> pts; - + std::set<BDS_Vector> pts; + std::list<BDS_Triangle*>::iterator tit = (*it)->t.begin(); std::list<BDS_Triangle*>::iterator tite = (*it)->t.end(); + BDS_Vector::t = LC/1.e6; while (tit!=tite) { BDS_Point *nod[3]; (*tit)->getNodes (nod); - pts.insert(nod[0]); - pts.insert(nod[1]); - pts.insert(nod[2]); + BDS_Vector p1 = BDS_Vector(nod[0]->X, nod[0]->Y, nod[0]->Z); + BDS_Vector p2 = BDS_Vector(nod[1]->X, nod[1]->Y, nod[1]->Z); + BDS_Vector p3 = BDS_Vector(nod[2]->X, nod[2]->Y, nod[2]->Z); + pts.insert(p1); + pts.insert(p2); + pts.insert(p3); + pts.insert((p1+p2)*0.5); + pts.insert((p1+p3)*0.5); + pts.insert((p2+p3)*0.5); tit++; } + + // We consider the following implicit quadrics surface + // f(x) = x^T A x + b^T x + c = 0 + // A symmetric ( 6 coeffs ), b a vector ( 3 coeffs ) and c a scalar + // 10 coefficients + // we try to fit that using least squares + // we use both points and edges mid points for the fitting + + if(pts.size() > 3) { - // TEST PLANE - { - std::set<BDS_Point*,PointLessThan>::iterator pit = pts.begin(); - std::set<BDS_Point*,PointLessThan>::iterator pite = pts.end(); - - BDS_Point *p1 = *pit;++pit; - BDS_Point *p2 = *pit;++pit; - BDS_Point *p3 = *pit;++pit; - BDS_Plane *plane = new BDS_Plane ( p1 , p2 , p3 ); - double distmax = 0; + // TEST PLANE (easier than quadrics...) + { + Double_Matrix PLANE ( pts.size() , 3 ); + Double_Vector ONES ( pts.size() ); + Double_Vector RSLT ( 3 ); + std::set<BDS_Vector>::iterator pit = pts.begin(); + std::set<BDS_Vector>::iterator pite = pts.end(); + int k=0; while (pit!=pite) { - double dist = plane->signedDistanceTo (*pit); - if (fabs(dist) > distmax) distmax = fabs(dist); + PLANE ( k , 0 ) = (*pit).x; + PLANE ( k , 1 ) = (*pit).y; + PLANE ( k , 2 ) = (*pit).z; + ONES ( k ) = -1; + k++; ++pit; } - if (distmax < 1.e-6 * LC ) + + PLANE.least_squares (ONES, RSLT); +// printf("%d points plane surface %d ?? : %g %g %g\n",pts.size(),(*it)->classif_tag,RSLT(0),RSLT(1),RSLT(2)); + + bool plane = true; + for (int i=0;i<pts.size();i++) { - (*it)->surf = plane; -// printf("plane surface found %g\n",distmax); - pit = pts.begin(); - while (pit!=pite) - { - if ((*pit)->g->classif_degree == 2) - (*pit)->radius_of_curvature = 1.e22; - pit++; - } + const double dist = PLANE ( i , 0 ) * RSLT(0)+PLANE ( i , 1 ) * RSLT(1)+PLANE ( i , 2 ) * RSLT(2)+1; + if (fabs(dist) > 1.e-6 * LC)plane = false; } - else - { -// printf("non plane surface found %g\n",distmax); - delete plane; + + if ( plane ) + { + printf("plane surface %d found : %g %g %g\n",(*it)->classif_tag,RSLT(0),RSLT(1),RSLT(2)); + (*it)->surf = new BDS_Plane (RSLT(0),RSLT(1),RSLT(2)); } } - } - if(pts.size() > 4 && !(*it)->surf) - { - // TEST SPHERE + if (!(*it)->surf && pts.size() > 20) { - std::set<BDS_Point*,PointLessThan>::iterator pit = pts.begin(); - std::set<BDS_Point*,PointLessThan>::iterator pite = pts.end(); - - BDS_Point *p1 = *pit;++pit; - BDS_Point *p2 = *pit;++pit; - BDS_Point *p3 = *pit;++pit; - BDS_Point *p4 = *pit;++pit; - BDS_Sphere *sphere = new BDS_Sphere ( p1 , p2 , p3 , p4); - double distmax = 0; + Double_Matrix QUADRIC ( pts.size() , 9 ); + Double_Vector ONES ( pts.size() ); + Double_Vector RSLT ( 9 ); + std::set<BDS_Vector>::iterator pit = pts.begin(); + std::set<BDS_Vector>::iterator pite = pts.end(); + int k=0; while (pit!=pite) { - double dist = sphere->signedDistanceTo (*pit); - if (fabs(dist) > distmax) distmax = fabs(dist); + QUADRIC ( k , 0 ) = (*pit).x* (*pit).x; + QUADRIC ( k , 1 ) = (*pit).y* (*pit).y; + QUADRIC ( k , 2 ) = (*pit).z* (*pit).z; + QUADRIC ( k , 3 ) = 2*(*pit).x* (*pit).y; + QUADRIC ( k , 4 ) = 2*(*pit).x* (*pit).z; + QUADRIC ( k , 5 ) = 2*(*pit).y* (*pit).z; + QUADRIC ( k , 6 ) = (*pit).x; + QUADRIC ( k , 7 ) = (*pit).y; + QUADRIC ( k , 8 ) = (*pit).z; + ONES ( k ) = 1; + k++; ++pit; } - if (distmax < 1.e-116 * LC ) + QUADRIC.least_squares (ONES, RSLT); + bool quad = true; + for (int i=0;i<pts.size();i++) { - (*it)->surf = sphere; - printf("spherical surface %d found %g (R=%g,LC=%g)\n",(*it)->classif_tag,distmax,sphere->R,LC); - } - else - { -// printf("non spherical surface found %g\n",distmax); - delete sphere; + const double dist = + QUADRIC ( i , 0 ) * RSLT(0) + + QUADRIC ( i , 1 ) * RSLT(1) + + QUADRIC ( i , 2 ) * RSLT(2) + + QUADRIC ( i , 3 ) * RSLT(3) + + QUADRIC ( i , 4 ) * RSLT(4) + + QUADRIC ( i , 5 ) * RSLT(5) + + QUADRIC ( i , 6 ) * RSLT(6) + + QUADRIC ( i , 7 ) * RSLT(7) + + QUADRIC ( i , 8 ) * RSLT(8) - 1; + if (fabs(dist) > 1.e-4 * LC )quad = false; + } + if ( quad ) + { + printf("quadric surface %d found : %g %g %g %g %g %g %g %g %g\n",(*it)->classif_tag, + RSLT(0),RSLT(1),RSLT(2),RSLT(3),RSLT(4),RSLT(5),RSLT(6),RSLT(7),RSLT(8)); + (*it)->surf = new BDS_Quadric ( RSLT(0),RSLT(1),RSLT(2),RSLT(3),RSLT(4),RSLT(5),RSLT(6),RSLT(7),RSLT(8)); + + //test + + FILE *f = fopen ("QUADRIC.pos","w"); + fprintf(f,"View \"quadric\" {\n"); + const int NNN = 20; + for (int I=0;I<NNN;I++) + { + for (int J=0;J<NNN;J++) + { + for (int K=0;K<NNN;K++) + { + double u1 = (double)I/NNN; + double v1 = (double)J/NNN; + double w1 = (double)K/NNN; + double X1 = Min[0] + u1 * (Max[0]-Min[0]); + double Y1 = Min[1] + v1 * (Max[1]-Min[1]); + double Z1 = Min[2] + w1 * (Max[2]-Min[2]); + double u2 = (double)(I+1)/NNN; + double v2 = (double)(J+1)/NNN; + double w2 = (double)(K+1)/NNN; + double X2 = Min[0] + u2 * (Max[0]-Min[0]); + double Y2 = Min[1] + v2 * (Max[1]-Min[1]); + double Z2 = Min[2] + w2 * (Max[2]-Min[2]); + fprintf(f,"SH(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g,%g,%g,%g,%g,%g};\n",X1,Y1,Z1,X2,Y1,Z1,X2,Y2,Z1,X1,Y2,Z1,X1,Y1,Z2,X2,Y1,Z2,X2,Y2,Z2,X1,Y2,Z2, + (*it)->surf->signedDistanceTo (X1,Y1,Z1), + (*it)->surf->signedDistanceTo (X2,Y1,Z1), + (*it)->surf->signedDistanceTo (X2,Y2,Z1), + (*it)->surf->signedDistanceTo (X1,Y2,Z1), + (*it)->surf->signedDistanceTo (X1,Y1,Z2), + (*it)->surf->signedDistanceTo (X2,Y1,Z2), + (*it)->surf->signedDistanceTo (X2,Y2,Z2), + (*it)->surf->signedDistanceTo (X1,Y2,Z2)); + } + } + } + fprintf(f,"};\n"); + fclose(f); } + } } } @@ -799,6 +807,7 @@ void BDS_Mesh :: classify ( double angle ) printf(" end classifying %d edgetags %d vertextags\n",edgetag-1,vertextag-1); } double PointLessThanLexicographic::t = 0; +double BDS_Vector::t = 0; bool BDS_Mesh :: read_stl ( const char *filename , const double tolerance) { diff --git a/Mesh/BDS.h b/Mesh/BDS.h index 97c1a988c98b7ed4ea15d6d0bb8b25edcea36943..7eac5c726d0a40e03f683dec7121596ce9c3720e 100644 --- a/Mesh/BDS.h +++ b/Mesh/BDS.h @@ -3,6 +3,7 @@ // points may know the normals to the surface they are classified on // default values are 0,0,1 +#include <string> #include <set> #include <map> #include <vector> @@ -18,9 +19,10 @@ class BDS_Point; class BDS_Surface { public : - virtual double signedDistanceTo ( BDS_Point * ) const = 0; + 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; }; @@ -55,6 +57,15 @@ 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); @@ -113,21 +124,29 @@ public: } BDS_Vector (const BDS_Point &p2,const BDS_Point &p1); - BDS_Vector (double ix=0, double iy=0, double iz=0) - // : x(ix),(iy),z(iz) + BDS_Vector (const double X=0., const double Y=0., const double Z=0.) + : x(X),y(Y),z(Z) { - x=ix; - y=iy; - z=iz; } + static double t; }; -class BDS_Point +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 { public: int iD; - double X,Y,Z,radius_of_curvature; + double radius_of_curvature; BDS_GeomEntity *g; std::list<BDS_Edge*> edges; @@ -156,7 +175,7 @@ public: void compute_curvature ( ); BDS_Point ( int id, double x=0, double y=0, double z=0 ) - : iD(id),X(x),Y(y),Z(z),radius_of_curvature(1.e22),g(0) + : BDS_Pos(x,y,z),iD(id),radius_of_curvature(1.e22),g(0) { } }; @@ -276,8 +295,11 @@ class BDS_Plane : public BDS_Surface { double a,b,c; public : - BDS_Plane (BDS_Point *p1, BDS_Point *p2, BDS_Point *p3); - virtual double signedDistanceTo ( BDS_Point * p) const {return a*p->X + b*p->Y + c*p->Z + 1;} + 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 { @@ -286,26 +308,41 @@ public : y = ya + k * b; z = za + k * c; } + virtual std::string nameOf () const {return std::string("Plane");} + }; -class BDS_Sphere : public BDS_Surface +class BDS_Quadric : public BDS_Surface { public : - double xc,yc,zc,R; - BDS_Sphere (BDS_Point *p1, BDS_Point *p2, BDS_Point *p3, BDS_Point *p4); - virtual double signedDistanceTo ( BDS_Point * p) const { - return sqrt((p->X-xc)*(p->X-xc)+ - (p->Y-yc)*(p->Y-yc)+ - (p->Z-zc)*(p->Z-zc)) - R; + 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 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 { - double k = ( R * R )/((xa-xc)*(xa-xc)+(ya-yc)*(ya-yc)+(za-zc)*(za-zc)) ; - x = xc + k * (xa-xc); - y = yc + k * (ya-yc); - z = zc + k * (za-zc); + // not done yet + // this is not as simple as for the plane + // you shoud have min (signedDistance), this can + // be done using the GSL... 2 BE DONE !!!!! + throw; } + virtual std::string nameOf () const {return std::string("Quadric");} };